VGGnet在新类图像分类中

数据挖掘 深度学习 喀拉斯 图像分类
2022-03-10 21:19:36

我正在使用带有 VGGnet 的 Keras 模型作为图像分类的基础模型。代码如下:

from keras import applications
from keras.callbacks import TensorBoard
from keras.preprocessing.image import ImageDataGenerator
from keras import optimizers
from keras.models import Sequential, Model
from keras.layers import Dropout, Flatten, Dense
from keras import optimizers
from keras import backend as keras_backend
from keras.callbacks import TensorBoard
from tensorflow.python import debug as tf_debug

inputshape=(224,224,3)
base_model=applications.vgg16.VGG16(weights = "imagenet", include_top=True,input_shape=inputshape)
print (base_model.summary())

new_sequential=Sequential()
print(type(base_model))
for mylayer in base_model.layers:
    mylayer.trainable=False#this is done to set the weight as predefined
    new_sequential.add(mylayer)

new_sequential.layers.pop()#remove my last layer
new_sequential.add(Dense(output_dim=1,activation='sigmoid'))
new_sequential.compile(optimizer="adam",loss='binary_crossentropy',metrics=['accuracy'])

from keras.preprocessing.image import ImageDataGenerator

train_datagen = ImageDataGenerator(rescale=1./255,
                                    shear_range=0.2,
                                    zoom_range=0.2,
                                    horizontal_flip=True)

test_datagen = ImageDataGenerator(rescale=1./255)

training_data = train_datagen.flow_from_directory(directory="/home/Basic_1/dataset/training_set/",
                                                    target_size=(224, 224),
                                                    batch_size=8,
                                                    class_mode='binary')

test_validation = test_datagen.flow_from_directory("/home/Basic_1/dataset/test_set/",
                                                        target_size=(224, 224),
                                                        batch_size=8,
                                                        class_mode='binary')

cb=TensorBoard(log_dir=("/home/Basic_1"))

new_sequential.fit_generator(generator=training_data,
                            steps_per_epoch=200,
                            epochs=1000,
                            validation_data=test_validation,
                            validation_steps=5,callbacks=[cb])

from keras.models import load_model
new_sequential.save('saved_vgg.h5')
new_sequential.save_weights('saved_vgg_weights.h5')

import numpy as np
from keras.preprocessing import image

predict_image_path = "/home/Basic_1/dataset/predict/"

import glob
import os
from keras.preprocessing import image

os.getcwd()
os.chdir(predict_image_path)

images = []
images = glob.glob('*')

for imagepath in images:
    test_image=image.load_img(path=predict_image_path+'/'+imagepath,target_size=(224,224))
    test_image=image.img_to_array(test_image)
    test_image=np.expand_dims(test_image,axis=0)
    result=new_sequential.predict(test_image)
    print(result)

    if (result > 0.5):
        print("Image path {}, Obstacle    : {}".format(imagepath, result))
    else:
        print("Image path {}, Lane Follow : {}".format(imagepath, result))

请帮助我澄清以下疑问。

  1. 我已经阅读了用于训练模型的VGGnet用途。ImageNet但在我的情况下,我使用的是来自自定义类的图像,该类不包含在Imagenet. 网络是否能够基于这些自定义类进行训练?

  2. 我从 ```tensorboard` 看到训练似乎很正常。然而,模型在使用新图像进行推理时失败。

  3. 我用来训练的数据集中的图像具有1000x540维度。但是在这个VGGnet输入形状中(224, 224, 3),图像会在训练期间调整大小吗?

根据给出的答案更新问题:

  1. 是的,我正在接受预训练,该预训练VGGnetImageNet针对我的自定义类图像进行训练和训练模型的。(我已经将预训练模型的权重用于卷积层,并从预训练模型中删除了 FC 层并使用了我自己的 FC 层。这对我在这里做的吗?

  2. 是的,训练损失在减少,准确率在增加。与测试集相同的情况。运行 500 个 epoch 后,我得到了以下准确度和损失。

Training - Accuracy : 0.81   Loss : 0.40
Testing  - Accuracy : 0.78   Loss : 0.55

这些图像与ImageNet.

在推理过程中,如果我从训练集中给出图像,模型将无法正确分类。

谢谢你,KK

1个回答
  1. 如果 ImageNet 不包含该类,那么它将无法“开箱即用”。但当然你可以训练它做任何你想做的事。从本质上讲,您使用 ImageNet 进行“预训练”:您不是从随机权重开始,而是从从其他一些任务中学习到的权重开始。这在文献中被称为“迁移学习”。最简单的方法是(1)训练一个 CNN(由n卷积层,然后是mFC 层)在一些随机任务(如 ImageNet)上,(2)丢弃mFC 层和(可选)“冻结”n卷积层,(3)在网络末端添加新的 FC 层,并在您真正感兴趣的任务上训练它们。这样做的原因是,从执行任务 1 中学到的卷积过滤器已被经验证明对一般任务也就是说,预训练的卷积层的输出是图像的良好向量表示,可以用于其他任务。然后,顶部的 FC 层使用该表示学习执行您想要的任何任务。所以当你问

    网络是否能够基于这些自定义类进行训练?

    我会说是的,假设你使用上面的范例(即你正在微调VGG),假设 conv 表示是好的。至于这个问题,请参阅第 2 部分。

  2. 您的问题缺少一些可能有用的细节。你写了:

    我从 ```tensorboard` 看到训练似乎很正常。然而,模型在使用新图像进行推理时失败。

    “训练似乎很正常”是否仅仅意味着训练损失几乎单调减少?您是否也在验证集上进行测试?测试(推理)图像与训练图像是否来自同一组?这些图像是否类似于 ImageNet?

    一个潜在的问题案例(例如,您的预训练可能没有用)是由于domain shift这是当测试集来自与训练集不同的集/分布时。已经设计了许多算法来纠正这个问题,称为域适应方法。如果训练(甚至预训练)图像与推理时的图像差异太大,则此类方法对于保持良好性能是必要的。

  3. say yes文档flow_from_directory


(根据问题更新进行编辑)

  1. 是的,这似乎是合理的。您可以尝试一些变化:例如,允许 conv 层权重发生变化,但使用较小的学习率(也称为微调)。或者使用更强大的FC多层网络。

  2. 老实说,训练和测试之间 0.03 的准确度差异是相当微小的。与训练集相比,我总是希望网络在测试集上的表现至少差一点。它还取决于集合的大小。PAC 界限和所有这些 :) 我不确定你的损失是什么,但如果它类似于交叉熵,那么你可以认为更糟糕的损失是网络对其响应“不太确定”(至少非正式地说)。

    我不确定您During Inference if I give the images from training set, model is not able to classify it correctly.所说的准确度值表明它做得相当好,并且类似于训练集是什么意思。

    如果图像与 ImageNet真的有很大不同,那么微调 conv 权重可能会更有用。如果您的数据集也非常小,那么查看领域适应和迁移学习文献也可能会有所帮助。