使用迁移学习而不是学习的神经网络模型

数据挖掘 神经网络 深度学习 迁移学习 vgg16
2021-09-29 01:48:16

我是深度学习的初学者,正在使用迁移学习进行道路裂缝检测。我正在研究具有两个类的二进制分类,裂纹和无裂纹。

我的两个类的分布如下:

裂缝 - 600 张图片

无裂缝 - 480 张图片

我也使用了数据增强:

 train_generator = train_datagen.flow(trainX, trainY, batch_size=16)

 val_generator = test_datagen.flow(testX, testY, batch_size= 16)

我正在使用 VGG16,我已经像这样冻结了较低的 4 层:

vgg = vgg16.VGG16(include_top=False, weights='imagenet', 
                                 input_shape=input_shape)

output = vgg.layers[-1].output

output = keras.layers.Flatten()(output)

vgg_model = Model(vgg.input, output)

for layer in vgg_model.layers[:4]:

     layer.trainable = False

之后,我添加了两个隐藏层:

model = Sequential()
model.add(vgg_model)
model.add(Dense(256, activation='relu', input_dim=input_shape))
model.add(Dense(256, activation='relu'))
model.add(Dense(2, activation='softmax')) 
model.compile(loss='binary_crossentropy',
          optimizer=Adam(lr = 1e-6),
          metrics=['accuracy'])

但是在 1-2 个 epoch 之后,似乎什么都没有改变,验证准确性和损失都没有。我也尝试使用 SGD 优化器,但这也无济于事。我还添加了更多层,但对准确率和损失没有任何影响。达到的最大验证准确率为 62%。

我尝试从我的数据集中测试图像,因为该模型也给出了错误的预测。对于它预测为裂纹的每个测试图像,即标签 1。

有人可以建议我如何改善这一点吗?谢谢!

3个回答

只需从您的训练数据中获取 2 张图像。一个来自“破解”类,另一个来自“非破解”类。现在,检查您的模型是否可以获得 100% 的训练准确度,这意味着它是否可以在训练数据集上过拟合。如果它不能做到这一点,那么模型就出现了极大的错误。

迁移学习是通过切断预训练网络中的最后一层(在您的情况下是 VGG16)并根据您需要的类数添加一个密集层来完成,然后训练新模型。

您的模型不工作的原因是您正在从 vgg16 的最后一层获取输出,该层由 softmax 层激活。并且无法从 softmax 层学到一些东西,尤其是对于迁移学习。

将您的代码重写为

from keras.models import Model
from keras.layers import Dense

X = vgg_model.layers[-1].output #will give 4096 feature vector as an output
X = Dense(256, activation ='relu')(X)
X = Dense(256, activation ='relu')(X)
X = Dense(2, activation ='softmax')(X)
newmodel = Model(vgg_model.layers[0].output,X)
newmodel.compile(loss='binary_crossentropy',
          optimizer=Adam(lr = 1e-6),
          metrics=['accuracy'])

您的代码的问题是您愿意操作的目标不一致。Softmax 计算单个神经元的概率,二元分类器包含单个神经元进行操作。因此,softmax 从不用于二进制分类,我们宁愿使用 sigmoid。

所以只需更改以下内容

model = Sequential()
model.add(vgg_model)
model.add(Dense(256, activation='relu', input_dim=input_shape))
model.add(Dense(256, activation='relu'))
model.add(Dense(1, activation='sigmoid')) 
model.compile(loss='binary_crossentropy',
          optimizer=Adam(lr = 1e-6),
          metrics=['accuracy'])

说到这个模型,我应该说你解冻的低层是学习边缘等低级特征的层,所以即使你训练了低层,它仍然可能无法从更高层检测到裂缝. 作为建议,我建议您使模型的较高层可训练并降低模型的复杂性。这将改善您的模型。