From df805e32ef7c72b4cb32f740bc655ce37aaed35d Mon Sep 17 00:00:00 2001 From: wassname Date: Sat, 4 Nov 2017 22:28:04 +0800 Subject: [PATCH] update example --- examples/pascal_voc_jaccard_loss.py | 129 +++++++++++++++++++--------- 1 file changed, 87 insertions(+), 42 deletions(-) diff --git a/examples/pascal_voc_jaccard_loss.py b/examples/pascal_voc_jaccard_loss.py index c561009..f670710 100644 --- a/examples/pascal_voc_jaccard_loss.py +++ b/examples/pascal_voc_jaccard_loss.py @@ -1,83 +1,128 @@ ''' -Trains a DenseNet-40-12 model on the CIFAR-10 Dataset. +Trains a DenseNet-40-12 model on a reduced Pascal VOC segmentation dataset. -Gets a 94.84% accuracy score after 100 epochs. +Gets a 70% accuracy score after 100 epochs. ''' from __future__ import absolute_import from __future__ import print_function from __future__ import division import numpy as np +import os from keras import backend as K +from keras.utils.np_utils import to_categorical from keras.callbacks import ModelCheckpoint, ReduceLROnPlateau, EarlyStopping -from keras.datasets import pascal_voc from keras.optimizers import Adam from keras.preprocessing.image import ImageDataGenerator from keras.utils import np_utils -from keras_contrib.applications import DenseNet +from keras.losses import categorical_crossentropy +from keras_contrib.losses.jaccard import jaccard_distance +from keras_contrib.datasets import pascal_voc +from keras_contrib.applications.densenet import DenseNetFCN batch_size = 64 -nb_classes = 10 +nb_classes = 21 epochs = 100 img_rows, img_cols = 32, 32 img_channels = 3 # Parameters for the DenseNet model builder -img_dim = (img_channels, img_rows, img_cols) if K.image_data_format() == 'channels_first' else (img_rows, img_cols, img_channels) +img_dim = (img_channels, img_rows, + img_cols) if K.image_data_format() == 'channels_first' else ( + img_rows, img_cols, img_channels) depth = 40 nb_dense_block = 3 growth_rate = 12 nb_filter = 16 dropout_rate = 0.0 # 0.0 for data augmentation -# Create the model (without loading weights) -model = DenseNet(depth=depth, nb_dense_block=nb_dense_block, - growth_rate=growth_rate, nb_filter=nb_filter, - dropout_rate=dropout_rate, - input_shape=img_dim, - weights=None) -print('Model created') +conf = pascal_voc.voc_config() +pascal_folder = os.path.join(conf['pascal_berkeley_root'], 'dataset') +# download dataset.. about an hour but you only need to do it once +if not os.path.isdir(pascal_folder): + pascal_voc.data_pascal_voc.run() + +# load the data using dual imagedata generators +# we create two instances with the same arguments +data_gen_args = dict() +image_datagen = ImageDataGenerator(**data_gen_args) +mask_datagen = ImageDataGenerator(**data_gen_args) + +# Provide the same seed and keyword arguments to the fit and flow methods +seed = 1 +image_generator = image_datagen.flow_from_directory( + pascal_folder, + target_size=(img_rows, img_cols), + class_mode=None, + classes=["img"], + seed=seed) +mask_generator = image_datagen.flow_from_directory( + pascal_folder, + target_size=(img_rows, img_cols), + class_mode=None, + classes=["cls_png"], + seed=seed) + + +def transform(gen_x, gen_y): + """Combine two generatorsand one-hot transform the labels.""" + while True: + x_batch = next(gen_x) / 255.0 + y_batch = next(gen_y) + y_batch = to_categorical( + y_batch[:, :, :, 0], + num_classes=nb_classes).reshape(y_batch.shape[:3] + (nb_classes, )) + yield x_batch, y_batch + +train_generator = transform(image_generator, mask_generator) + +# Create the model +model = DenseNetFCN( + # depth=depth, + nb_dense_block=nb_dense_block, + growth_rate=growth_rate, + # nb_filter=nb_filter, + dropout_rate=dropout_rate, + input_shape=img_dim, + classes=nb_classes +) +print('Model created') model.summary() optimizer = Adam(lr=1e-3) # Using Adam instead of SGD to speed up training -model.compile(loss='categorical_crossentropy', optimizer=optimizer, metrics=['acc']) +model.compile( + loss=jaccard_distance, + optimizer=optimizer, + metrics=['acc', categorical_crossentropy]) print('Finished compiling') -(trainX, trainY), (testX, testY) = pascal_voc.load_data() +weights_file = 'DenseNet-40-12-PASCAL-10.h5' -trainX = trainX.astype('float32') -testX = testX.astype('float32') - -trainX /= 255. -testX /= 255. - -Y_train = np_utils.to_categorical(trainY, nb_classes) -Y_test = np_utils.to_categorical(testY, nb_classes) - -generator = ImageDataGenerator(rotation_range=15, - width_shift_range=5. / 32, - height_shift_range=5. / 32) - -generator.fit(trainX, seed=0) - -weights_file = 'DenseNet-40-12-CIFAR-10.h5' - -lr_reducer = ReduceLROnPlateau(monitor='val_loss', factor=np.sqrt(0.1), - cooldown=0, patience=10, min_lr=0.5e-6) +# setup some callbacks +lr_reducer = ReduceLROnPlateau( + monitor='val_loss', + factor=np.sqrt(0.1), + cooldown=0, + patience=10, + min_lr=0.5e-6) early_stopper = EarlyStopping(monitor='val_acc', min_delta=1e-4, patience=20) -model_checkpoint = ModelCheckpoint(weights_file, monitor='val_acc', save_best_only=True, - save_weights_only=True, mode='auto') - +model_checkpoint = ModelCheckpoint( + weights_file, + monitor='val_acc', + save_best_only=True, + save_weights_only=True, + mode='auto') callbacks = [lr_reducer, early_stopper, model_checkpoint] -model.fit_generator(generator.flow(trainX, Y_train, batch_size=batch_size), steps_per_epoch=len(trainX) // batch_size, - epochs=epochs, - callbacks=callbacks, - validation_data=(testX, Y_test), - verbose=2) +model.fit_generator( + train_generator, + steps_per_epoch=image_generator.n // batch_size, + epochs=epochs, + callbacks=callbacks, + verbose=2) scores = model.evaluate(testX, Y_test, batch_size=batch_size) print('Test loss : ', scores[0])