我在使用Keras微调Inception模型时遇到了问题。
我通过教程和文档成功地生成了一个全连接顶层模型,使用Inception的瓶颈特征将我的数据集分类到相应的类别中,准确率超过99%。
import numpy as npfrom keras.preprocessing.image import ImageDataGeneratorfrom keras.models import Sequentialfrom keras.layers import Dropout, Flatten, Densefrom keras import applications# 我们的图像的尺寸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' #训练相关的参数?inclusive_images = 1424nb_train_samples = 1424nb_validation_samples = 1424epochs = 50batch_size = 16def save_bottlebeck_features(): datagen = ImageDataGenerator(rescale=1. / 255) # 构建瓶颈特征 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()
第50/50个周期 1424/1424 [==============================] – 17s 12ms/step – loss: 0.0398 – acc: 0.9909
我还能够将这个模型堆叠在Inception之上,创建我的完整模型,并使用该完整模型成功地对训练集进行分类。
from keras import Modelfrom keras import optimizersfrom keras.callbacks import EarlyStoppingimg_width, img_height = 150, 150top_model_weights_path = 'Inception_fc_model_v0.h5'train_data_dir = '../data/train2'validation_data_dir = '../data/train2' #我们有多少包含的例子?inclusive_images = 1424nb_train_samples = 1424nb_validation_samples = 1424epochs = 50batch_size = 16# 构建完整的网络以进行评估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)#合并基础和顶层模型fullModel = Model(input= base_model.input, output= top_model(base_model.output))#使用完整的训练数据集进行预测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))
对这个完整模型处理结果的检查与使用瓶颈生成的全连接模型的准确率相匹配。
import matplotlib.pyplot as pltimport operator#从结果中检索基于softmax的类别分配resultMaxClassIDs = [ max(enumerate(result), key=operator.itemgetter(1))[0] for result in results]#resultMaxClassIDs应该等于range(inclusive_images),所以我们减去这两个并绘制绝对值的对数#寻找指示值不相等的尖峰plt.plot([np.log(np.abs(x)+10) for x in (np.array(resultMaxClassIDs) - np.array(range(inclusive_images)))])
问题在这里:当我尝试训练这个完整模型时,准确率下降到0,尽管验证集的准确率仍然保持在99%以上。
model2 = fullModelfor layer in model2.layers[:-2]: layer.trainable = False# 使用SGD/动量优化器编译模型# 并使用非常慢的学习率。#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)]# 微调模型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)
第1/50个周期 89/89 [==============================] – 388s 4s/step – loss: 13.5787 – acc: 0.0000e+00 – val_loss: 0.0353 – val_acc: 0.9937
随着进展情况变得更糟
第21/50个周期 89/89 [==============================] – 372s 4s/step – loss: 7.3850 – acc: 0.0035 – val_loss: 0.5813 – val_acc: 0.8272
我唯一能想到的是,在最后一次训练中,训练标签可能被错误分配,但我之前使用类似的代码和VGG16成功地完成了这个任务。
我已经仔细检查了代码,试图找出为什么一个模型在99%的时间里做出准确预测,但在微调过程中训练准确率下降而保持验证准确率的原因,但我无法找出答案。任何帮助都将不胜感激。
关于代码和环境的信息:
以下是一些可能会显得奇怪,但确实是故意这样设置的项目:
- 每个类别只有一张图像。这个神经网络旨在对环境和方向条件受到控制的对象进行分类。每种类别只有一个可接受的图像,对应于正确的环境和旋转情况。
- 测试集和验证集是相同的。这个神经网络仅设计用于它正在训练的类别。它将处理的图像将是类别示例的完全复制。我的意图是使模型过度拟合这些类别。
我正在使用:
- Windows 10
- Python 3.5.6 在Anaconda客户端1.6.14下
- Keras 2.2.2
- TensorFlow 1.10.0 作为后端
- CUDA 9.0
- CuDNN 8.0
我已经查看了以下内容:
- Keras accuracy discrepancy in fine-tuned model
- VGG16 Keras fine tuning: low accuracy
- Keras: model accuracy drops after reaching 99 percent accuracy and loss 0.01
- Keras inception v3 retraining and finetuning error
- How to find which version of TensorFlow is installed in my system?
但它们似乎与我的问题无关。
回答: