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

时间:2018-05-03 13:16:01

标签: python machine-learning deep-learning keras conv-neural-network

我对Python和机器学习都很陌生,我正在开发我的第一个真正的图像识别项目。它基于this tutorial,它只有两个分类(猫或狗),并且有更多的数据。尽管如此,我没有让我的多类脚本正确地预测它,但主要是如何解决脚本问题。该脚本无法正确预测。

Examples of domino images in the training data

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

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
from keras.models import model_from_json
import numpy
import os

# Initialising the CNN
classifier = Sequential()

# Step 1 - Convolution
classifier.add(Conv2D(32, (25, 25), input_shape = (100, 100, 3), activation = 'relu'))

# Step 2 - Pooling
classifier.add(MaxPooling2D(pool_size = (2, 2)))

# Adding a second convolutional layer
classifier.add(Conv2D(32, (25, 25), activation = 'relu'))
classifier.add(MaxPooling2D(pool_size = (2, 2)))

# Step 3 - Flattening
classifier.add(Flatten())

# Step 4 - Full connection
classifier.add(Dense(units = 128, activation = 'relu'))
classifier.add(Dense(units = 7, activation = 'sigmoid')) # 7 units equals amount of output categories

# Compiling the CNN
classifier.compile(optimizer = 'adam', loss = 'categorical_crossentropy', metrics = ['accuracy'])


# Part 2 - Fitting the CNN to the images
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)
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()

# serialize weights to HDF5
classifier.save_weights("dominoweights.h5")
print("Saved model to disk")

# Part 3 - Making new predictions
import numpy as np
from keras.preprocessing import image

path = 'dataset/prediction_images/' # Folder with my 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())] # Get the index of the highest predicted value
    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. 我是否正确理解了卷积层,有一个25x25px的窗口可以扫描图像。我试过"默认" 3x3px,但结果相同?
  2. 卷积层中的数字32。它是指32位图像吗?
  3. 有2个卷积层是否正常?我无法真正理解为什么需要它。
  4. 整个部分包含:

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

  5. 让我感到困惑。据我所知,steps_per_epoch应该是我拥有的训练图像的数量。那是对的吗? epochs CNN的迭代次数是多少?

    1. 我不明白为什么需要此代码:

      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)

    2. 在我看来,它正在创建图像的副本/版本,放大它们,翻转它们等等。为什么需要它?

      任何关于此的提示都会对我有所帮助!

1 个答案:

答案 0 :(得分:2)

代码似乎没有任何明显的错误,但是大小为(25,25)的过滤器可能有些不好。

有两种可能性:

  • 培训指标很好,但测试指标很差:您的模型过度拟合(可能是由于数据很少)
  • 训练指标不好:你的模型不够好

<强>子问题:

1 - 是的,您正在使用沿着输入图像滑动的窗口大小(25,25)的过滤器。过滤器越大,它们就越不普遍。

2 - 数字32指的是多少输出&#34;频道&#34;你想要这个图层。当您的输入图像有3个通道,红色层,绿色层和蓝色层时,这些卷积层将产生32个不同的通道。每个频道的含义取决于我们无法看到的隐藏数学。

  • 频道数完全独立于任何事物。
  • 唯一的限制是:输入通道为3,输出类为7。

3 - 很多&#34;很多&#34;卷积层,一个在另一个上。一些众所周知的模型具有超过10个卷积层。

  • 为什么需要它?每个卷积层都在解释前一层的结果,并产生新的结果。它对模型的威力更大。一个可能太少了。

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

  • steps_per_epoch是必要的,因为使用的生成器是无限的(因此keras不知道何时停止)
  • 通常,人们使用steps_per_epoch = total_images//batch_size,因此一个纪元将使用所有图像。但是你可以随心所欲地使用这些数字
  • 通常,一个纪元是整个数据集的一次迭代。 (但是使用生成器和steps_per_epoch,这取决于用户)

5 - 图像数据生成器除了从您的文件夹加载数据并为您创建课程外,还是数据扩充的工具。

  • 如果你的数据太少,你的模型会过度拟合(优秀的训练结果,糟糕的测试结果)。
  • 机器学习需要大量数据才能正常运作
  • 数据扩充是一种在您没有足够数据时创建更多数据的方法
    • 在模型的视野中,移动,翻转,拉长等图像是全新的
    • 模型可以学习向右看的猫,但不会学习向左看的猫,例如