我是机器学习和TensorFlow的新手。我正在尝试构建一个CNN来对好的图像和损坏的图像进行分类,类似于TensorFlow中的石头剪刀布教程,只是我只有两个类别。
模型架构
train_generator = training_datagen.flow_from_directory( TRAINING_DIR, target_size=(150,150), class_mode='categorical')validation_generator = validation_datagen.flow_from_directory( VALIDATION_DIR, target_size=(150,150), class_mode='categorical')model = tf.keras.models.Sequential([ # 注意输入形状是期望的图像大小150x150,3字节颜色 # 这是第一个卷积层 tf.keras.layers.Conv2D(64, (3,3), activation='relu', input_shape=(150, 150, 3)), tf.keras.layers.MaxPooling2D(2, 2), # 第二个卷积层 tf.keras.layers.Conv2D(64, (3,3), activation='relu'), tf.keras.layers.MaxPooling2D(2,2), # 第三个卷积层 tf.keras.layers.Conv2D(128, (3,3), activation='relu'), tf.keras.layers.MaxPooling2D(2,2), # 第四个卷积层 tf.keras.layers.Conv2D(128, (3,3), activation='relu'), tf.keras.layers.MaxPooling2D(2,2), # 将结果展平以输入到DNN tf.keras.layers.Flatten(), tf.keras.layers.Dropout(0.5), # 512个神经元的隐藏层 tf.keras.layers.Dense(512, activation='relu'), tf.keras.layers.Dense(2, activation='softmax')])model.summary()model.compile(loss = 'categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy'])history = model.fit_generator(train_generator, epochs=25, validation_data = validation_generator, verbose = 1)model.save("rps.h5")
我唯一做的改变是将输入形状从(150,150,1)改为(150,150,3),并将最后一个层的输出从3个神经元改为2个。训练给我带来了每个类别600张图像的数据集上持续超过90%的准确率。但是当我使用教程中的代码进行预测时,即使是对数据集中图片,也会得到非常错误的值。
预测
TensorFlow教程中的原始代码
for file in onlyfiles: path = fn img = image.load_img(path, target_size=(150, 150,3)) # 将target_size从(150,150)改为(150, 150,3)) x = image.img_to_array(img) x = np.expand_dims(x, axis=0) images = np.vstack([x]) classes = model.predict(images, batch_size=10) print(fn) print(classes)
我认为由于我的输入是三通道图像,所以我将target_size从(150,150)改为(150, 150,3)),
结果
它给出了非常错误的值[0,1][0,1],即使是数据集中的图片
但是当我将代码改为如下时
for file in onlyfiles: path = fn img = image.load_img(path, target_size=(150, 150,3)) x = image.img_to_array(img) x = np.expand_dims(x, axis=0) x /= 255. classes = model.predict(images, batch_size=10) print(fn) print(classes)
在这种情况下,值看起来像这样
[[9.9999774e-01 2.2242968e-06]] [[9.9999785e-01 2.1864464e-06]] [[9.9999785e-01 2.1641024e-06]]
可能有一两个错误,但整体上非常正确
所以我的问题是,尽管最后的激活函数是softmax,为什么现在得到的是小数值,我在进行预测的方式上是否有逻辑错误?我也试过二进制分类,但没有发现太大区别。
回答:
请注意 –
- 当你将输出类别从2改为3时,你是在要求模型分类成3个类别。这与你的问题陈述相矛盾,你的问题是区分好的和损坏的图像,即2个输出类别(一个二元问题)。我认为如果我理解问题正确的话,可以将它从3改回2。
- 其次,你得到的输出完全正确,神经网络模型输出的是概率而不是绝对的类别值,如0或1。通过概率,它告诉我们某一图像属于类别0或类别1的可能性有多大。
- 另外,如上所述,@BBloggsbott提到 – 你只需对输出数组使用np.argmax,它会默认告诉你属于类别1(正类)的概率。希望这对你有帮助。谢谢。