使用 TensorFlow 2 将 Dropout 添加到 MobileNet
Adding Dropout to MobileNet with TensorFlow 2
我正在使用 MobileNet 和 TensorFlow 2 来区分 4 个非常相似的玩具。我有每个玩具的 750 张图片和一个包含 750 'negative' 张图片的标签,没有任何玩具。
我之前使用 MobileNet 对此取得了一定程度的成功,但这种情况导致了很多过度拟合(training/validation 准确度之间存在约 30-40% 的差异)。该模型在 3 个时期内很快训练到约 99.8% 的训练准确率,但验证准确率停留在 75% 左右。验证数据集是 20% 的输入图像的随机集合。在查看模型的准确性时,对其中一个玩具有强烈的偏见,许多其他玩具被错误地识别为该玩具。
我已经尝试了几乎所有方法来解决这个问题:
我在添加到 MobileNet 顶部的 Conv2D 层之后添加了 Dropout,并尝试了 0.2 到 0.9 之间的各种丢弃率。
model = tf.keras.Sequential([
base_model,
tf.keras.layers.Conv2D(32, 3, activation='relu'),
tf.keras.layers.Dropout(0.5),
tf.keras.layers.GlobalAveragePooling2D(),
tf.keras.layers.Dense(label_count, activation='softmax')
])
我在 Conv2D 层之前添加了一个额外的 Dropout 层,这似乎略有改进:
model = tf.keras.Sequential([
base_model,
tf.keras.layers.Dropout(0.5),
tf.keras.layers.Conv2D(32, 3, activation='relu'),
tf.keras.layers.Dropout(0.5),
tf.keras.layers.GlobalAveragePooling2D(),
tf.keras.layers.Dense(label_count, activation='softmax')
])
我还添加了更多测试数据,尝试混合各种光照条件和背景下的玩具照片,并生成叠加在随机背景上的玩具图像。 None 其中有重大影响。
我应该将 dropout 添加到 MobileNet 模型,而不是仅仅添加到我在它之后添加的层吗?我在 github 上看到 this code 这样做,但我不知道这是否真的是个好主意 - 或者不知道如何使用 TensorFlow 2 实现这一点。
这是否明智或可行?
或者,我能想到的唯一其他想法是:
- 捕获更多图像,使训练更加困难 - 但我认为每个项目 750 应该足以做得很好。
- 不要使用 MobileNet,从头开始创建神经网络或使用另一个已有的神经网络。
由于模型过拟合,您可以
Shuffle
数据,通过在 cnn_model.fit
中使用 shuffle=True
。代码如下:
history = cnn_model.fit(x = X_train_reshaped,
y = y_train,
batch_size = 512,
epochs = epochs, callbacks=[callback],
verbose = 1, validation_data = (X_test_reshaped, y_test),
validation_steps = 10, steps_per_epoch=steps_per_epoch, shuffle = True)
使用Early Stopping
。代码如下
callback = tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=15)
使用Regularization
。正则化代码如下所示(您也可以尝试l1 Regularization
或l1_l2 Regularization
):
from tensorflow.keras.regularizers import l2
Regularizer = l2(0.001)
cnn_model.add(Conv2D(64,3, 3, input_shape = (28,28,1), activation='relu', data_format='channels_last',
activity_regularizer=Regularizer, kernel_regularizer=Regularizer))
cnn_model.add(Dense(units = 10, activation = 'sigmoid',
activity_regularizer=Regularizer, kernel_regularizer=Regularizer))
尝试用 MaxPool2D
替换 GlobalAveragePooling2D
你可以试试BatchNormalization
.
使用 ImageDataGenerator
执行图像数据增强。有关详细信息,请参阅 this link。
如果 Pixels
不是 Normalized
,将像素值除以 255
也有帮助。
最后,如果还是没有变化,可以试试其他的Pre-Trained Models
,比如ResNet
、Vgg Net
、DenseNet
(Mohsin提到的在评论中)
我正在使用 MobileNet 和 TensorFlow 2 来区分 4 个非常相似的玩具。我有每个玩具的 750 张图片和一个包含 750 'negative' 张图片的标签,没有任何玩具。
我之前使用 MobileNet 对此取得了一定程度的成功,但这种情况导致了很多过度拟合(training/validation 准确度之间存在约 30-40% 的差异)。该模型在 3 个时期内很快训练到约 99.8% 的训练准确率,但验证准确率停留在 75% 左右。验证数据集是 20% 的输入图像的随机集合。在查看模型的准确性时,对其中一个玩具有强烈的偏见,许多其他玩具被错误地识别为该玩具。
我已经尝试了几乎所有方法来解决这个问题:
我在添加到 MobileNet 顶部的 Conv2D 层之后添加了 Dropout,并尝试了 0.2 到 0.9 之间的各种丢弃率。
model = tf.keras.Sequential([
base_model,
tf.keras.layers.Conv2D(32, 3, activation='relu'),
tf.keras.layers.Dropout(0.5),
tf.keras.layers.GlobalAveragePooling2D(),
tf.keras.layers.Dense(label_count, activation='softmax')
])
我在 Conv2D 层之前添加了一个额外的 Dropout 层,这似乎略有改进:
model = tf.keras.Sequential([
base_model,
tf.keras.layers.Dropout(0.5),
tf.keras.layers.Conv2D(32, 3, activation='relu'),
tf.keras.layers.Dropout(0.5),
tf.keras.layers.GlobalAveragePooling2D(),
tf.keras.layers.Dense(label_count, activation='softmax')
])
我还添加了更多测试数据,尝试混合各种光照条件和背景下的玩具照片,并生成叠加在随机背景上的玩具图像。 None 其中有重大影响。
我应该将 dropout 添加到 MobileNet 模型,而不是仅仅添加到我在它之后添加的层吗?我在 github 上看到 this code 这样做,但我不知道这是否真的是个好主意 - 或者不知道如何使用 TensorFlow 2 实现这一点。
这是否明智或可行?
或者,我能想到的唯一其他想法是:
- 捕获更多图像,使训练更加困难 - 但我认为每个项目 750 应该足以做得很好。
- 不要使用 MobileNet,从头开始创建神经网络或使用另一个已有的神经网络。
由于模型过拟合,您可以
Shuffle
数据,通过在cnn_model.fit
中使用shuffle=True
。代码如下:history = cnn_model.fit(x = X_train_reshaped, y = y_train, batch_size = 512, epochs = epochs, callbacks=[callback], verbose = 1, validation_data = (X_test_reshaped, y_test), validation_steps = 10, steps_per_epoch=steps_per_epoch, shuffle = True)
使用
Early Stopping
。代码如下
callback = tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=15)
使用
Regularization
。正则化代码如下所示(您也可以尝试l1 Regularization
或l1_l2 Regularization
):from tensorflow.keras.regularizers import l2
Regularizer = l2(0.001)
cnn_model.add(Conv2D(64,3, 3, input_shape = (28,28,1), activation='relu', data_format='channels_last', activity_regularizer=Regularizer, kernel_regularizer=Regularizer))
cnn_model.add(Dense(units = 10, activation = 'sigmoid', activity_regularizer=Regularizer, kernel_regularizer=Regularizer))
尝试用
MaxPool2D
替换 你可以试试
BatchNormalization
.使用
ImageDataGenerator
执行图像数据增强。有关详细信息,请参阅 this link。如果
Pixels
不是Normalized
,将像素值除以255
也有帮助。最后,如果还是没有变化,可以试试其他的
Pre-Trained Models
,比如ResNet
、Vgg Net
、DenseNet
(Mohsin提到的在评论中)
GlobalAveragePooling2D