过去一周我一直在学习机器学习,并且我一直在尝试使用128×128的彩色图像作为输入的自定义回归CNN模型,输出为评分。尽管我的数据集较小,总共约400个样本,我还是得到了不错的结果,模型有些过拟合(训练集的平均绝对误差为0.5,测试集为0.9,评分范围为1-10),如下所示的模型:
model = keras.Sequential([ keras.layers.Conv2D(32, kernel_size=(5, 5), strides=(1, 1), activation='relu', input_shape=(128, 128, 3)), keras.layers.Dropout(0.15), keras.layers.MaxPooling2D(pool_size=(2, 2), strides=(2, 2)), keras.layers.Conv2D(64, kernel_size=(5, 5), activation='relu'), keras.layers.Dropout(0.15), keras.layers.MaxPooling2D(pool_size=(2, 2)), keras.layers.Flatten(), keras.layers.Dense(1000, activation='relu'), keras.layers.Dropout(0.4), keras.layers.Dense(1)])
然而,对结果不满意,我决定尝试一些经过验证的模型。所以我使用了AlexNet:
model = keras.Sequential([ keras.layers.Conv2D(filters=96, kernel_size=(11, 11), strides=(4, 4), activation='relu', input_shape=(128, 128, 3), padding='same'), keras.layers.MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same'), keras.layers.Conv2D(filters=256, kernel_size=(11, 11), strides=(1, 1), activation='relu', padding='same'), keras.layers.MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same'), keras.layers.Conv2D(filters=384, kernel_size=(3, 3), strides=(1, 1), activation='relu', padding='same'), keras.layers.Conv2D(filters=384, kernel_size=(3, 3), strides=(1, 1), activation='relu', padding='same'), keras.layers.Conv2D(filters=256, kernel_size=(3, 3), strides=(1, 1), activation='relu', padding='same'), keras.layers.MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same'), keras.layers.Flatten(), keras.layers.Dense(4096, activation='relu'), keras.layers.Dropout(0.4), keras.layers.Dense(4096, activation='relu'), keras.layers.Dropout(0.4), keras.layers.Dense(1000, activation='relu'), keras.layers.Dropout(0.4), keras.layers.Dense(1)])
然而,它的收敛速度要慢得多,并且在训练集的MAE达到1.2和测试集的MAE达到0.9时基本停止改善。尽管这显示出较少的过拟合,但我觉得奇怪的是测试结果仍然相同。我的AlexNet实现是否有问题,还是AlexNet不适合这个应用?我知道它通常用于分类,但我认为尝试用于回归也值得一试。任何信息/建议/批评都对我有帮助,谢谢!
回答:
我没有看到你的AlexNet实现有什么明显的问题。但我想指出几点。
第一个模型中Dropout的使用方式
在卷积输出后应用Dropout
并不是标准做法。当你以这种方式应用Dropout时,Convolution
输出的输出会被随机关闭。但与全连接层不同,卷积输出具有”空间“结构。我想表达的是,关闭整个通道比随机关闭神经元更有意义。我认为一个插图会有所帮助。想象一个通道输出对应于一个全连接层的单个神经元(这不是最好的类比,但有助于理解我的建议)。
另一种选择是去掉卷积输出后的Dropout
,只在全连接层后使用Dropout
。
AlexNet收敛所需时间
AlexNet比模型1大得多,意味着参数比你的第一个模型多得多。所以它需要更长时间来收敛是合理的。
为什么准确率低?
我能想到的一件事是Flatten()
层之前的输出大小。在模型1中,它是32×32,而在AlexNet中,它是4×4,这非常小。所以你的全连接层从卷积层接收到的信息很少。这可能导致AlexNet表现不佳(这只是一个猜测)。