Keras: la precisión disminuye mientras se inicia la puesta a punto

Tengo problemas para ajustar un modelo Inception con Keras.

Logré usar tutoriales y documentación para generar un modelo de capas superiores completamente conectadas que clasifique mi conjunto de datos en sus categorías apropiadas con una precisión de más del 99% usando las funciones de cuello de botella desde el inicio.

import numpy as np from keras.preprocessing.image import ImageDataGenerator from keras.models import Sequential from keras.layers import Dropout, Flatten, Dense from keras import applications # dimensions of our images. img_width, img_height = 150, 150 #paths for saving weights and finding datasets top_model_weights_path = 'Inception_fc_model_v0.h5' train_data_dir = '../data/train2' validation_data_dir = '../data/train2' #training related parameters? inclusive_images = 1424 nb_train_samples = 1424 nb_validation_samples = 1424 epochs = 50 batch_size = 16 def save_bottlebeck_features(): datagen = ImageDataGenerator(rescale=1. / 255) # build bottleneck features model = applications.inception_v3.InceptionV3(include_top=False, weights='imagenet', input_shape=(img_width,img_height,3)) generator = datagen.flow_from_directory( train_data_dir, target_size=(img_width, img_height), batch_size=batch_size, class_mode='categorical', shuffle=False) bottleneck_features_train = model.predict_generator( generator, nb_train_samples // batch_size) np.save('bottleneck_features_train', bottleneck_features_train) generator = datagen.flow_from_directory( validation_data_dir, target_size=(img_width, img_height), batch_size=batch_size, class_mode='categorical', shuffle=False) bottleneck_features_validation = model.predict_generator( generator, nb_validation_samples // batch_size) np.save('bottleneck_features_validation', bottleneck_features_validation) def train_top_model(): train_data = np.load('bottleneck_features_train.npy') train_labels = np.array(range(inclusive_images)) validation_data = np.load('bottleneck_features_validation.npy') validation_labels = np.array(range(inclusive_images)) print('base size ', train_data.shape[1:]) model = Sequential() model.add(Flatten(input_shape=train_data.shape[1:])) model.add(Dense(1000, activation='relu')) model.add(Dense(inclusive_images, activation='softmax')) model.compile(loss='sparse_categorical_crossentropy', optimizer='Adam', metrics=['accuracy']) proceed = True #model.load_weights(top_model_weights_path) while proceed: history = model.fit(train_data, train_labels, epochs=epochs, batch_size=batch_size)#, #validation_data=(validation_data, validation_labels), verbose=1) if history.history['acc'][-1] > .99: proceed = False model.save_weights(top_model_weights_path) save_bottlebeck_features() train_top_model() 

Época 50/50 1424/1424 [==============================] – 17s 12ms / step – pérdida: 0.0398 – acc : 0.9909

También he podido astackr este modelo sobre el principio para crear mi modelo completo y usar ese modelo completo para clasificar con éxito mi conjunto de entrenamiento.

 from keras import Model from keras import optimizers from keras.callbacks import EarlyStopping img_width, img_height = 150, 150 top_model_weights_path = 'Inception_fc_model_v0.h5' train_data_dir = '../data/train2' validation_data_dir = '../data/train2' #how many inclusive examples do we have? inclusive_images = 1424 nb_train_samples = 1424 nb_validation_samples = 1424 epochs = 50 batch_size = 16 # build the complete network for evaluation base_model = applications.inception_v3.InceptionV3(weights='imagenet', include_top=False, input_shape=(img_width,img_height,3)) top_model = Sequential() top_model.add(Flatten(input_shape=base_model.output_shape[1:])) top_model.add(Dense(1000, activation='relu')) top_model.add(Dense(inclusive_images, activation='softmax')) top_model.load_weights(top_model_weights_path) #combine base and top model fullModel = Model(input= base_model.input, output= top_model(base_model.output)) #predict with the full training dataset results = fullModel.predict_generator(ImageDataGenerator(rescale=1. / 255).flow_from_directory( train_data_dir, target_size=(img_width, img_height), batch_size=batch_size, class_mode='categorical', shuffle=False)) 

La inspección de los resultados del procesamiento en este modelo completo coincide con la precisión del modelo totalmente conectado generado cuello de botella.

 import matplotlib.pyplot as plt import operator #retrieve what the softmax based class assignments would be from results resultMaxClassIDs = [ max(enumerate(result), key=operator.itemgetter(1))[0] for result in results] #resultMaxClassIDs should be equal to range(inclusive_images) so we subtract the two and plot the log of the absolute value #looking for spikes that indicate the values aren't equal plt.plot([np.log(np.abs(x)+10) for x in (np.array(resultMaxClassIDs) - np.array(range(inclusive_images)))]) 

resultados: los picos son errores de clasificación

Aquí está el problema: cuando tomo este modelo completo e bash entrenarlo, la precisión cae a 0, aunque la validación permanece por encima del 99%.

 model2 = fullModel for layer in model2.layers[:-2]: layer.trainable = False # compile the model with a SGD/momentum optimizer # and a very slow learning rate. #model.compile(loss='binary_crossentropy', optimizer=optimizers.SGD(lr=1e-4, momentum=0.9), metrics=['accuracy']) model2.compile(loss='categorical_crossentropy', optimizer=optimizers.SGD(lr=1e-4, momentum=0.9), metrics=['accuracy']) train_datagen = ImageDataGenerator(rescale=1. / 255) test_datagen = ImageDataGenerator(rescale=1. / 255) train_generator = train_datagen.flow_from_directory( train_data_dir, target_size=(img_height, img_width), batch_size=batch_size, class_mode='categorical') validation_generator = test_datagen.flow_from_directory( validation_data_dir, target_size=(img_height, img_width), batch_size=batch_size, class_mode='categorical') callback = [EarlyStopping(monitor='acc', min_delta=0, patience=3, verbose=0, mode='auto', baseline=None)] # fine-tune the model model2.fit_generator( #train_generator, validation_generator, steps_per_epoch=nb_train_samples//batch_size, validation_steps = nb_validation_samples//batch_size, epochs=epochs, validation_data=validation_generator) 

Época 1/50 89/89 [===============================] – 388s 4s / step – pérdida: 13.5787 – acc : 0.0000e + 00 – val_loss: 0.0353 – val_acc: 0.9937

y empeora a medida que las cosas progresan.

Época 21/50 89/89 [===============================] – 372s 4s / step – pérdida: 7.3850 – acc : 0.0035 – val_loss: 0.5813 – val_acc: 0.8272

Lo único en lo que pude pensar es que de alguna manera las tags de entrenamiento se asignan incorrectamente en este último tren, pero lo he hecho con éxito con un código similar utilizando VGG16 anteriormente.

He buscado en el código tratando de encontrar una discrepancia para explicar por qué un modelo que realiza predicciones precisas más del 99% del tiempo disminuye su precisión de entrenamiento mientras mantiene la precisión de validación durante el ajuste fino, pero no puedo entenderlo. Cualquier ayuda sería apreciada.

Información sobre el código y el entorno:

Las cosas que van a excel como extrañas, pero están destinadas a ser así:

  • Solo hay 1 imagen por clase. Este NN está destinado a clasificar objetos cuyas condiciones ambientales y de orientación están controladas. Solo hay una imagen aceptable para cada clase correspondiente a la situación ambiental y de rotación correcta.
  • El conjunto de prueba y validación son los mismos. Esta NN solo está diseñada para usarse en las clases en las que se está capacitando. Las imágenes que procesará serán copias al carbón de los ejemplos de la clase. Tengo la intención de adaptar el modelo a estas clases.

Estoy usando:

  • Windows 10
  • Python 3.5.6 bajo el cliente Anaconda 1.6.14
  • Keras 2.2.2
  • Tensorflow 1.10.0 como el backend
  • CUDA 9.0
  • CuDNN 8.0

He comprobado:

  1. Discrepancia de precisión de Keras en el modelo ajustado
  2. VGG16 Keras ajuste fino: baja precisión
  3. Keras: la precisión del modelo disminuye después de alcanzar el 99% de precisión y la pérdida 0.01
  4. Keras inicio v3 reentrenamiento y error de ajuste
  5. ¿Cómo encontrar qué versión de TensorFlow está instalada en mi sistema?

pero aparecen sin relación.

Nota: debido a que su problema es un poco extraño y difícil de depurar sin tener su modelo y conjunto de datos entrenados, esta respuesta es solo una (la mejor) estimación después de considerar muchas cosas que pueden salir mal. Por favor envíe sus comentarios y eliminaré esta respuesta si no funciona.

Dado que el BatchNormalization contiene capas BatchNormalization , tal vez el problema se deba al comportamiento (de alguna manera ambiguo o inesperado) de esta capa cuando establece un parámetro trainable en False ( 1 , 2 , 3 , 4 ).

Ahora, veamos si esta es la raíz del problema: como lo sugiere @fchollet , establezca la fase de aprendizaje al definir el modelo para el ajuste fino:

 from keras import backend as K K.set_learning_phase(0) base_model = applications.inception_v3.InceptionV3(weights='imagenet', include_top=False, input_shape=(img_width,img_height,3)) for layer in base_model.layers: layer.trainable = False K.set_learning_phase(1) top_model = Sequential() top_model.add(Flatten(input_shape=base_model.output_shape[1:])) top_model.add(Dense(1000, activation='relu')) top_model.add(Dense(inclusive_images, activation='softmax')) top_model.load_weights(top_model_weights_path) #combine base and top model fullModel = Model(input= base_model.input, output= top_model(base_model.output)) fullModel.compile(loss='categorical_crossentropy', optimizer=optimizers.SGD(lr=1e-4, momentum=0.9), metrics=['accuracy']) ##################################################################### # Here, define the generators and then fit the model same as before # ##################################################################### 

Nota al top_model(base_model.output) : Esto no causa ningún problema en su caso, pero tenga en cuenta que cuando usa top_model(base_model.output) todo el modelo secuencial (es decir, top_model ) se almacena como una capa de fullModel . Puede verificar esto usando fullModel.summary() o print(fullModel.layers[-1]) . De ahí que cuando usaste:

 for layer in model2.layers[:-2]: layer.trainable = False 

En realidad, tampoco estás congelando la última capa de base_model . Sin embargo, dado que es una capa de Concatenate y, por lo tanto, no tiene parámetros entrenables, no se produce ningún problema y se comportaría como usted quería.

Al igual que en la respuesta anterior, intentaré compartir algunos pensamientos para ver si ayuda.

Hay un par de cosas que llamaron mi atención (y tal vez vale la pena revisarlas). Nota: algunos de ellos también deberían haberle dado problemas con los modelos separados.

  • Corregir si estoy equivocado, pero parece que sparse_categorical_crossentropy para el primer entrenamiento mientras que sparse_categorical_crossentropy categorical_crossentropy para el segundo. ¿Es correcto? Porque creo que asumen las tags de manera diferente (sparse asume enteros y el otro asume uno-hot).
  • ¿Ha intentado establecer las capas que agregó al final como trainable = True ? Sé que ya has configurado a los demás en trainable = False , pero tal vez eso también valga la pena.
  • Parece que el generador de datos no está haciendo uso de la función de preprocesamiento predeterminada utilizada en Inception v3, que utiliza un canal por media.
  • ¿Has probado algún experimento utilizando Functional en lugar de API secuencial?

Espero que eso ayude.