我正在研究10种类别(数字从0到10)的手语数字集的图像分类问题。尽管我尝试了简单的模型(例如1个Conv层),经典的ResNet50甚至是最先进的NASNetMobile,但由于某些原因,我的模型还是非常适合。
图像是彩色的,尺寸为100x100。我尝试调整学习速度,但并没有太大帮助,尽管减小批次大小会导致val精度提前提高。
我对图像进行了增强,但也无济于事:当val精度不能高于0.6时,我的火车精度可以达到1.0。
我查看了数据,看起来好像加载得很好。验证集中的类分布也很公平。我总共有2062张图片。
当我将损失更改为binary_crossentropy
时,无论是在火车精度还是在val精度上似乎都能提供更好的结果,但这似乎并不正确。
我不明白怎么了,请您帮我找出我所缺少的内容吗?谢谢。
这是我笔记本的链接:click
答案 0 :(得分:3)
这将是一个非常有趣的答案。解决问题时,您需要注意很多事情。幸运的是,这里有一种方法(可能有些含糊,但仍然是一种方法)。
TLDR :从数据而不是模型开始您的旅程。
首先让我们看看您的数据?
您有10节课。每个图像均为(100,100)
。而且只有2062张图片。你的第一个问题。与标准图像分类问题相比,数据很少。因此,您需要确保在不牺牲数据通用性的情况下易于学习数据(即,使其在验证/测试集上能表现出色)。我们该怎么做?
理解数据是其他部分中反复出现的主题。因此,我将没有单独的部分。
这是第一个问题。您正在将数据重新缩放到[0,1]之间。但是通过标准化数据(即(x - mean(x))/std(x)
),您可以做得更好。这是您的操作方式。
def create_datagen():
return tf.keras.preprocessing.image.ImageDataGenerator(
samplewise_center=True,
samplewise_std_normalization=True,
horizontal_flip=False,
rotation_range=30,
shear_range=0.2,
validation_split=VALIDATION_SPLIT)
您可能会注意到的另一件事是我设置了horizontal_flip=False
。这使我回到了第一点。您必须做出判断,以了解哪些增强技术可能有意义。
这非常重要。您没有那么多数据。而且,您要确保从数据中获得最大收益。数据的原始大小为(100,100)
。您可以使用尺寸明显较小的图像来做得很好(我尝试过(64,64)
-但您可以将图像缩小得更低)。因此,请尽可能减小图像的大小。
接下来的事情,无论您看到的是RGB还是灰度符号都没关系。您仍然可以识别该标志。但与RGB相比,灰度将样本数量减少了66%。因此,尽可能使用较少的颜色通道。
这是您的操作方式,
def create_flow(datagen, subset, directory, hflip=False):
return datagen.flow_from_directory(
directory=directory,
target_size=(64, 64),
color_mode='grayscale',
batch_size=BATCH_SIZE,
class_mode='categorical',
subset=subset,
shuffle=True
)
再次重申一下,您需要花一些时间来理解数据,然后再继续进行模型研究。这是此问题的基本清单。也可以尝试其他方法。
所以,这是我对模型所做的更改。
padding='same'
添加到所有卷积层。如果默认情况下不这样做,则会显示padding=valid
,这会导致尺寸自动降低。这意味着,您越深入,输出将越小。您可以在模型中看到,您有一个大小为(3,3)
的最终卷积输出。对于密集层来说,这可能太小而无法理解。因此,请注意致密层正在得到什么。进行这些更改之后,您无需更改Adam
的学习率。 Adam
无需任何调整即可很好地工作。所以您可以稍后再担心。
您使用的批处理大小为8。这甚至还不够大,不足以在批处理中为每个类包含一个图像。尝试将其设置为更高的值。我将其设置为32
。只要您可以尝试增加批量大小。可能值不是很大。但是最多约128个(对于这个问题应该没问题)。
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Convolution2D(8, (5, 5), activation='relu', input_shape=(64, 64, 1), padding='same'))
model.add(tf.keras.layers.MaxPooling2D((2, 2)))
model.add(tf.keras.layers.BatchNormalization())
model.add(tf.keras.layers.Convolution2D(16, (3, 3), activation='relu', padding='same'))
model.add(tf.keras.layers.MaxPooling2D((2, 2)))
model.add(tf.keras.layers.BatchNormalization())
model.add(tf.keras.layers.Convolution2D(32, (3, 3), activation='relu', padding='same'))
model.add(tf.keras.layers.MaxPooling2D((2, 2)))
model.add(tf.keras.layers.BatchNormalization())
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(128, activation='relu'))
model.add(tf.keras.layers.Dropout(0.5))
model.add(tf.keras.layers.Dense(10, activation='softmax'))
model.summary()
通过在进行模型制作之前进行一些冥想,我取得了比您所拥有的更好的结果。
Epoch 1/10
233/233 [==============================] - 37s 159ms/step - loss: 2.6027 - categorical_accuracy: 0.2218 - val_loss: 2.7203 - val_categorical_accuracy: 0.1000
Epoch 2/10
233/233 [==============================] - 37s 159ms/step - loss: 1.8627 - categorical_accuracy: 0.3711 - val_loss: 2.8415 - val_categorical_accuracy: 0.1450
Epoch 3/10
233/233 [==============================] - 37s 159ms/step - loss: 1.5608 - categorical_accuracy: 0.4689 - val_loss: 2.7879 - val_categorical_accuracy: 0.1750
Epoch 4/10
233/233 [==============================] - 37s 158ms/step - loss: 1.3778 - categorical_accuracy: 0.5145 - val_loss: 2.9411 - val_categorical_accuracy: 0.1450
Epoch 5/10
233/233 [==============================] - 38s 161ms/step - loss: 1.1507 - categorical_accuracy: 0.6090 - val_loss: 2.5648 - val_categorical_accuracy: 0.1650
Epoch 6/10
233/233 [==============================] - 38s 163ms/step - loss: 1.1377 - categorical_accuracy: 0.6042 - val_loss: 2.5416 - val_categorical_accuracy: 0.1850
Epoch 7/10
233/233 [==============================] - 37s 160ms/step - loss: 1.0224 - categorical_accuracy: 0.6472 - val_loss: 2.3338 - val_categorical_accuracy: 0.2450
Epoch 8/10
233/233 [==============================] - 37s 158ms/step - loss: 0.9198 - categorical_accuracy: 0.6788 - val_loss: 2.2660 - val_categorical_accuracy: 0.2450
Epoch 9/10
233/233 [==============================] - 37s 160ms/step - loss: 0.8494 - categorical_accuracy: 0.7111 - val_loss: 2.4924 - val_categorical_accuracy: 0.2150
Epoch 10/10
233/233 [==============================] - 37s 161ms/step - loss: 0.7699 - categorical_accuracy: 0.7417 - val_loss: 1.9339 - val_categorical_accuracy: 0.3450
Epoch 1/10
59/59 [==============================] - 14s 240ms/step - loss: 1.8182 - categorical_accuracy: 0.3625 - val_loss: 2.1800 - val_categorical_accuracy: 0.1600
Epoch 2/10
59/59 [==============================] - 13s 228ms/step - loss: 1.1982 - categorical_accuracy: 0.5843 - val_loss: 2.2777 - val_categorical_accuracy: 0.1350
Epoch 3/10
59/59 [==============================] - 13s 228ms/step - loss: 0.9460 - categorical_accuracy: 0.6676 - val_loss: 2.5666 - val_categorical_accuracy: 0.1400
Epoch 4/10
59/59 [==============================] - 13s 226ms/step - loss: 0.7066 - categorical_accuracy: 0.7465 - val_loss: 2.3700 - val_categorical_accuracy: 0.2500
Epoch 5/10
59/59 [==============================] - 13s 227ms/step - loss: 0.5875 - categorical_accuracy: 0.8008 - val_loss: 2.0166 - val_categorical_accuracy: 0.3150
Epoch 6/10
59/59 [==============================] - 13s 228ms/step - loss: 0.4681 - categorical_accuracy: 0.8416 - val_loss: 1.4043 - val_categorical_accuracy: 0.4400
Epoch 7/10
59/59 [==============================] - 13s 228ms/step - loss: 0.4367 - categorical_accuracy: 0.8518 - val_loss: 1.7028 - val_categorical_accuracy: 0.4300
Epoch 8/10
59/59 [==============================] - 13s 226ms/step - loss: 0.3823 - categorical_accuracy: 0.8711 - val_loss: 1.3747 - val_categorical_accuracy: 0.5600
Epoch 9/10
59/59 [==============================] - 13s 227ms/step - loss: 0.3802 - categorical_accuracy: 0.8663 - val_loss: 1.0967 - val_categorical_accuracy: 0.6000
Epoch 10/10
59/59 [==============================] - 13s 227ms/step - loss: 0.3585 - categorical_accuracy: 0.8818 - val_loss: 1.0768 - val_categorical_accuracy: 0.5950
注意:这是我付出的最小努力。您可以通过增加数据,优化模型结构,选择合适的批次大小等来进一步提高准确性。