TensorFlow二进制图像分类:预测数据集中每个图像的每个类别的概率

时间:2020-07-27 18:06:17

标签: python tensorflow image-processing classification

我正在为二进制图像分类构建TensorFlow模型。我有两个标签:“好”和“坏” 我希望模型应该为数据集中的每个图像输出图像,无论该图像是好是坏,并​​且以什么概率

例如,如果我提交1.jpg并假设它是“好”图像。然后,模型应预测1.jpg的概率为100%,好,概率为0%,则不好。

到目前为止,我已经能够提出以下建议

start = "2020-08-02T00:00:00Z";
month = moment(start).format("MMMM");
console.log(month) // <- August

上述模型的输出形状为1 x1。但是我认为这不会达到我的目的。

我正在以这种方式编译模型

model = tf.keras.models.Sequential([
  tf.keras.layers.Conv2D(16, (3,3), activation='relu', input_shape=(input_shape, input_shape, 3)),
  tf.keras.layers.MaxPool2D(2,2),
  #
  tf.keras.layers.Conv2D(32, (3,3), activation='relu'),
  tf.keras.layers.MaxPool2D(2,2),
  #
  tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
  tf.keras.layers.MaxPool2D(2,2),
  ##
  tf.keras.layers.Flatten(),
  ##
  tf.keras.layers.Dense(512, activation='relu'),
  ##
  tf.keras.layers.Dense(1, activation='sigmoid')
])

非常感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

您不必使模型输出“好”和“差”作为标签,而是可以分别输出每个概率,换句话说,图像的概率为图像不好。使最后一层的输出大小为2。因此,您的模型现在将输出一个二维矢量,使得[1.0,0.0]表示100%良好和0%不良,而[0.0,1.0]表示0%良好和100%糟糕。使用二元交叉熵作为训练的损失函数。当然,您必须类似地标记训练数据,因此,如果您有一个好的训练示例,则将其标记为[1.0,0.0],因为您100%确信它是好的,而如果您有一个不良的训练示例,则将其标记为[1.0,0.0] [0.0,1.0],因为您也100%确信这是一个不好的例子。

我告诉您使用二元交叉熵作为损失函数的原因是,该模型将学习输出2维矢量输出分量的相反概率。因此,如果图像质量好,则第一个成分会变高,第二个成分会变低,反之亦然。另外,经过训练后,进行预测时,您只会采用两者中的最高概率,如果较高的概率是第一个,则它是“好”图像,并且您仅使用该概率。

答案 1 :(得分:1)

万一有人在寻找答案,下面是用于模型生成的python代码

这里要注意的一些要点是

  1. 输入图像的形状为360x360x3
  2. 最后一层的
  3. 激活功能是“ softmax ”,而不是“ Sigmoid
  4. 损失函数是“ sparse_categorical_crossentropy ”,而不是“ binary_crossentropy
  5. 输出形状为2而不是1

请注意#2,#3和#4,即使我试图提出二进制图像分类模型。我的最终目标是将该模型转换为TensorFlow Lite版本,并在Android应用程序中使用TensorFlow Lite模型。

更早之前,当我在最后一层使用“ Sigmoid”并将“ binary_crossentropy”用作损失函数时,最后一层的输出形状不能大于1。

结果是,当我在Android应用程序中使用从该TensorFlow模型生成的Lite模型时,出现了下面提到的错误

“找不到要标记的轴。要标记的有效轴应具有尺寸 大于1“

通过#2,#3和#4中提到的更改,生成的Lite模型可以在Android上正常工作。

import tensorflow as tf
import matplotlib.pyplot as plt
import cv2
import os
import numpy as np
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.preprocessing import image
from tensorflow.keras.optimizers import RMSprop


print("version")
print(tf.__version__)

train = ImageDataGenerator(rescale=1/255)
validation = ImageDataGenerator(rescale=1/255)

input_shape = 360
train_dataset = train.flow_from_directory('container_images/train/',
                                          target_size=(input_shape,input_shape),
                                          batch_size=3,
                                          classes=['good', 'bad'],
                                          class_mode='binary')

validation_dataset = train.flow_from_directory('container_images/validation/',
                                          target_size=(input_shape,input_shape),
                                          batch_size=3,
                                          classes=['good', 'bad'],
                                          class_mode='binary')

print(train_dataset.class_indices)
model = tf.keras.models.Sequential([
    tf.keras.layers.Conv2D(16, (3,3), activation='relu', input_shape=(input_shape, input_shape, 3)),
    tf.keras.layers.MaxPool2D(2,2),
    #
    tf.keras.layers.Conv2D(32, (3,3), activation='relu'),
    tf.keras.layers.MaxPool2D(2,2),
    #
    tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
    tf.keras.layers.MaxPool2D(2,2),
    ##
    tf.keras.layers.Flatten(),
    ##
    tf.keras.layers.Dense(512, activation='relu'),
    ##
    tf.keras.layers.Dense(2, activation='softmax')
])

model.compile(loss='sparse_categorical_crossentropy',
              optimizer=RMSprop(lr=0.001),
              metrics=['accuracy'])
model_fit = model.fit(train_dataset,
                      steps_per_epoch=3,
                      epochs=30,
                      validation_data=validation_dataset)