训练准确性卡在 Keras

数据挖掘 机器学习 Python 神经网络 喀拉斯
2021-10-13 13:18:40

我已经使用 keras 训练了一个 CNN,用于 3 个类的图像分类。结果很糟糕,我试图了解分类器学到了什么,没有学到什么。它只给我 1 类的输出。

我对学习率、激活(最后一层的 relu、sigmoid 和 softmax)进行了更改,更改了架构和优化器(SGD 和 Adam),但训练准确度停留在 ~33.33%。这绝对不是巧合,因为我只有 3 节课。

我现在的架构是

[Conv -> Relu -Conv -> Relu -> MAxPool] * 3 -> Flatten -> [Dense -> Relu] * 2 -> Dense -> Softmax

我的前 2 个卷积层有 64 个大小为 (3, 3) 的过滤器,其余的卷积层有 32 个相同大小的过滤器。

我的密集层是这样的 128 个单位-> 64 个单位-> 3 个单位。

我从一个简单的模型开始,并使其变得更加复杂以改进它。但是在任何这些更改之后都没有改善。

出于实验目的,我使用了两个激活“relu”和“sigmoid”。我正在考虑只在最后一层使用 sigmoid 和 softmax。

我有大约 13000 张图像要训练,1400 张要验证。3类之间的分布几乎相等。

我正在使用这种语法来添加激活。摘要没有显示任何激活层。我的网络并没有改善。

classifier = Sequential()
    classifier.add(Conv2D(32, (3, 3), input_shape  = (256, 256, 3), activation = 'relu'))
    classifier.add(Conv2D(32, (3, 3), activation = 'relu'))
    classifier.add(MaxPooling2D(pool_size = (2,2)))

    _________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_11 (Conv2D)           (None, 254, 254, 32)      896       
_________________________________________________________________
conv2d_12 (Conv2D)           (None, 252, 252, 32)      9248      
_________________________________________________________________
max_pooling2d_6 (MaxPooling2 (None, 84, 84, 32)        0         
_________________________________________________________________
conv2d_13 (Conv2D)           (None, 82, 82, 32)        9248      
_________________________________________________________________
conv2d_14 (Conv2D)           (None, 80, 80, 32)        9248      
_________________________________________________________________
max_pooling2d_7 (MaxPooling2 (None, 40, 40, 32)        0         
_________________________________________________________________
conv2d_15 (Conv2D)           (None, 38, 38, 32)        9248      
_________________________________________________________________
conv2d_16 (Conv2D)           (None, 36, 36, 32)        9248      
_________________________________________________________________
max_pooling2d_8 (MaxPooling2 (None, 18, 18, 32)        0         
_________________________________________________________________
flatten_1 (Flatten)          (None, 10368)             0         
_________________________________________________________________
dense_6 (Dense)              (None, 128)               1327232   
_________________________________________________________________
dense_7 (Dense)              (None, 64)                8256      
_________________________________________________________________
dense_8 (Dense)              (None, 3)                 195       
=================================================================
Total params: 1,382,819
Trainable params: 1,382,819
Non-trainable params: 0

编辑:更新网络。但是当我将激活添加为新层时,架构会发生变化。现在我的网络似乎工作了。

classifier = Sequential()
classifier.add(Conv2D(64, (3, 3), input_shape  = (256, 256, 3))
classifier.add(Activation('relu'))
classifier.add(Conv2D(64, (3, 3))
classifier.add(Activation('relu'))
classifier.add(MaxPooling2D(pool_size = (2,2)))

Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_13 (Conv2D)           (None, 254, 254, 32)      896       
_________________________________________________________________
activation_1 (Activation)    (None, 254, 254, 32)      0         
_________________________________________________________________
conv2d_14 (Conv2D)           (None, 252, 252, 32)      9248      
_________________________________________________________________
activation_2 (Activation)    (None, 252, 252, 32)      0         
_________________________________________________________________
max_pooling2d_7 (MaxPooling2 (None, 84, 84, 32)        0         
_________________________________________________________________
conv2d_15 (Conv2D)           (None, 82, 82, 32)        9248      
_________________________________________________________________
activation_3 (Activation)    (None, 82, 82, 32)        0         
_________________________________________________________________
conv2d_16 (Conv2D)           (None, 80, 80, 32)        9248      
_________________________________________________________________
activation_4 (Activation)    (None, 80, 80, 32)        0         
_________________________________________________________________
max_pooling2d_8 (MaxPooling2 (None, 40, 40, 32)        0         
_________________________________________________________________
flatten_2 (Flatten)          (None, 51200)             0         
_________________________________________________________________
dense_7 (Dense)              (None, 128)               6553728   
_________________________________________________________________
activation_5 (Activation)    (None, 128)               0         
_________________________________________________________________
dense_8 (Dense)              (None, 3)                 387       
_________________________________________________________________
activation_6 (Activation)    (None, 3)                 0         
=================================================================
Total params: 6,582,755
Trainable params: 6,582,755
Non-trainable params: 0

目录结构

Training_path
    -Label1 Folder
    -Label2 Folder
    -Label3 Folder

我认为这是我网络中的问题。参数激活没有按预期工作,并且没有对网络输入执行激活。我不明白的是,这两种语法都是等价的(根据文档),但是却产生了不同的结果。

2个回答

所以有两个问题:

  1. 当我尝试将激活添加为参数Conv2d( activation = 'relu'), my activation layers were not added as displayed in the summary in my question. But by usingadd(Activation('relu'))` 时,它的工作原理如问题所示。
  2. 但这并没有解决问题。我使用的学习率在0.01, 0.007, 0.005几个 epoch 中显示出良好的训练和验证准确度,但再次暴跌至 33.33,因此可能超调。所以我使用了低得多的学习率0.0001,效果很好。

我遇到了类似的问题。在 Keras 中使用 nputils 对目标变量进行 One-hot 编码,解决了准确性和验证丢失卡住的问题。使用权重来平衡目标类进一步提高了性能。

y_train_temp = y_train.copy()
y_val_temp = y_val.copy()
from keras.utils.np.utils import to_categorical
y_train = to_categorical(y_train)
y_val = to_categorical(y_val)