首页 > 解决方案 > 在图像识别任务中如何处理意外图像

问题描述

我正在尝试使用 Keras 开发图像分类器,我按照页面上的教程进行操作: https ://www.tensorflow.org/tutorials/images/classification?hl=en

仍然使用教程提供的花卉数据集,我尝试通过使用山羊照片进行预测来测试模型。结果是,预测认为山羊照片属于雏菊类别的占 70%。考虑到山羊的照片中没有雏菊,我认为这是不可能的。

这是我使用的代码:

import matplotlib.pyplot as plt
import numpy as np
import os
import PIL
import tensorflow as tf

from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.models import Sequential

import pathlib

dataset_url = "https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz"
data_dir = tf.keras.utils.get_file('flower_photos', origin=dataset_url, untar=True)
data_dir = pathlib.Path(data_dir)

image_count = len(list(data_dir.glob('*/*.jpg')))
print(image_count)

batch_size = 32
img_height = 180
img_width = 180

train_ds = tf.keras.preprocessing.image_dataset_from_directory(
    data_dir,
    validation_split=0.2,
    subset="training",
    seed=123,
    image_size=(img_height, img_width),
    batch_size=batch_size)

val_ds = tf.keras.preprocessing.image_dataset_from_directory(
    data_dir,
    validation_split=0.2,
    subset="validation",
    seed=123,
    image_size=(img_height, img_width),
    batch_size=batch_size)

class_names = train_ds.class_names
print(class_names)


AUTOTUNE = tf.data.experimental.AUTOTUNE

train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)

normalization_layer = layers.experimental.preprocessing.Rescaling(1./255)

normalized_ds = train_ds.map(lambda x, y: (normalization_layer(x), y))
image_batch, labels_batch = next(iter(normalized_ds))
first_image = image_batch[0]
# Notice the pixels values are now in `[0,1]`.
print(np.min(first_image), np.max(first_image))

# MODELLO
data_augmentation = keras.Sequential(
  [
    layers.experimental.preprocessing.RandomFlip("horizontal",
                                                 input_shape=(img_height,
                                                              img_width,
                                                              3)),
    layers.experimental.preprocessing.RandomRotation(0.1),
    layers.experimental.preprocessing.RandomZoom(0.1),
  ]
)

# MODIFICARE IN BASE A QUANTE CLASSI SI HANNO
num_classes = 5

model = Sequential([
  data_augmentation,
  layers.experimental.preprocessing.Rescaling(1./255),
  layers.Conv2D(16, 3, padding='same', activation='relu'),
  layers.MaxPooling2D(),
  layers.Conv2D(32, 3, padding='same', activation='relu'),
  layers.MaxPooling2D(),
  layers.Conv2D(64, 3, padding='same', activation='relu'),
  layers.MaxPooling2D(),
  layers.Dropout(0.2),
  layers.Flatten(),
  layers.Dense(128, activation='relu'),
  layers.Dense(num_classes)
])

model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])

model.summary()

epochs=15
history = model.fit(
  train_ds,
  validation_data=val_ds,
  epochs=epochs
)

acc = history.history['accuracy']
val_acc = history.history['val_accuracy']

loss = history.history['loss']
val_loss = history.history['val_loss']

epochs_range = range(epochs)

plt.figure(figsize=(8, 8))
plt.subplot(1, 2, 1)
plt.plot(epochs_range, acc, label='Training Accuracy')
plt.plot(epochs_range, val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')

plt.subplot(1, 2, 2)
plt.plot(epochs_range, loss, label='Training Loss')
plt.plot(epochs_range, val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()


#sunflower_url = "https://storage.googleapis.com/download.tensorflow.org/example_images/592px-#Red_sunflower.jpg"
#sunflower_path = tf.keras.utils.get_file('Red_sunflower', origin=sunflower_url)

img = keras.preprocessing.image.load_img(
    'C:\\Users\\matti\\PycharmProjects\\Tensorflow\\goat.jpg', target_size=(img_height, img_width)
)
img_array = keras.preprocessing.image.img_to_array(img)
img_array = tf.expand_dims(img_array, 0) # Create a batch

predictions = model.predict(img_array)
score = tf.nn.softmax(predictions[0])

print(
    "This image most likely belongs to {} with a {:.2f} percent confidence."
    .format(class_names[np.argmax(score)], 100 * np.max(score))
)

我正在使用 tensorflow 2.3.2 版本和上一个版本的其他库。

我该如何改进模型,以便如果它收到一张与它用于训练的类完全不同的照片,例如一张不是花的照片,它会给出等于 0% 的预测?

我需要一个解决方案,因为我正在尝试开发一个具有一组图像的系统,例如公司徽标的三类:正确、错误和可接受,如果它收到一个徽标,它必须将其分类到正确的类中。但是,如果它收到一张不是公司徽标的照片,它必须返回它不属于徽标集。

标签: pythontensorflowmachine-learningkerasdeep-learning

解决方案


由于您的模型已经在一组封闭的图像上进行了训练,因此它将采用其他类型的任何图像来适应它所学习的方案,并且通常它会成功。最后,输出概率只不过是给定图像中某些形状组合和颜色的概率,而不是您期望作为输出的抽象概念(要了解更多神经网络实际看到的内容,您可以阅读本文等:https ://www.kdnuggets.com/2016/06/peeking-inside-convolutional-neural-networks.html )

因此,您的问题的解决方案是教您的神经网络另一个类,一个补充类,由不是您的目标的各种通用图像组成。例如,您可以从 ImageNet ( http://image-net.org/ )获取图像以输入此类。通过这种方式,当您提供的图像不在您期望的目标范围内时,您将获得一个对抗性输出。

从技术上讲,关于您提供的代码,您只需要在您的培训和验证目录中创建一个进一步的目录,该目录包含您的额外类“其他”的混合图像。


推荐阅读