【问题标题】:Why doesn't the accuracy when training VGG-16 change much?为什么训练 VGG-16 时准确率没有太大变化?
【发布时间】:2021-08-16 17:35:20
【问题描述】:

目前,我正在尝试在 VGG-16 模型上训练数据集。问题是精度没有太大变化,但它并没有固定在一个固定的精度上。情节图如下所示。有什么建议为什么会发生这种情况?

我已经按照几个指南来解决这个关于准确性卡住的问题,但它们不起作用。

编辑:

200 个纪元

50 个具有 Imagenet 权重的 Epochs

代码

模型的输入大小为 600 张 224x224x3 的图像。此外,两个标签狗和猫(0,1)。

属性

imageSize = (224,224,3)
epochs = 25
batch_size = 32

型号

from keras.applications.vgg16 import VGG16
vgg = VGG16(input_shape=imageSize,weights=None,include_top=False)

x = Flatten()(vgg.output)
prediction = Dense(1,activation='sigmoid')(x)

model = Model(inputs=vgg.input,outputs=prediction)
model.compile(loss='binary_crossentropy', optimizer='adam',metrics=['accuracy'])

图像生成器

from keras.applications.vgg16 import preprocess_input
from keras.preprocessing import image
from keras.preprocessing.image import ImageDataGenerator

imgGen = ImageDataGenerator(rotation_range=20,
                            width_shift_range=0.1,
                            height_shift_range=0.1,
                            shear_range=0.1,
                            zoom_range=0.2,
                            horizontal_flip=True,
                            vertical_flip=True,
                            preprocessing_function = preprocess_input)

拟合模型

r = model.fit_generator(imgGen.flow(trainX, trainY, batch_size=batch_size),
                        validation_data = imgGen.flow(testX, testY, batch_size=batch_size),
                        epochs=epochs,
                        steps_per_epoch=len(trainX)//batch_size,
                        validation_steps=len(testX)//batch_size,
                        verbose = 1,
                       )


【问题讨论】:

    标签: python tensorflow keras deep-learning


    【解决方案1】:

    不要使用adam优化器来训练VGG,众所周知,由于VGG网络中的大量参数,它会失败。只需使用 sgd 并调整学习率,例如从 0.01 开始,增加 10 倍或 0.1 倍,直到训练损失很好地减少。

    【讨论】:

    • 看点@Dr。史努比,谢谢!虽然我想知道为什么会这样?你知道吗?
    【解决方案2】:

    我建议您微调预训练模型,并冻结前几层的权重。 喜欢:

    vgg = VGG16(input_shape=imageSize,weights='imagenet',include_top=False)
    for layer in vgg.layers[0:-10]:
        layer.trainable = false
    

    【讨论】:

      【解决方案3】:

      你正在寻找它发生的原因,我猜你似乎没有得到答案,所以在这里......

      原因是在 VGGNet 中,AlexNet 的 参数空间 巨大,为了解决这个问题,它没有像 ResNet 中使用的 BatchNorm 和后面的模型。所以在 VGGNet 中要让模型收敛,你必须自己动手,玩转超参数,尤其是学习率,经验结果表明从低至 1e-6 开始甚至有助于收敛。此外,如果您可以对权重使用一些不同的权重初始化,这将在收敛方面显示出巨大的结果,导致默认权重初始化在这种情况下无法正常工作。最后,让模型训练更长的 epoch(比如 100 个),因为(参数的)空间非常颠簸,你会看到它有点振荡,但使用适当的 lr,它会收敛但需要一些时间。

      希望它能给你一点直觉......

      【讨论】:

        【解决方案4】:

        对于可能有类似问题的人,可以尝试以下方法:

        • 加载预训练的 VGG-16 权重
        • 只使最后几个卷积层可训练
        • 使用 SGD 优化器并将学习率设置为低
        • 在输出层设置正确的激活函数
        • 增加纪元

        关于使用预训练的权重,使用预训练的权重的好处是可以克服小数据集的限制,例如 OP 的 600 张图像的情况。但是你必须确保只有最后几层是可训练的,而其余的是不可训练的。

        【讨论】:

        • only make last few convolutional layers trainable 怎么样?通过设置weights='imagenet'?
        【解决方案5】:

        25 epochs 不够,试试 100 epochs 或 200 epochs

        def model(self):
            inputs = keras.layers.Input(shape=self.input_Shape)
            x = keras.layers.Conv2D(16, (3,3), activation='relu')(inputs)
            x = keras.layers.MaxPooling2D(2,2)(x)
            x = keras.layers.Conv2D(32,(3,3),activation='relu')(x)
            x = keras.layers.MaxPooling2D(2,2)(x)
            x = keras.layers.Conv2D(64,(3,3),activation='relu')(x)
            x = keras.layers.MaxPooling2D(2,2)(x)
            x = keras.layers.Flatten()(x)
            x = keras.layers.Dense(512,activation='relu')(x)
            outputs = keras.layers.Dense(1,activation='sigmoid')(x)
        
            model = keras.models.Model(inputs, outputs)
            model.summary()
            model.compile(optimizer=RMSprop(lr=0.001),
                          loss='binary_crossentropy',
                          metrics = ['acc'])
        
            return model
        

        【讨论】:

        • 对不起,我再次检查模型。原始的 vgg 模型没有输出层。所以你需要添加一个输出层。 keras.layers.Dense(1,actication='sigmoid')
        • 感谢您的建议。我试过了,我会回信给你的。
        • 如果更多的时期仍然不起作用。你可以尝试使用预训练的权重,然后检查结果吗?
        • 目前,我正在尝试 200 个 epoch,之后我会给你图形图。是的,我可以做到:)
        • 我都试过了,但似乎不起作用。我已经编辑了我的帖子,并在那里添加了情节:)
        【解决方案6】:

        原因

        预测层之前没有全连接层。

        背景

        您可以将 VGG 模型(实际上也是大多数其他模型)视为由

        1. 特征提取器(卷积层和池化层)和
        2. 一个完全连接的网络,它使用提取的特征来学习所需的分类。

        通过使用include_top=False,您可以删除 VGG16 模型中的全连接层。因此,您最终只能使用特征提取器。没有使用这些特征进行分类的网络。

        解决方案

        在特征提取器 (vgg) 和您的预测层之间添加两个完全连接的隐藏层。还建议使用迁移学习,因为您的数据集对于具有数百万参数的庞大 vgg 网络来说太小了。代码应该是这样的(没有测试过):

        # load the model (only the feature extractor) with the imagenet weights 
        vgg = VGG16(input_shape=imageSize, weights='imagenet', include_top=False, pooling='avg')
        # freeze the feature extractor values, as they're already pretrained on imagenet
        vgg.trainable = False
        # build the classificator model
        model = Sequential()
        # use vgg as feature extractor
        model.add(vgg)
        # add two hidden layers for classification
        model.add(Dense(512, activation=('relu'))
        model.add(Dense(256, activation=('relu'))
        # add the prediction layer
        model.add(Dense(1, activation=('sigmoid'))
        

        祝大家好运!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-12-20
          • 1970-01-01
          • 1970-01-01
          • 2020-01-06
          • 2020-09-20
          • 2021-09-10
          • 2023-04-04
          • 1970-01-01
          相关资源
          最近更新 更多