在keras CNN可怕的准确性

8cdiaqws  于 2023-04-21  发布在  其他
关注(0)|答案(2)|浏览(139)

我是深度学习的初学者,我正在尝试创建一个手写单词分类模型,我创建了一个数据集,它包含71个不同的类,每个类有1000张图像。
问题是,我试图创建一个卷积、最大池化和密集层的不同组合的CNN模型,同时也改变了优化器,但准确性仍然很糟糕。
这是模型、数据集还是我的参数的问题?你有什么建议?
这是我试过的最后一个模型

model = Sequential([
    Conv2D(32, kernel_size=(2, 2),activation="relu", input_shape=(143, 75, 1)),
    MaxPooling2D(pool_size=(3,3)),
    Conv2D(64, kernel_size=(4, 4),activation="relu"),
    MaxPooling2D(pool_size=(9,9)),
    Flatten(),
    Dense(512, activation="relu"),
    Dense(128, activation="sigmoid"),
    Dense(71, activation="softmax")
])

model.compile(optimizer=Nadam(learning_rate=0.01), loss="categorical_crossentropy", metrics=["accuracy"])
eufgjt7s

eufgjt7s1#

你的模型的问题在于你的池大小。Keras的官方文档是这样描述池化层的
通过在输入的每个通道的输入窗口(由pool_size定义的大小)上取最大值,沿着其空间维度(高度和宽度)对输入进行下采样。窗口沿每个维度移动步幅。
默认情况下,池化层的池大小为(2,2),这意味着在4个元素的矩阵窗口中,仅考虑最大值。
如果我们打印您的模型的摘要,我们得到

Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 conv2d (Conv2D)             (None, 142, 74, 32)       160       
                                                                 
 max_pooling2d (MaxPooling2D  (None, 47, 24, 32)       0         
 )                                                               
                                                                 
 conv2d_1 (Conv2D)           (None, 44, 21, 64)        32832     
                                                                 
 max_pooling2d_1 (MaxPooling  (None, 4, 2, 64)         0         
 2D)                                                             
                                                                 
 flatten (Flatten)           (None, 512)               0         
                                                                 
 dense (Dense)               (None, 512)               262656    
                                                                 
 dense_1 (Dense)             (None, 128)               65664     
                                                                 
 dense_2 (Dense)             (None, 71)                9159      
                                                                 
=================================================================
Total params: 370,471
Trainable params: 370,471
Non-trainable params: 0
_________________________________________________________________

因此,通过查看这些层及其形状,conv2d_1(Conv2D)层输出和max_pooling2d_1(MaxPooling2D)层输出之间有很大的变化。输出形状从(44,21,64)变为(4,2,64)。这是因为您在Dense层之前为Pooling层使用了(9,9)的池大小。
为了理解池大小和池化的效果,考虑下面的输入图像,其大小为(183,183,3)

现在,当我们对上面的图像应用2D最大池化,池大小为(2,2)时,我们得到以下图像,其空间维度减少到(91,91,3)。这里图像维度减少了,但图像中的信息被保留了下来。

现在,对于相同的输入图像,池大小为(3,3)的最大池化输出将是以下尺寸为(61,61,3)的图像


在这里,你几乎可以看到这个词真棒的图像。
当池大小为(5,5)时,我们得到的最大池输出为

,空间维度为(36,36,3)。在这里,您根本看不到任何信息。
Why is that ?因为白色像素是255,黑色像素是0,当你做一个最大池时,你总是取255。现在,因为你使用的是(9,9)的池大小,在窗口中考虑更多的白色像素沿着黑色像素,并且随着空间维度减少到(20,20,3),您会丢失有用的信息,就像池大小为的情况一样(5,5). (此处仅显示图像上的池化效果。添加Conv 2D图层时,输出将根据过滤器值而变化。)
有了这个,你的模型将无法学习任何东西,尽管你改变了任何其他组件,如优化器或损失函数。
因此,将模型架构更改为如下所示,并重新训练网络

model = Sequential([
    Conv2D(32, kernel_size=(3, 3),activation="relu", input_shape=(143, 75, 1)),
    MaxPooling2D(),
    Conv2D(64, kernel_size=(3, 3),activation="relu"),
    MaxPooling2D(),
    Flatten(),
    Dense(512, activation="relu"),
    Dense(128, activation="relu"),
    Dense(71, activation="softmax")
])

model.compile(optimizer=tf.keras.optimizers.Nadam(learning_rate=0.01), loss="categorical_crossentropy", metrics=["accuracy"])

**P.S:**卷积层的内核大小通常是(3,3)或(5,5)。例如,当你有一个卷积层Conv2D(64, kernel_size=(3, 3))时,你将有64个过滤器,每个过滤器的大小为(3,3)。另外,不要忘记在将图像输入模型之前将其归一化。

Cheers!!!

ybzsozfc

ybzsozfc2#

找到了解决方案
我的数据集有白色背景和黑色手写的图像,由于我使用的是MaxPooling2D层,它只接受白色像素,因为它们的值是255,黑色像素的值是0,这就是为什么我必须使用Pillow库中的invert方法来反转我的数据集图像。
这样做之后,我的精度上升到0.9887
我还修复了我使用的模型,感谢@Keerthitheja S.C.的回答。

model = Sequential([
    Conv2D(64, kernel_size=(2, 2),activation="relu", input_shape=(143, 175, 3)),
    MaxPooling2D(pool_size=(2,2)),
    Flatten(),
    Dense(256, activation="relu"),
    Dense(128, activation="relu"),
    Dense(256, activation="sigmoid"),
    Dense(num_classes, activation="softmax")
])

相关问题