所以,我一直在试图微调一个VGG16为了一个数据集我做它有4类进行分类,但同时在训练和验证集的准确性增加好,测试总是导致25%的准确率,无论我做什么。我决定通过微调第一次启动的猫一狗VGG16从数据集和Kaggle我也跟着,进行了良好的精度结果不同的教程。但是,这是我遇到的第一次同样的问题。现在,精度为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()
主叫VGG16与imagenet重量和无顶层+冻结低层
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,蟒蛇,硬GPU Tensorflow 2.1.1 1.4.0 3.6.4的Python
数据集用于: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和报告功能来分析。我仍然无法找到,虽然这个问题。
到我做了一个数据集,其具有4类分类
对于初学者来说,你的网络配置似乎很奇怪的一个4级分类问题(至少可以这样说);第一个建议:
loss='categorical_crossentropy'
add_model.add(Dense(4, activation='softmax'))
因为,由于你的predictions = np.argmax(predictions, axis=1)
行,我假设你已经在使用一个热经编码标签...
模型=模型(输入= base_model.input,输出= add_model(base_model.output))你未能正确添加新层。只需使用功能的API。
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)