我正在尝试在Keras设计一个CNN来对其他图像中的表情符号的小图像进行分类。下面是13个类中的一个示例。所有的图像都是相同的大小,所有的表情符号也都是相同的大小。我认为一个人在分类时应该很容易达到非常高的准确率,因为来自一个类别的表情符号是完全相同的!我的直觉告诉我,如果一个表情符号是50x50,我可以创建一个相同大小的卷积层来匹配一种表情符号。然而,我的主管并不认为这是可行的。无论如何,我的问题是,无论我如何设计我的模型,我总是得到相同的验证精度,每个时期对应1/13 (或者简单地猜测每个表情符号属于同一个类)。
我的模型是这样的:
model = Sequential()
model.add(Conv2D(16, kernel_size=3, activation="relu", input_shape=IMG_SIZE))
model.add(Dropout(0.5))
model.add(Conv2D(32, kernel_size=3, activation="relu"))
model.add(Conv2D(64, kernel_size=3, activation="relu"))
model.add(Conv2D(128, kernel_size=3, activation="relu"))
#model.add(Conv2D(256, kernel_size=3, activation="relu"))
model.add(Dropout(0.5))
model.add(Flatten())
#model.add(Dense(256, activation="relu"))
model.add(Dense(128, activation="relu"))
model.add(Dense(64, activation="relu"))
model.add(Dense(NUM_CLASSES, activation='softmax', name="Output")) 我是这样训练它的:
# ------------------ Compile and train ---------------
sgd = optimizers.SGD(lr=0.001, decay=1e-6, momentum=0.9, nesterov=True)
rms = optimizers.RMSprop(lr=0.004, rho=0.9, epsilon=None, decay=0.0)
model.compile(optimizer=sgd, loss='categorical_crossentropy', metrics=["accuracy"]) # TODO Read more about this
train_hist = model.fit_generator(
train_generator,
steps_per_epoch=train_generator.n // BATCH_SIZE,
validation_steps=validation_generator.n // BATCH_SIZE, # TODO que?
epochs=EPOCHS,
validation_data=validation_generator,
#callbacks=[EarlyStopping(patience=3, restore_best_weights=True)]
)即使使用这个拥有200多万个参数的模型,我在每个时期的验证准确率也只有0.0773:
Epoch 1/10
56/56 [==============================] - 21s 379ms/step - loss: 14.9091 - acc: 0.0737 - val_loss: 14.8719 - val_acc: 0.0773
Epoch 2/10
56/56 [==============================] - 6s 108ms/step - loss: 14.9308 - acc: 0.0737 - val_loss: 14.8719 - val_acc: 0.0773
Epoch 3/10
56/56 [==============================] - 6s 108ms/step - loss: 14.7869 - acc: 0.0826 - val_loss: 14.8719 - val_acc: 0.0773
Epoch 4/10
56/56 [==============================] - 6s 108ms/step - loss: 14.8948 - acc: 0.0759 - val_loss: 14.8719 - val_acc: 0.0773
Epoch 5/10
56/56 [==============================] - 6s 109ms/step - loss: 14.8897 - acc: 0.0762 - val_loss: 14.8719 - val_acc: 0.0773
Epoch 6/10
56/56 [==============================] - 6s 109ms/step - loss: 14.8178 - acc: 0.0807 - val_loss: 14.8719 - val_acc: 0.0773
Epoch 7/10
56/56 [==============================] - 6s 108ms/step - loss: 15.0747 - acc: 0.0647 - val_loss: 14.8719 - val_acc: 0.0773
Epoch 8/10
56/56 [==============================] - 6s 108ms/step - loss: 14.7509 - acc: 0.0848 - val_loss: 14.8719 - val_acc: 0.0773
Epoch 9/10
56/56 [==============================] - 6s 108ms/step - loss: 14.8948 - acc: 0.0759 - val_loss: 14.8719 - val_acc: 0.0773
Epoch 10/10
56/56 [==============================] - 6s 108ms/step - loss: 14.8228 - acc: 0.0804 - val_loss: 14.8719 - val_acc: 0.0773因为它没有学到任何东西,我开始认为这不是我的模型的错误,而可能是数据集或我如何训练它。我也尝试过使用"adam“进行训练,但也得到了同样的结果。我尝试更改图像的输入大小,但仍然是相同的结果。下面是我的数据集中的一个示例。你们知道会出什么问题吗?

发布于 2019-09-13 00:06:19
我认为目前的主要问题是,相对于用于训练的样本太少,你的模型有太多的参数。对于现在的图像分类,您通常只希望拥有conv层、Global_Something_Pooling层,然后为您的输出提供单个密集层。您只需要确保您的conv部分最终具有足够大的接受域,以便能够找到所需的所有功能。
首先要考虑的是确保你有一个足够大的接受域(further reading about that here)。有三种主要的方法来实现这一点: pooling,stride >= 2,和/或easily >= 2。因为你只需要识别13个“特征”,并且所有这些“特征”都是像素完美的,所以我认为扩展将是一种方法,这样模型就可以很容易地在这13个“特征”上“过拟合”。如果我们使用4个卷积层,分别膨胀为1,2,4和8,那么我们将最终得到31的接受场。这应该足以轻松识别50像素的表情符号。
接下来,每一层应该有多少个过滤器?通常,您从几个过滤器开始,并随着模型的进行而增加,就像您在这里所做的那样。然而,我们希望在特定的功能上“过度拟合”,因此我们可能应该增加较早层中的数量。为了简单起见,让我们给所有的layers 64个过滤器。
最后,我们如何将所有这些都转换为单个预测?现在人们使用GlobalAveragePooling或GlobalMaxPooling,而不是使用密集的层,这将使用大量参数,并且不是平移不变的。GlobalAveragePooling更常见,因为它有助于找到许多特性的组合。然而,我们只想在这里找到大约13个确切的功能,所以GlobalMaxPooling可能会工作得更好。然后,在那之后的单个致密层将足以获得预测。因为我们使用的是_Global_MaxPooling,所以它不需要首先被扁平化--全局池已经为我们做到了这一点。
结果模型:
Conv2D(64, kernel_size=3, activation="relu", input_shape=IMG_SIZE)
Conv2D(64, kernel_size=3, dilation_rate=2, activation="relu")
Conv2D(64, kernel_size=3, dilation_rate=4, activation="relu")
Conv2D(64, kernel_size=3, dilation_rate=8, activation="relu")
GlobalMaxPooling()
Dense(NUM_CLASSES, activation='softmax', name="Output")试试看。你可能还想在除了最后一层之外的每一层之后都添加BatchNormalization层。一旦你得到了良好的训练精度,检查它是否过拟合。如果是(很有可能),请尝试以下步骤:
对所有卷积层和密集layers
设计这样的网络更像是一门艺术,而不是一门科学,所以如果你认为你应该改变周围的东西,那就去改变吧。最终,您将对在任何给定情况下或多或少可能工作的情况有一个直观的认识。
https://stackoverflow.com/questions/57901697
复制相似问题