我正在使用下面的LeNet架构来训练我的图像分类模型,我注意到每次迭代的训练,val的准确性都没有提高。任何一个在这方面的专业知识,可以解释什么可能已经出了问题?
训练样本--110张属于2类的图像.验证--50张属于2类的图像。
#LeNet
import keras
from keras.models import Sequential
from keras.layers import Conv2D
from keras.layers import MaxPooling2D
from keras.layers import Flatten
from keras.layers import Dense
#import dropout class if needed
from keras.layers import Dropout
from keras import regularizers
model = Sequential()
#Layer 1
#Conv Layer 1
model.add(Conv2D(filters = 6,
kernel_size = 5,
strides = 1,
activation = 'relu',
input_shape = (32,32,3)))
#Pooling layer 1
model.add(MaxPooling2D(pool_size = 2, strides = 2))
#Layer 2
#Conv Layer 2
model.add(Conv2D(filters = 16,
kernel_size = 5,
strides = 1,
activation = 'relu',
input_shape = (14,14,6)))
#Pooling Layer 2
model.add(MaxPooling2D(pool_size = 2, strides = 2))
#Flatten
model.add(Flatten())
#Layer 3
#Fully connected layer 1
model.add(Dense(units=128,activation='relu',kernel_initializer='uniform'
,kernel_regularizer=regularizers.l2(0.01)))
model.add(Dropout(rate=0.2))
#Layer 4
#Fully connected layer 2
model.add(Dense(units=64,activation='relu',kernel_initializer='uniform'
,kernel_regularizer=regularizers.l2(0.01)))
model.add(Dropout(rate=0.2))
#layer 5
#Fully connected layer 3
model.add(Dense(units=64,activation='relu',kernel_initializer='uniform'
,kernel_regularizer=regularizers.l2(0.01)))
model.add(Dropout(rate=0.2))
#layer 6
#Fully connected layer 4
model.add(Dense(units=64,activation='relu',kernel_initializer='uniform'
,kernel_regularizer=regularizers.l2(0.01)))
model.add(Dropout(rate=0.2))
#Layer 7
#Output Layer
model.add(Dense(units = 2, activation = 'softmax'))
model.compile(optimizer = 'adam', loss = 'categorical_crossentropy', metrics = ['accuracy'])
from keras.preprocessing.image import ImageDataGenerator
#Image Augmentation
train_datagen = ImageDataGenerator(
rescale=1./255, #rescaling pixel value bw 0 and 1
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
#Just Feature scaling
test_datagen = ImageDataGenerator(rescale=1./255)
training_set = train_datagen.flow_from_directory(
'/Dataset/Skin_cancer/training',
target_size=(32, 32),
batch_size=32,
class_mode='categorical')
test_set = test_datagen.flow_from_directory(
'/Dataset/Skin_cancer/testing',
target_size=(32, 32),
batch_size=32,
class_mode='categorical')
model.fit_generator(
training_set,
steps_per_epoch=50, #number of input (image)
epochs=25,
validation_data=test_set,
validation_steps=10) # number of training sample
Epoch 1/25
50/50 [==============================] - 52s 1s/step - loss: 0.8568 - accuracy: 0.4963 - val_loss: 0.7004 - val_accuracy: 0.5000
Epoch 2/25
50/50 [==============================] - 50s 1s/step - loss: 0.6940 - accuracy: 0.5000 - val_loss: 0.6932 - val_accuracy: 0.5000
Epoch 3/25
50/50 [==============================] - 48s 967ms/step - loss: 0.6932 - accuracy: 0.5065 - val_loss: 0.6932 - val_accuracy: 0.5000
Epoch 4/25
50/50 [==============================] - 50s 1s/step - loss: 0.6932 - accuracy: 0.4824 - val_loss: 0.6933 - val_accuracy: 0.5000
Epoch 5/25
50/50 [==============================] - 49s 974ms/step - loss: 0.6932 - accuracy: 0.4949 - val_loss: 0.6932 - val_accuracy: 0.5000
Epoch 6/25
50/50 [==============================] - 51s 1s/step - loss: 0.6932 - accuracy: 0.4854 - val_loss: 0.6931 - val_accuracy: 0.5000
Epoch 7/25
50/50 [==============================] - 49s 976ms/step - loss: 0.6931 - accuracy: 0.5015 - val_loss: 0.6918 - val_accuracy: 0.5000
Epoch 8/25
50/50 [==============================] - 51s 1s/step - loss: 0.6932 - accuracy: 0.4986 - val_loss: 0.6932 - val_accuracy: 0.5000
Epoch 9/25
50/50 [==============================] - 49s 973ms/step - loss: 0.6932 - accuracy: 0.5000 - val_loss: 0.6929 - val_accuracy: 0.5000
Epoch 10/25
50/50 [==============================] - 50s 1s/step - loss: 0.6931 - accuracy: 0.5044 - val_loss: 0.6932 - val_accuracy: 0.5000
Epoch 11/25
50/50 [==============================] - 49s 976ms/step - loss: 0.6931 - accuracy: 0.5022 - val_loss: 0.6932 - val_accuracy: 0.5000
Epoch 12/25
最重要的是,你正在使用 loss = 'categorical_crossentropy'
,将其改为 loss = 'binary_crossentropy'
因为你只有2个班。而且还改变 class_mode='categorical'
到 class_mode='binary'
在 flow_from_directory
.
正如@desertnaut正确地提到的。categorical_crossentropy
并驾齐驱 softmax
最后一层的激活,如果你把损失改为 binary_crossentropy
最后一次激活也应改为 sigmoid
.
其他改进。
horizontal_flip
, vertical_flip
, shear_range
,ImageDataGenerator的zoom_range来增加训练和验证图像的数量。按照 @desertnaut 的建议,将评论移到答案区 -------------------------。
问题 - 谢谢! 是的,我想的问题是数据少。有一个额外的问题--为什么增加更多的致密层会对模型产生负面影响,当我们决定使用多少个致密层和密集层时,有什么规则可以遵循吗?- Arun_Ramji_Shanmugam 2天前
回答 - 回答你问题的第一部分,Conv2D层保持了图像的空间信息,需要学习的权重取决于层中提到的内核大小和步长,而密集层需要将Conv2D的输出进行扁平化处理并进一步使用,因此失去了空间信息。此外,密集层还增加了更多的权重,例如2个512的密集层会给模型增加(512*512)=262144个参数或权重(必须由模型学习).这意味着你必须训练更多的纪元数,并以良好的炒作参数设置来学习这些权重。- Tensorflow战士 2天前
回答 - 回答你问题的第二部分,使用系统化的实验来发现什么是最适合你的特定数据集的。另外,这也取决于你所拥有的处理能力。请记住,更深的网络总是更好的,代价是更多的数据和增加学习的复杂性。 传统的方法是寻找类似的问题和已经被证明有效的深度学习架构。同时我们还可以灵活地利用预训练的模型,如resnet、vgg等,通过冻结部分层和在剩余层上训练来使用这些模型。- Tensorflow战士 2天前
问题 - 谢谢你的详细回答! 如果你不嫌麻烦的话,还有一个问题--当我们使用已经训练好的模型(可能是一些层)时,是不是需要在相同的输入数据上进行训练,作为我们要工作的模型?- Arun_Ramji_Shanmugam yesterday
答案 - 图像分类的转移学习背后的直觉是,如果在一个足够大和通用的数据集上训练一个模型,这个模型将有效地作为视觉世界的通用模型。 你可以在这里找到转移学习的例子与解释 - tensorflow.orgtutorialsimagestransfer_learning 。
移除 都 kernel_initializer='uniform'
的参数;不要在这里指定任何东西,你的 默认 初始化器 glorot_uniform
是极力推荐的一款(和 uniform
是一个特别糟糕的设置)。)
一般来说,请记住,这种相当高级的设置的默认值是为了方便你,它们是隐含的推荐值,你最好不要乱用它们,除非你有特殊的原因,而且你知道你在做什么。
对于 kernel_initializer
特别是争论,我已经开始相信它给人们带来了很多不必要的痛苦(参见:1. 此处 为最新的例子)。)
另外,默认情况下不应该使用 dropout,特别是在像这里这样的情况下,模型似乎在努力学习任何东西;开始时不要使用任何 dropout(注释出相应的层),只有当你看到过度拟合的迹象时才将其添加回来。