为什么这个CNN脚本无法正确预测?

我对Python和机器学习都还比较陌生,目前正在进行我的第一个图像识别真实项目。该项目基于这个教程,该教程只有两种分类(猫或狗)并且拥有大量数据。尽管如此,我无法让我的多类别脚本正常工作,主要问题在于它无法正确预测以及如何对脚本进行故障排除。脚本在预测方面完全不准确。

训练数据中的多米诺骨牌图片示例

以下是脚本。数据/图像由7个文件夹组成,每个文件夹包含大约10-15张图片。这些图片是100×100像素的不同多米诺骨牌,还有一个文件夹是婴儿照片(主要作为对照组,因为它们与多米诺照片非常不同):

from keras.models import Sequentialfrom keras.layers import Conv2Dfrom keras.layers import MaxPooling2Dfrom keras.layers import Flattenfrom keras.layers import Densefrom keras.models import model_from_jsonimport numpyimport os# 初始化CNNclassifier = Sequential()# 第一步 - 卷积classifier.add(Conv2D(32, (25, 25), input_shape = (100, 100, 3), activation = 'relu'))# 第二步 - 池化classifier.add(MaxPooling2D(pool_size = (2, 2)))# 添加第二个卷积层classifier.add(Conv2D(32, (25, 25), activation = 'relu'))classifier.add(MaxPooling2D(pool_size = (2, 2)))# 第三步 - 平铺classifier.add(Flatten())# 第四步 - 全连接classifier.add(Dense(units = 128, activation = 'relu'))classifier.add(Dense(units = 7, activation = 'sigmoid')) # 7个单位等于输出类别的数量# 编译CNNclassifier.compile(optimizer = 'adam', loss = 'categorical_crossentropy', metrics = ['accuracy'])# 第二部分 - 使CNN适应图像from keras.preprocessing.image import ImageDataGeneratortrain_datagen = ImageDataGenerator(rescale = 1./255,    shear_range = 0.2,    zoom_range = 0.2,    horizontal_flip = True)test_datagen = ImageDataGenerator(rescale = 1./255)training_set = train_datagen.flow_from_directory('dataset/training_set',    target_size = (100, 100),    batch_size = 32,    class_mode = 'categorical')test_set = test_datagen.flow_from_directory('dataset/test_set',    target_size = (100, 100),    batch_size = 32,    class_mode = 'categorical')classifier.fit_generator(training_set,    steps_per_epoch = 168,    epochs = 35,    validation_data = test_set,    validation_steps = 3)classifier.summary()# 将权重序列化为HDF5classifier.save_weights("dominoweights.h5")print("Saved model to disk")# 第三部分 - 进行新预测import numpy as npfrom keras.preprocessing import imagepath = 'dataset/prediction_images/' # 包含我的图片的文件夹for filename in os.listdir(path):  if "jpg" in filename:    test_image = image.load_img(path + filename, target_size = (100, 100))    test_image = image.img_to_array(test_image)    test_image = np.expand_dims(test_image, axis = 0)    result = classifier.predict(test_image)    print result    training_set.class_indices    folder = training_set.class_indices.keys()[(result[0].argmax())] # 获取最高预测值的索引    if folder == '1':      prediction = '1x3'    elif folder == '2':      prediction = '1x8'    elif folder == '3':      prediction = 'Baby'    elif folder == '4':      prediction = '5x7'    elif folder == '5':      prediction = 'Upside down'    elif folder == '6':      prediction = '2x3'       elif folder == '7':      prediction = '0x0'    else:      prediction = 'Unknown'    print "Prediction: " + filename + " seems to be " + prediction  else:    print "DSSTORE"  print "\n"

解释:

  • 训练数据:每个类别大约有10-15张图片。总共有168张训练图片
  • 测试数据:每个类别3张图片
  • dataset/prediction_images/包含大约10张不同的图片,脚本将对这些图片进行预测
  • result通常输出array([[0., 0., 1., 0., 0., 0., 0.]], dtype=float32)

我的问题

我的主要问题是:你是否在脚本中发现了明显的错误?或者,脚本应该正常工作,而预测错误只是由于数据不足造成的?

子问题:

  1. 我是否正确理解了卷积层?是否有一个25×25像素的窗口扫描图像?我尝试过“默认”的3×3像素,但结果相同?
  2. 卷积层中的数字32。它指的是32位图像吗?
  3. 有两个卷积层正常吗?我不太明白为什么需要这样做。
  4. 以下整个部分让我感到困惑:

    classifier.fit_generator(training_set,
    steps_per_epoch = 168,
    epochs = 35,
    validation_data = test_set,
    validation_steps = 3)

    据我所知,steps_per_epoch应该是我的训练图像数量。这是正确的吗?epochs是CNN进行的迭代次数吗?

  5. 我不明白为什么需要以下代码:

    from keras.preprocessing.image import ImageDataGenerator
    train_datagen = ImageDataGenerator(rescale = 1./255,
    shear_range = 0.2,
    zoom_range = 0.2,
    horizontal_flip = True)
    test_datagen = ImageDataGenerator(rescale = 1./255)

    对我来说,它似乎是在创建图像的副本/版本,对它们进行放大、翻转等操作。为什么需要这样做?

任何关于这方面的建议对我都将非常有帮助!


回答:

代码看起来似乎没有明显的错误,但大小为(25,25)的滤波器可能不太合适。

有两种可能的情况:

  • 训练指标很好,但测试指标不好:你的模型出现了过拟合(可能是由于数据量太少)
  • 训练指标不好:你的模型不够好

子问题:

1 – 是的,你使用的是大小为(25,25)的窗口作为滤波器,这些窗口会在输入图像上滑动。滤波器越大,它们的通用性就越差。

2 – 数字32指的是你希望这一层输出的“通道”数量。虽然你的输入图像有3个通道(红色层、绿色层和蓝色层),但这些卷积层将生成32个不同的通道。每个通道的含义取决于我们无法看到的隐藏数学运算。

  • 通道的数量完全独立于任何其他因素。
  • 唯一的限制是:输入通道为3,输出类别为7。

3 – 拥有“很多”卷积层是正常的,一个接着一个。一些著名的模型拥有超过10个卷积层。

  • 为什么需要这样做?每个卷积层都在解释前一层的输出,并生成新的结果。这为模型提供了更多的能力。一个卷积层可能太少了。

4 – 生成器生成的批次形状为(batch_size,image_side1, image_side2, channels)

  • steps_per_epoch是必要的,因为使用的生成器是无限的(因此Keras不知道何时停止)
  • 通常情况下,人们使用steps_per_epoch = total_images//batch_size,这样一个epoch将使用所有图像。但你可以随意调整这些数字
  • 通常情况下,一个epoch是对整个数据集进行一次迭代。(但使用生成器和steps_per_epoch后,这取决于用户)

5 – 图像数据生成器除了从你的文件夹加载数据并为你创建类别外,还是一种数据增强工具。

  • 如果你数据太少,你的模型会过拟合(训练结果非常好,测试结果非常差)。
  • 机器学习需要大量数据才能正常工作
  • 数据增强是在你没有足够数据时创造更多数据的一种方式
    • 在模型看来,移动、翻转、拉伸等后的图像完全是新的
    • 例如,一个模型可以学会识别向右看的猫,但可能学不会识别向左看的猫

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注