CNN图像二进制分类的准确率达到50%

时间:2020-06-18 15:53:38

标签: python keras sequential

我有张开着眼睛和闭着眼睛的图像。
使用keras通过以下方式从当前目录收集数据:

batch_size = 64
N_images = 84898 #total number of images
datagen = ImageDataGenerator(
    rescale=1./255)
data_iterator = datagen.flow_from_directory(
    './Eyes',
    shuffle = 'False',
    color_mode='grayscale',
    target_size=(h, w),
    batch_size=batch_size,
    class_mode = 'binary')

我有一个具有每只眼睛状态的.csv文件。

我已经建立了这个顺序模型:

num_filters = 8
filter_size = 3
pool_size = 2

model = Sequential([
  Conv2D(num_filters, filter_size, input_shape=(90, 90, 1)),
  MaxPooling2D(pool_size=pool_size),
  Flatten(),
  Dense(16, activation='relu'),
  Dense(2, activation='sigmoid'), # Two classes. one for "open" and another one for "closed"
])

模型编译。

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

最后,我将所有数据拟合为以下内容:

model.fit(
  train_images,
  to_categorical(train_labels),
  epochs=3,
  validation_data=(test_images, to_categorical(test_labels)),
)

结果波动约50%,我不明白为什么。

1 个答案:

答案 0 :(得分:1)

您当前的模型实质上具有一个卷积层。也就是说,num_filters卷积滤波器(在这种情况下为3 x 3数组)的定义和拟合度使得当它们与图像卷积时,它们会产生在类之间尽可能具有区别性的特征。然后,您可以执行maxpooling来稍微减小输出CNN要素的尺寸,然后再传递到2个密集层。

我首先要说一个卷积层几乎可以肯定是不够的,尤其是对于3x3滤镜。基本上,通过单个卷积层,您可以获得的最有意义的信息是边或线。这些功能对于函数逼近器(即完全连接的图层)仅比原始像素强度值稍微有用,因为它们在类内和类间仍然具有极高的可变性。考虑到将眼睛图像向左移动2个像素会导致从1层CNN输出的值完全不同。您希望CNN的输出在缩放,旋转,照明等方面不变。

在实践中,这意味着您将需要更多的卷积层。相对简单的VGG网络至少具有14个卷积层,而基于现代残差层的网络通常具有100多个卷积层。尝试编写例程来依次定义更复杂的网络,直到开始看到性能提升为止。

作为第二要点,通常您不想在训练期间在最终层输出上使用sigmoid()激活功能。这会使梯度变平,并且使向后传播损失的速度变慢得多。实际上,您实际上并不关心输出值在0到1之间,而只关心它们的相对大小。通常的做法是使用交叉熵损失,它已经将对数softmax函数(梯度比正常softmax更稳定)和负对数似然损失相结合,就像您已经做过的那样。因此,由于对数softmax部分将输出值转换为所需的范围,因此无需使用S型激活函数。