我对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)
我的问题
我的主要问题是:你是否在脚本中发现了明显的错误?或者,脚本应该正常工作,而预测错误只是由于数据不足造成的?
子问题:
- 我是否正确理解了卷积层?是否有一个25×25像素的窗口扫描图像?我尝试过“默认”的3×3像素,但结果相同?
- 卷积层中的数字32。它指的是32位图像吗?
- 有两个卷积层正常吗?我不太明白为什么需要这样做。
-
以下整个部分让我感到困惑:
classifier.fit_generator(training_set,
steps_per_epoch = 168,
epochs = 35,
validation_data = test_set,
validation_steps = 3)
据我所知,
steps_per_epoch
应该是我的训练图像数量。这是正确的吗?epochs
是CNN进行的迭代次数吗? -
我不明白为什么需要以下代码:
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 – 图像数据生成器除了从你的文件夹加载数据并为你创建类别外,还是一种数据增强工具。
- 如果你数据太少,你的模型会过拟合(训练结果非常好,测试结果非常差)。
- 机器学习需要大量数据才能正常工作
- 数据增强是在你没有足够数据时创造更多数据的一种方式
- 在模型看来,移动、翻转、拉伸等后的图像完全是新的
- 例如,一个模型可以学会识别向右看的猫,但可能学不会识别向左看的猫