CNN模型在大多数情况下预测相同的值

Posted

技术标签:

【中文标题】CNN模型在大多数情况下预测相同的值【英文标题】:CNN model predict the same value in most part of cases 【发布时间】:2020-07-07 00:46:28 【问题描述】:

我正在尝试训练一个用于图像分类的 CNN 模型。

有九个班级,每个班级有1000张图片。

这是我的代码

model = Sequential()

model.add(Conv2D(32, kernel_size=(5,5), activation='relu',kernel_initializer='random_uniform', input_shape=(128,646,1)))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(BatchNormalization())
model.add(Conv2D(16, kernel_size=(5,5), activation='relu', input_shape=(64,321,1)))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(BatchNormalization())

model.add(Flatten())
model.add(Dense(16, activation = 'relu',kernel_initializer='normal'))
model.add(Dropout(0.5))
model.add(Dense(9, activation = 'softmax'))

model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

我已经在 MNIST 数据集上尝试过这个,它的工作将

但在我的数据集上,它总是预测相同的值。

(上方为真标签,下方为预测标签值)

[[0. 0. 0. 1. 0. 0. 0. 0. 0.]
 [0. 0. 0. 1. 0. 0. 0. 0. 0.]
 [0. 0. 0. 1. 0. 0. 0. 0. 0.]
 [0. 0. 0. 1. 0. 0. 0. 0. 0.]
 [0. 0. 0. 1. 0. 0. 0. 0. 0.]]
[[0.11161657 0.11246169 0.11564494 0.11465651 0.11153363 0.10664304
  0.11097018 0.11052497 0.10594855]
 [0.11161657 0.11246169 0.11564494 0.11465651 0.11153363 0.10664304
  0.11097018 0.11052497 0.10594855]
 [0.11161657 0.11246169 0.11564494 0.11465651 0.11153363 0.10664304
  0.11097018 0.11052497 0.10594855]
 [0.11161657 0.11246169 0.11564494 0.11465651 0.11153363 0.10664304
  0.11097018 0.11052497 0.10594855]
 [0.11161657 0.11246169 0.11564494 0.11465651 0.11153363 0.10664304
  0.11097018 0.11052497 0.10594855]]

Accuracy curves Loss curves

我已尝试更改 初始化器、优化器、损失函数、更多 epoch, ...仍然没有任何变化。

但是当我 1.将两个 Conv2D 内核数设置为 1 2.将第一个Conv2D激活函数设置为tanh

模型开始预测输入的不同值,但性能不会。

我主要是对感到困惑 1.将内核编号设置为 1 似乎并不常见,但根据我的经验,它会避免预测相同的值。 2.输入图像的值都大于零,但是设置activate函数为tanh也可以改变结果到不同的预测类?

另外,图片尺寸为128*646 每个图像值都在 0~80 范围内

array([[[33.74863434],
        [27.84932709],
        [22.6257019 ],
        ...,
        [21.47132492],
        [19.61938477],
        [14.22393227]],

       [[16.31633759],
        [29.69265747],
        [25.40621376],
        ...,
        [28.50727081],
        [11.46302605],
        [ 4.04836655]],

       [[ 9.1305275 ],
        [10.00378227],
        [28.46733665],
        ...,
        [23.54629517],
        [20.91897202],
        [ 1.38314819]],

       ...,

       [[63.33175659],
        [66.34197998],
        [68.40023804],
        ...,
        [73.8707428 ],
        [68.64536285],
        [67.72910309]],

       [[67.61167908],
        [67.59188843],
        [66.96526337],
        ...,
        [70.63095856],
        [74.70448303],
        [72.90202332]],

       [[71.49047852],
        [74.54782104],
        [69.39613342],
        ...,
        [80.        ],
        [80.        ],
        [80.        ]]])

更新

我的数据集来自免费音乐档案

包括轨道音频数据 (.mp3) 和轨道元数据(流派、艺术家、...)

我选择了小版本(8000音轨),通过libROSA包转换成谱图。

就像这个链接Using CNNs and RNNs for Music Genre Recognition

但我只想先尝试 CNN 模型。

libROSA包转换后的频谱图大小为128*646。

行数据是这样的

array([[-65.06227 , -47.759537, -44.17627 , ..., -39.40817 , -41.736862,
        -25.19515 ],
       [-65.40295 , -52.76098 , -49.17935 , ..., -16.40555 , -16.314035,
        -17.56438 ],
       [-69.481834, -56.676388, -50.506615, ..., -16.358843, -16.072405,
        -18.807785],
       ...,
       [-79.42308 , -59.743004, -36.382896, ..., -46.371193, -42.364635,
        -50.037727],
       [-80.      , -63.419754, -41.73323 , ..., -50.383797, -46.90663 ,
        -55.136078],
       [-80.      , -73.820724, -52.94601 , ..., -63.188026, -56.469948,
        -60.473305]], dtype=float32)

我将该值除以 80 并计算这些频谱图的绝对值作为 CNN 模型输入

【问题讨论】:

问题不在于你的模型一直在预测同一个类,因为它根本没有学会区分类。看看预测[0.11161657 0.11246169 0.11564494 0.11465651 0.11153363 0.10664304 0.11097018 0.11052497 0.10594855]。它为所有类别提供相同的概率!您的代码似乎没问题。有时这是非常简单的事情,例如您尚未对图像进行归一化,并且使用的学习率非常小(即优化器的默认值)。 这里似乎没有什么问题。你能包括你的预处理步骤吗? 谢谢你的建议,我的输入图像值都在0到80的范围内,我还需要对这些数据进行归一化吗? 已经添加了预处理部分,希望对您有所帮助。 您的问题现在解决了吗?否则,您能否分享完整的代码或 google colab 文件以重现您的问题,以便我们为您提供帮助。谢谢! 【参考方案1】:

为了社区的利益,在此处(回答部分)提及解决方案(即使它出现在评论部分)。同时添加更多建议。

KernelsFilters 的数量增加到 50 以上,比如 64,提高了准确性。这是因为更多数量的Kernels/Filters 提高了Model 的表示能力,尤其是当数据不是很容易学习时。

为了改进Accuracy,Model可以从

model = Sequential()

model.add(Conv2D(32, kernel_size=(5,5), activation='relu',kernel_initializer='random_uniform', input_shape=(128,646,1)))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(BatchNormalization())
model.add(Conv2D(16, kernel_size=(5,5), activation='relu', input_shape=(64,321,1)))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(BatchNormalization())

model.add(Flatten())
model.add(Dense(16, activation = 'relu',kernel_initializer='normal'))
model.add(Dropout(0.5))
model.add(Dense(9, activation = 'softmax'))

model = Sequential()

model.add(Conv2D(64, kernel_size=(5,5), 
activation='relu',kernel_initializer='random_uniform', 
input_shape=(128,646,1))) # Increased the Number of Kernels in this Conv2D 
Layer
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(BatchNormalization())
model.add(Conv2D(64, kernel_size=(5,5), activation='relu', 
input_shape=(64,321,1))) # Increased the Number of Kernels in this Conv2D 
Layer
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(BatchNormalization())

model.add(Flatten())
model.add(Dense(256, activation = 'relu',
kernel_initializer='normal')) #Increased the Number of Neurons in this Dense 
Layer
model.add(Dropout(0.5))
model.add(Dense(9, activation = 'softmax'))

另外,Input Data 位于0 to 80 范围内。将其规范化为0 and 1 之间的值将导致更好的accuracy

一般预处理步骤如下所示:

from tensorflow.keras.preprocessing import image

Test_Dir = 'Dogs_Vs_Cats_Small/test/cats'
Image_File = os.path.join(Test_Dir, 'cat.1545.jpg')

Image = image.load_img(Image_File, target_size = (128,646))

Image_Tensor = image.img_to_array(Image)

Image_Tensor = tf.expand_dims(Image_Tensor, axis = 0)

Image_Tensor = Image_Tensor/255.0

希望这会有所帮助。快乐学习!

【讨论】:

以上是关于CNN模型在大多数情况下预测相同的值的主要内容,如果未能解决你的问题,请参考以下文章

LSTM 模型不会预测高于某个值的值(始终不是相同的值)

结合来自不同 CNN 模型的概率

PyTorch搭建CNN-LSTM混合模型实现多变量多步长时间序列预测(负荷预测)

机器学习回归模型为每张图像预测相同的值

Tensorflow.js 模型仅预测相同的值

CNN模型预测