【问题标题】:Predicting single image using Tensorflow not being accurate使用 Tensorflow 预测单张图像不准确
【发布时间】:2021-09-27 09:23:11
【问题描述】:

我正在尝试构建一个 CNN 模型来对图像进行分类,但是每当训练完成并且我尝试为其提供单个图像(来自训练数据集)时,它总是会错误地分类该图像。

请看我下面写的代码。

提前谢谢你。

首先,我为我的训练集和测试集声明了一个图像数据生成器:

train_datagen = ImageDataGenerator(rescale = 1./255, rotation_range=20, horizontal_flip = True, 
validation_split=0.3)

test_datagen = ImageDataGenerator(rescale = 1./255,validation_split=0.3)

然后,我使用 flow_from_directory() 函数来加载图像:

train_generator = train_datagen.flow_from_directory(
data_dir,
shuffle=False,
subset='training',
target_size = (224, 224), 
class_mode = 'categorical'
)

test_generator = test_datagen.flow_from_directory(
data_dir,
shuffle=False,
subset='validation',
target_size = (224, 224),
class_mode = 'categorical'
)

然后我加载了一个预训练模型并添加了几层来构建我的模型:

pretrained_model = VGG16(weights="imagenet", include_top=False, 

input_tensor=input_shape)
pretrained_model.trainable = False

model = tf.keras.Sequential([
    pretrained_model,
    Flatten(name="flatten"),
    Dense(3, activation="softmax")
])

然后我训练了模型:

INIT_LR = 3e-4
EPOCHS = 15
opt = Adam(lr=INIT_LR)

model.compile(loss="categorical_crossentropy", optimizer='Adam', metrics=["accuracy"])

H = model.fit(
    train_generator,
    validation_data=test_generator,
    epochs=EPOCHS,
    verbose= 1)

然后是预测单个图像的部分:

我选择了一张属于训练集的图像,我什至过度拟合了模型以确保预测正确,但它给我输入到模型的每张图像都给出了错误的结果。

我尝试了以下方法:

image = image.load_img(url,target_size = (224, 224))
img = tf.keras.preprocessing.image.img_to_array(image)
img = np.array([img])
img = img.astype('float32') / 255.
img = tf.keras.applications.vgg16.preprocess_input(img)

这没用

image = cv2.imread(url)
image = cv2.normalize(image, None,beta=255, dtype=cv2.CV_32F)
image = cv2.resize(image, (224, 224))
image = np.expand_dims(image, axis=0)

这也不起作用,我还尝试了许多其他方法来预测单个图像,但都没有成功。

最后,唯一的方法是我必须为这个单一的图像创建一个图像数据生成器和来自目录的流,它确实有效,但我认为这不是应该的。

【问题讨论】:

    标签: python-3.x tensorflow keras conv-neural-network tf.keras


    【解决方案1】:

    这个答案可能是一个起点:

    Resnet50 produces different prediction when image loading and resizing is done with OpenCV

    这些是可能的差异(简短的要点):

    1. RGB vs BGROpenCV 加载 BGR)
    2. 使用的插值方法(INTER_LINEAR vs INTER_NEAREST)。
    3. img_to_array()将数据类型转换为float32,而不是uint8OpenCV加载时默认获取。
    4. tf.keras.applications.vgg16.preprocess_input(img)。这个预处理函数实际上可以不同于你上面写的图像预处理;还值得注意的是,如果您在以这种特殊方式 (preprocess_input()) 进行训练时不对其进行预处理,那么在测试集上得到不好的结果也是有意义的,因为预处理是不同的。

    希望这些观察能有所启发。

    【讨论】:

      【解决方案2】:

      代码 img = tf.keras.applications.vgg16.preprocess_input(img) 缩放像素 假设原始像素值在 0 到 255 范围内,则图像中的值在 -1 到 +1 之间。在上一行代码中

      img = img.astype('float32') / 255.
      

      您重新调整了像素。所以删除那行代码。现在要预测单个图像,您需要扩展尺寸

      img = np.expand_dims(img, axis=0) 
      

      在您的第二次代码工作中,请注意 CV2 将图像读取为 BGR。如果您的模型是在 RGB 图像上训练的,那么您的预测将是错误的。使用下面的代码将图像转换为 RGB。

      image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
      

      作为旁注,您可以将 tf.keras.applications.vgg16.preprocess_input(img) 替换为下面的函数,该函数将在 -1 到 +1 之间缩放图像

      def scalar(img):
          return img/127.5 - 1
      

      【讨论】:

        猜你喜欢
        • 2017-08-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多