我正在尝试使用 Keras 上的基本 CNN 架构对彩色 MNIST 数字进行分类。这是将原始数据集着色为纯红色、绿色或蓝色的代码。
def load_norm_data():
## load basic mnist
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
train_images = np.zeros((*x_train.shape, 3)) # orig shape: (60 000, 28, 28, 1) -> rgb shape: (60 000, 28, 28, 3)
for num in range(x_train.shape[0]):
rgb = np.random.randint(3)
train_images[num, ..., rgb] = x_train[num]/255
return train_images, y_train
if __name__ == '__main__':
ims, labels = load_norm_data()
for num in range(10):
plt.subplot(2, 5, num+1)
plt.imshow(ims[num])
plt.axis('off')
给出前几个数字:
然后,我尝试将这个彩色数据集分类为 MNIST 的相同 10 位数字类别,因此标签不会改变——但模型准确度从非彩色 MNIST 的 95% 下降到变化很大的 30-70%在彩色 MNIST 上,很大程度上取决于权重初始化...请在下面找到所述模型的架构:
model = keras.Sequential()
model.add(keras.layers.Conv2D(64, kernel_size=(3,3), padding='same'))
model.add(keras.layers.MaxPool2D(pool_size=(2,2)))
model.add(keras.layers.Conv2D(64, kernel_size=(3,3), padding='same'))
model.add(keras.layers.MaxPool2D(pool_size=(2,2), padding='same'))
model.add(keras.layers.Flatten())
model.add(keras.layers.Dense(10, activation='relu'))
model.add(keras.layers.Softmax())
input_shape = train_images.shape
model.build(input_shape)
model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy'])
model.summary()
model.fit(train_images, train_numbers, batch_size=12, epochs=25)
最初,我认为这种性能下降可能与数据不规则性有关(例如,想象数据中的很多 3 最终变成绿色,因此模型学习绿色 = 3)。所以我检查了数据,计数很好,每个类别的 RGB 分布也接近每种颜色的 33%。我还检查了错误分类的图像,看看是否有很多特定颜色或数字的代表,但似乎也不是这种情况。无论如何,在阅读了 Keras 的文档之后,由于
Conv2D
迫使您向其传递一个二维 kernel_size
,我认为它可以在输入图像的所有通道上运行,因此模型不应该采用此处考虑分类时的颜色。
我在这里遗漏了什么吗?
模型的最后一部分包括一个dense -> relu -> softmax。应删除 relu 激活。此外,您可能会受益于在卷积块中添加非线性(例如 relu)。否则,神经网络最终将成为一个(大)线性函数,并且不能很好地处理非线性数据。
model = keras.Sequential()
model.add(keras.layers.Conv2D(64, kernel_size=(3,3), padding='same', activation='relu'))
model.add(keras.layers.MaxPool2D(pool_size=(2,2)))
model.add(keras.layers.Conv2D(64, kernel_size=(3,3), padding='same', activation='relu'))
model.add(keras.layers.MaxPool2D(pool_size=(2,2), padding='same'))
model.add(keras.layers.Flatten())
model.add(keras.layers.Dense(10))
model.add(keras.layers.Softmax())
有趣的是,原始模型在 MNIST 数据集上运行良好。我无法确定原因,但也许 MNIST 数据集足够简单,模型能够应对。此外,
relu -> softmax
会将负值限制为 0,而且负值可能并不多。