因此,我一直试图微调一个VGG16,以便对我创建的包含4个类的数据集进行分类,但是尽管训练和验证集的准确性都有很好的提高,但是无论我做了什么,测试的准确率总是会达到25%。我决定首先微调来自Kaggle的猫狗数据集上的VGG16,我遵循了不同的教程,得到了很好的精确结果。然而,这也是我第一次面对的问题。现在的准确率是50% (因为它是2级)。我开始认为这是一个Keras VGG16问题。我在网上尝试了所有不同的建议,包括类似的问题,堆叠溢出,但似乎没有任何效果。所有的预处理,增强和层冻结似乎是适当的,经过几个星期的错误试验后,我发现自己不得不求助于你的建议/建议的问题。
这是我使用的全部代码:
from keras.models import Sequential, Model, load_model
from keras import applications
from keras import optimizers
from keras.layers import Dropout, Flatten, Dense
from keras.preprocessing.image import ImageDataGenerator
from sklearn.metrics import classification_report,confusion_matrix
from keras.callbacks import ModelCheckpoint
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np接下来是我使用的混淆矩阵函数实现。
def plot_confusion_matrix_two(cm,
target_names,
title='Confusion matrix',
cmap=None,
normalize=True):
import matplotlib.pyplot as plt
import numpy as np
import itertools
accuracy = np.trace(cm) / float(np.sum(cm))
misclass = 1 - accuracy
if cmap is None:
cmap = plt.get_cmap('Blues')
plt.figure(figsize=(8, 6))
plt.imshow(cm, interpolation='nearest', cmap=cmap)
plt.title(title)
plt.colorbar()
if target_names is not None:
tick_marks = np.arange(len(target_names))
plt.xticks(tick_marks, target_names, rotation=45)
plt.yticks(tick_marks, target_names)
if normalize:
cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]
thresh = cm.max() / 1.5 if normalize else cm.max() / 2
for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
if normalize:
plt.text(j, i, "{:0.4f}".format(cm[i, j]),
horizontalalignment="center",
color="white" if cm[i, j] > thresh else "black")
else:
plt.text(j, i, "{:,}".format(cm[i, j]),
horizontalalignment="center",
color="white" if cm[i, j] > thresh else "black")
plt.tight_layout()
plt.ylabel('True label')
plt.xlabel('Predicted label\naccuracy={:0.4f}; misclass={:0.4f}'.format(accuracy, misclass))
plt.show()使用imagenet权重并没有顶层+冻结低层调用VGG16
img_rows, img_cols, img_channel = 224, 224, 3
base_model = applications.VGG16(weights='imagenet', include_top=False, input_shape=(img_rows, img_cols, img_channel))
for layer in base_model.layers[:-4]:
layer.trainable = False
# check the trainable status of the individual layers
for layer in base_model.layers:
print(layer, layer.trainable)添加用于对数据进行分类和编译模型的最后一层:
add_model = Sequential()
add_model.add(Flatten(input_shape=base_model.output_shape[1:]))
add_model.add(Dense(256, activation='relu'))
add_model.add(Dropout(0.5))
add_model.add(Dense(2, activation='softmax'))
for layer in add_model.layers[:-3]:
layer.trainable = False
model = Model(inputs=base_model.input, outputs=add_model(base_model.output))
model.compile(loss='categorical_crossentropy', optimizer=optimizers.SGD(lr=1e-4, momentum=0.9),
metrics=['accuracy'])
model.summary()训练参数,路径等..。
image_size = 224
epochs = 500
train_batch = 50
valid_batch = 30
test_batch = 20
train_dir = 'D:/PetImages/train'
valid_dir = 'D:/PetImages/valid'
test_dir = 'D:/PetImages/test'用于从不同集合读取的数据生成器。这些集合在单独的文件夹中,所以不需要分割列车,在我的情况下也是有效的。
train_datagen = ImageDataGenerator(
rescale=1./255,
rotation_range=20,
width_shift_range=0.2,
height_shift_range=0.2,
horizontal_flip=True,
#vertical_flip=True,
fill_mode='nearest')
validation_datagen = ImageDataGenerator(rescale=1./255)
test_datagen = ImageDataGenerator(rescale=1./255)
train_generator = train_datagen.flow_from_directory(
train_dir,
target_size=(image_size, image_size),
batch_size=train_batch,
class_mode='categorical',
shuffle=True)
validation_generator = validation_datagen.flow_from_directory(
valid_dir,
target_size=(image_size, image_size),
batch_size=valid_batch,
class_mode='categorical',
shuffle=True)
test_generator = test_datagen.flow_from_directory(
test_dir,
target_size=(image_size, image_size),
batch_size=test_batch,
class_mode='categorical',
shuffle=True)培训模式:
history = model.fit_generator(
train_generator,
steps_per_epoch=train_generator.samples // train_generator.batch_size,
epochs=epochs,
validation_data=validation_generator,
validation_steps=validation_generator.samples // validation_generator.batch_size,
#callbacks=[ModelCheckpoint('VGG16-transferlearning.model', monitor='val_acc', save_best_only=True)]
verbose=1
)然后在测试集上进行预测,并与地面真实值进行比较,得到精度等:
predictions = model.predict_generator(test_generator, steps=test_generator.samples//test_generator.batch_size,
verbose=0)
#Confution Matrix and Classification Report
predictions = np.argmax(predictions, axis=1)
print('Confusion Matrix')
cm = confusion_matrix(test_generator.classes, predictions)
#print(cm)
target_names =['cats', 'dogs']
#target_names =['Bark', 'Jump','Stand', 'Walk']
plot_confusion_matrix_two(cm, target_names, title='Confusion Matrix',cmap=None,normalize=False)
print('Classification Report')
print(classification_report(test_generator.classes, predictions, target_names=target_names))
print('Confusion Matrix')
print(cm)我真的试过各种不同的方法来检查。我甚至试着检查模型对训练数据本身是如何做的,而不是测试数据,它仍然给出了50%的结果(考虑到训练的准确率几乎达到99%,这是非常奇怪的)。我试着调优超参数,不同的算法,但仍然没有改变。
系统: Windows 10,Anaconda,Keras 2.1.1 Tensorflow-gpu 1.4.0 Python 3.6.4
使用的数据集:https://files.fm/u/t6zdskc7
我已经被困了几个星期了,这真的很令人沮丧。如果有人能帮助我,我将永远感激!
编辑:
因此,在询问之后,有人向我指出,这个模型实际上正在学习,我可以使用下面的代码来检查预测的准确性:
x, y = zip(*(test_generator[i] for i in range(len(test_generator))))
x_test, y_test = np.vstack(x), np.vstack(y)
loss, acc = model.evaluate(x_test, y_test, batch_size=64)
print("Accuracy: ", acc)
print("Loss: ",loss)结果,我确实得到了一个有意义的实际值(大约70%取决于超参数的优化)。因此,我现在的猜测是,当我尝试使用confusion_matrix和report函数进行分析时,会出现一些问题。不过,我还是找不到问题。
发布于 2018-09-17 14:56:57
对我创建的包含4个类的数据集进行分类
首先,对于4类分类问题,您的网络配置似乎很奇怪(至少可以说);第一个建议是:
loss='categorical_crossentropy'add_model.add(Dense(4, activation='softmax'))因为,由于你的predictions = np.argmax(predictions, axis=1)行,我想你已经使用了一个热编码标签.
发布于 2018-09-19 06:34:01
outputs=add_model(base_model.output))模型=(inputs=base_model.input,您未能正确添加新层)。只需使用functional。
out = base_model.output
out = Flatten()(out)
out = Dense(256, activation='relu')(out)
out = Dropout(0.5)(out)
out = Dense(2, activation='softmax')(out)
for layer in add_model.layers[:-3]:
layer.trainable = False
model = Model(inputs=base_model.input, outputs=out)https://stackoverflow.com/questions/52370361
复制相似问题