当前位置: 首页 > 知识库问答 >
问题:

使用 Keras 进行迁移学习,验证准确性从一开始就没有提高(超出幼稚的基线),而训练准确性提高了

关正雅
2023-03-14

我正在为Food-101数据集构建分类器(图像数据集w/101类,每个类1k图像)。我的方法是使用Keras和ResNet50(来自imagenet的权重)进行转移学习。

当训练模型时,训练精度在几个时期内得到适度提高(30%)--

当我查看模型在验证集上所做的预测时,它始终是同一类。

我的感觉是,该模型并没有过度拟合到如此糟糕的程度,以致于无法解释验证精度中缺乏变化的原因。

如有任何建议,以提高验证精度,我们将不胜感激。

作为参考,下面是相关的代码片段:

datagen = ImageDataGenerator(rescale=1./255, validation_split=0.2)

train_datagen = datagen.flow_from_directory('data/train/', seed=42, class_mode='categorical', subset='training', target_size=(256,256))
# prints "60603 images belonging to 101 classes"
val_datagen = datagen.flow_from_directory('data/train/', seed=42, class_mode='categorical', subset='validation', target_size=(256,256)) 
# prints "15150 images belonging to 101 classes"

train_steps = len(train_datagen) #1894
val_steps = len(val_datagen) #474
classes = len(list(train_datagen.class_indices.keys())) #101

conv_base = ResNet50(weights='imagenet', include_top=False, pooling='avg', input_shape=(256, 256, 3))

from keras.layers import GlobalAveragePooling2D
from keras.layers import Dropout
from keras.layers import Flatten
from keras.layers import BatchNormalization

model = Sequential()

model.add(conv_base)
model.add(BatchNormalization())
model.add(Dropout(0.2))
model.add(Dense(512, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(classes, activation='softmax'))

conv_base.trainable = False

from keras.optimizers import Adam

model.compile(loss='categorical_crossentropy',
              optimizer=Adam(),
              metrics=['acc','top_k_categorical_accuracy'])

history = model.fit_generator(
    train_datagen,
    steps_per_epoch=train_steps,
    epochs=5,
    verbose=2,
    validation_data=val_datagen,
    validation_steps=val_steps
)

下面是<代码>的结果。fit_generator():

  • 第1/5纪元
    • 724秒 - 亏损:3.1305 - acc:0.3059 - top_k_categorical_accuracy:0.5629 - val_loss:6.5914 val_acc:0.0099 - val_top_k_categorical_accuracy:0.0494
    • 715s - 损失: 2.4812 - 截至: 0.4021 - top_k_categorical_accuracy: 0.6785 - val_loss: 7.4093 - val_acc: 0.0099 - val_top_k_categorical_accuracy: 0.0495
    • 714s-损失:2.3559-acc:0.4248-top_k_categorical_accuracy:0.7026-val_loss:8.9146-val_acc:0.0094-val_top_k_categorical_accuracy:0.0495
    • 714s-损失:2.2661-acc:0.4459-top_k_Categorial_accuracy:0.7200-val_loss:8.0597-val _acc:
    • 715s - 损失: 2.1870 - 截至: 0.4583 - top_k_categorical_accuracy: 0.7348 - val_loss: 7.5171 - val_acc: 0.0100 - val_top_k_categorical_accuracy: 0.0483

    下面是model.summary()

    Layer (type)                 Output Shape              Param #   
    =================================================================
    resnet50 (Model)             (None, 2048)              23587712  
    _________________________________________________________________
    batch_normalization_1 (Batch (None, 2048)              8192      
    _________________________________________________________________
    dropout_1 (Dropout)          (None, 2048)              0         
    _________________________________________________________________
    dense_1 (Dense)              (None, 512)               1049088   
    _________________________________________________________________
    dropout_2 (Dropout)          (None, 512)               0         
    _________________________________________________________________
    dense_2 (Dense)              (None, 101)               51813     
    =================================================================
    Total params: 24,696,805
    Trainable params: 1,104,997
    Non-trainable params: 23,591,808
    _________________________________________________________________
    

共有3个答案

颜楚青
2023-03-14

试试这个

datagen = ImageDataGenerator(rescale=1./255, validation_split=0.4)

train_datagen = datagen.flow_from_directory('data/train/', seed=42, class_mode='categorical', subset='training', target_size=(256,256))
# prints "60603 images belonging to 101 classes"
val_datagen = datagen.flow_from_directory('data/train/', seed=42, class_mode='categorical', subset='validation', target_size=(256,256)) 
# prints "15150 images belonging to 101 classes"

train_steps = len(train_datagen) #1894
val_steps = len(val_datagen) #474
classes = len(list(train_datagen.class_indices.keys())) #101

conv_base = ResNet50(weights='imagenet', include_top=False, pooling='avg', input_shape=(256, 256, 3))

from keras.layers import GlobalAveragePooling2D
from keras.layers import Dropout
from keras.layers import Flatten
from keras.layers import BatchNormalization

model = Sequential()

model.add(conv_base)
model.add(Dropout(0.2))
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.3))
model.add(Dense(classes, activation='softmax'))

conv_base.trainable = False

from keras.optimizers import Adam

model.compile(loss='categorical_crossentropy',
              optimizer=Adam(),
              metrics=['acc','top_k_categorical_accuracy'])

history = model.fit_generator(
    train_datagen,
    steps_per_epoch=train_steps,
    epochs=50,
    verbose=2,
    validation_data=val_datagen,
    validation_steps=val_steps
)
孙俊彦
2023-03-14

减少模型中的冻结层(或增加可训练层)。我遇到了同样的问题,然后我用我的数据训练了一半的层,准确性大大提高。

姜彬郁
2023-03-14

验证准确性低的原因与模型的构建方式有关。有理由认为迁移学习在这种情况下会很有效。然而,你的前1名和前5名分别接近1/101和5/101。这表明您的模型是偶然进行分类的,并且尚未了解数据集的潜在信号(特征)。因此,迁移学习在这种情况下不起作用。然而,这确实意味着它永远不会工作。

我重复了你的实验,我得到了相同的结果,即前1和前5的精度反映了随机选择的分类。然而,我随后解冻了ResNet50模型的层,并重复了实验。这只是进行迁移学习的一种稍微不同的方法。经过10个阶段的训练,我得到了以下结果:

Epoch 10/50 591/591 [===========================================] - 1492秒 3s/步 - 损耗: 1.0594 - 精度: 0.7459 - val_loss: 1.1397 - val_accuracy: 0.7143

这并不完美。然而,该模型尚未收敛,还有一些预处理步骤可用于进一步改进结果。

您观察的原因在于,冻结的ResNet50模型是根据与Food101数据集根本不同的图像分布进行训练的。数据分布中的这种不匹配导致html" target="_blank">性能不佳,因为冻结网络执行的转换未调整到Food101图像。解冻网络可以让神经元实际学习Food101图像,这是获得更好结果的原因。

希望这对你有帮助。

 类似资料:
  • 关于使用Lenet5网络解释MNIST上某些优化器的性能,我有几个问题,以及验证损失/精度与训练损失/精度图确切地告诉我们什么。因此,所有的事情都是在Keras中使用标准的LeNet5网络完成的,它运行了15个历元,批处理大小为128。 有两个图,列车acc vs val acc和列车损失vs val损失。我生成了4个图,因为我运行了两次,一次是validation_split=0.1,一次是va

  • 我目前正在Mac OS计算机上的网页上录制音频,并通过云语音api运行它以生成一份抄本。然而,结果并不是那么准确,结果中有大量缺失的单词。 是否有任何步骤可以帮助我产生更准确的结果? 以下是我将音频转换为文本的步骤: 使用Soundflower将音频输出从声卡传输到麦克风输入 从网站播放音频 使用quickTime player录制保存为的音频。m4a文件 使用命令行工具ffmpeg转换。m4a文

  • 我试图了解分支预测单元如何在 CPU 中工作。 我使用了和linux的,但这两个都没有给出准确的结果(就我的情况而言)。 这是我的代码: 我的数组由0和1组成。它有一个大小为的模式。例如,如果我的大小是8,那么它有一个或类似的模式。 试验1: 我试图理解CPU是如何预测这些分支的。因此,我使用了papi并为预测失误的分支预测设置了性能计数器(我知道它也计算间接分支)。 我看到的输出是(序列长度为2

  • 问题内容: 我使用Google的Tesseract API创建了一个用于识别文本的基本应用程序,并将其与我的相机应用程序集成在一起。它可以正常工作,但唯一的问题是准确性,因为有时文本会被识别为随机字符集,我想准确性约为50%。 此外,当它尝试扫描图像中的四个以上单词时,应用程序崩溃。 Tesseract API类的对象在哪里。 我是否需要使用其他数据结构来保存识别的文本,还是有其他原因导致四个以上

  • 因此,我在这里使用Watson ExampleStreaming Speech to Text演示作为Unity SDK的起点 https://github.com/watson-developer-cloud/unity-sdk 这是可行的,但问题是准确性。 我在这里读过这篇文章,我如何提高沃森语音对文本的准确性?但有一个问题 通过简单地使用我自己的声音创建一个自定义的声学模型,我可以期望提高准

  • 在每个纪元结束时,我会得到以下输出: 谁能给我解释一下损失、准确性、验证损失和验证准确性之间有什么区别吗?