首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >vgg16微调狗猫测试数据失败

vgg16微调狗猫测试数据失败
EN

Stack Overflow用户
提问于 2018-09-17 14:46:36
回答 2查看 490关注 0票数 0

因此,我一直试图微调一个VGG16,以便对我创建的包含4个类的数据集进行分类,但是尽管训练和验证集的准确性都有很好的提高,但是无论我做了什么,测试的准确率总是会达到25%。我决定首先微调来自Kaggle的猫狗数据集上的VGG16,我遵循了不同的教程,得到了很好的精确结果。然而,这也是我第一次面对的问题。现在的准确率是50% (因为它是2级)。我开始认为这是一个Keras VGG16问题。我在网上尝试了所有不同的建议,包括类似的问题,堆叠溢出,但似乎没有任何效果。所有的预处理,增强和层冻结似乎是适当的,经过几个星期的错误试验后,我发现自己不得不求助于你的建议/建议的问题。

这是我使用的全部代码:

代码语言:javascript
复制
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

接下来是我使用的混淆矩阵函数实现。

代码语言:javascript
复制
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

代码语言:javascript
复制
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)

添加用于对数据进行分类和编译模型的最后一层:

代码语言:javascript
复制
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()

训练参数,路径等..。

代码语言:javascript
复制
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'

用于从不同集合读取的数据生成器。这些集合在单独的文件夹中,所以不需要分割列车,在我的情况下也是有效的。

代码语言:javascript
复制
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)

培训模式:

代码语言:javascript
复制
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
)

然后在测试集上进行预测,并与地面真实值进行比较,得到精度等:

代码语言:javascript
复制
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

我已经被困了几个星期了,这真的很令人沮丧。如果有人能帮助我,我将永远感激!

编辑:

因此,在询问之后,有人向我指出,这个模型实际上正在学习,我可以使用下面的代码来检查预测的准确性:

代码语言:javascript
复制
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函数进行分析时,会出现一些问题。不过,我还是找不到问题。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-09-17 14:56:57

对我创建的包含4个类的数据集进行分类

首先,对于4类分类问题,您的网络配置似乎很奇怪(至少可以说);第一个建议是:

  1. 在模型编译中更改为loss='categorical_crossentropy'
  2. 将最后一层更改为
代码语言:javascript
复制
add_model.add(Dense(4, activation='softmax'))

因为,由于你的predictions = np.argmax(predictions, axis=1)行,我想你已经使用了一个热编码标签.

票数 0
EN

Stack Overflow用户

发布于 2018-09-19 06:34:01

outputs=add_model(base_model.output))模型=(inputs=base_model.input,您未能正确添加新层)。只需使用functional。

代码语言:javascript
复制
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)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52370361

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档