在每个 epoch 之后,准确性保持不变
Posted
技术标签:
【中文标题】在每个 epoch 之后,准确性保持不变【英文标题】:Accuracy remains constant after every epoch 【发布时间】:2020-05-01 13:44:32 【问题描述】:我已经创建了一个模型来对飞机和汽车图像进行分类,但是在 acc 和 val_acc 保持相同的时代之后
import numpy as np
import matplotlib as plt
from keras.models import Sequential
from keras.layers import Convolution2D
from keras.layers import MaxPooling2D
from keras.layers import Flatten
from keras.layers import Dense
from keras.preprocessing.image import ImageDataGenerator
from keras.preprocessing.image import image
import os
model=Sequential()
model.add(Convolution2D(32,(3,3),input_shape=(64,64,3),activation="relu"))
model.add(MaxPooling2D(2,2))
model.add(Convolution2D(64,(3,3),activation="relu"))
model.add(MaxPooling2D(2,2))
model.add(Convolution2D(64,(3,3),activation="sigmoid"))
model.add(MaxPooling2D(2,2))
model.add(Flatten())
model.add(Dense(32,activation="sigmoid"))
model.add(Dense(32,activation="sigmoid"))
model.add(Dense(32,activation="sigmoid"))
model.add(Dense(1,activation="softmax"))
model.compile(optimizer='adam', loss='binary_crossentropy',
metrics=['accuracy'])
train_datagen = ImageDataGenerator(
rescale=1./255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
test_datagen = ImageDataGenerator(rescale=1./255)
train_set = train_datagen.flow_from_directory( 'train_images', 目标尺寸=(64,64), 批量大小=32, class_mode='二进制')
test_set = train_datagen.flow_from_directory( 'val_set', 目标尺寸=(64,64), 批量大小=32, class_mode='二进制')
model.fit_generator( 动车组, step_per_epoch=160, 时期=25, 验证数据=测试集, 验证步骤=40)
Epoch 1/25
30/30 [==============================] - 18s 593ms/step - loss: 7.9712 - acc: 0.5000 - val_loss:
7.9712 - val_acc: 0.5000
Epoch 2/25
30/30 [==============================] - 15s 491ms/step - loss: 7.9712 - acc: 0.5000 - val_loss:
7.9712 - val_acc: 0.5000
Epoch 3/25
30/30 [==============================] - 19s 640ms/step - loss: 7.9712 - acc: 0.5000 - val_loss:
7.9712 - val_acc: 0.5000
Epoch 4/25
30/30 [==============================] - 14s 474ms/step - loss: 7.9712 - acc: 0.5000 - val_loss:
7.9712 - val_acc: 0.5000
Epoch 5/25
30/30 [==============================] - 16s 532ms/step - loss: 7.9712 - acc: 0.5000 - val_loss:
7.9712 - val_acc: 0.5000
Epoch 6/25
30/30 [==============================] - 14s 473ms/step - loss: 7.9712 - acc: 0.5000 - val_loss:
7.9712 - val_acc: 0.5000
Epoch 7/25
30/30 [==============================] - 14s 469ms/step - loss: 7.9712 - acc: 0.5000 - val_loss:
7.9712 - val_acc: 0.5000
Epoch 8/25
30/30 [==============================] - 14s 469ms/step - loss: 7.9712 - acc: 0.5000 - val_loss:
7.9712 - val_acc: 0.5000
Epoch 9/25
30/30 [==============================] - 14s 472ms/step - loss: 7.9712 - acc: 0.5000 - val_loss:
7.9712 - val_acc: 0.5000
Epoch 10/25
30/30 [==============================] - 16s 537ms/step - loss: 7.9712 - acc: 0.5000 - val_loss:
7.9712 - val_acc: 0.5000
Epoch 11/25
30/30 [==============================] - 18s 590ms/step - loss: 7.9712 - acc: 0.5000 - val_loss:
7.9712 - val_acc: 0.5000
Epoch 12/25
30/30 [==============================] - 13s 441ms/step - loss: 7.9712 - acc: 0.5000 - val_loss:
7.9712 - val_acc: 0.5000
Epoch 13/25
30/30 [==============================] - 11s 374ms/step - loss: 7.9712 - acc: 0.5000 - val_loss:
7.9712 - val_acc: 0.5000
Epoch 14/25
30/30 [==============================] - 11s 370ms/step - loss: 7.9712 - acc: 0.5000 - val_loss:
7.9712 - val_acc: 0.5000
Epoch 15/25
30/30 [==============================] - 13s 441ms/step - loss: 7.9712 - acc: 0.5000 - val_loss:
7.9712 - val_acc: 0.5000
Epoch 16/25
30/30 [==============================] - 13s 419ms/step - loss: 7.9712 - acc: 0.5000 - val_loss:
7.9712 - val_acc: 0.5000
Epoch 17/25
30/30 [==============================] - 12s 401ms/step - loss: 7.9712 - acc: 0.5000 - val_loss:
7.9712 - val_acc: 0.5000
Epoch 18/25
30/30 [==============================] - 16s 536ms/step - loss: 7.9712 - acc: 0.5000 - val_loss:
7.9712 - val_acc: 0.5000
Epoch 19/25
30/30 [==============================] - 16s 523ms/step - loss: 7.9712 - acc: 0.5000 - val_loss:
7.9712 - val_acc: 0.5000
Epoch 20/25
30/30 [==============================] - 16s 530ms/step - loss: 7.9712 - acc: 0.5000 - val_loss:
7.9712 - val_acc: 0.5000
Epoch 21/25
30/30 [==============================] - 16s 546ms/step - loss: 7.9712 - acc: 0.5000 - val_loss:
7.9712 - val_acc: 0.5000
Epoch 22/25
30/30 [==============================] - 15s 500ms/step - loss: 7.9712 - acc: 0.5000 - val_loss:
7.9712 - val_acc: 0.5000
Epoch 23/25
30/30 [==============================] - 16s 546ms/step - loss: 7.9712 - acc: 0.5000 - val_loss:
7.9712 - val_acc: 0.5000
Epoch 24/25
30/30 [==============================] - 16s 545ms/step - loss: 7.9712 - acc: 0.5000 - val_loss:
7.9712 - val_acc: 0.5000
Epoch 25/25
30/30 [==============================] - 15s 515ms/step - loss: 7.9712 - acc: 0.5000 - val_loss:
7.9712 - val_acc: 0.5000
【问题讨论】:
这是因为模型没有学习。中间层的梯度是相同的。为什么你在中间层使用sigmoid
而不是relu
?
其实是因为softmax。在使用 binary_crossentropy 时,我们应该使用 sigmoid。
并且当使用 sigmoid 代替 relu 时,模型会学习,但准确率会在 50% 左右
【参考方案1】:
您的模型结构存在几个问题。
首先,对于模型的输出model.add(Dense(1,activation="softmax"))
您使用的是 softmax,这意味着您尝试解决多类分类,而不是二元分类。如果真的是这样,你需要把你的损失改成categorical_crossentropy
。这样编译行会变成:
model.compile(optimizer='adam', loss='categorical_crossentropy',
metrics=['accuracy'])
如果不是这种情况并且您只想解决二进制分类,您可能会很好,但我建议将最后一层激活更改为sigmoid
sigmoid
作为中间层的激活是一个坏主意,因为它很容易导致梯度消失(阅读更多here)。尝试使用relu
更改中间层中的所有sigmoid
激活,或者使用leakyrelu
甚至更好
【讨论】:
是的,是的,我还在学习,所以我只是在玩我的模型【参考方案2】:问题就在这里:
model.add(Dense(1,activation="softmax"))
你不能对一个神经元使用softmax
,因为它会在神经元上进行归一化,这意味着对于一个神经元,它总是会产生一个恒定的 1.0 值。对于二进制分类,您必须在输出中使用sigmoid
激活:
model.add(Dense(1,activation="sigmoid"))
在隐藏层中使用sigmoid
激活也是不明智的,因为它们会产生梯度消失问题。请首选ReLU
或类似的激活方式。
【讨论】:
是的,我明白了。以上是关于在每个 epoch 之后,准确性保持不变的主要内容,如果未能解决你的问题,请参考以下文章