如何将图像输入 CNN 以进行二元分类

Posted

技术标签:

【中文标题】如何将图像输入 CNN 以进行二元分类【英文标题】:How to feed images into a CNN for binary classification 【发布时间】:2021-05-24 00:45:13 【问题描述】:

我正在尝试创建一个卷积神经网络,该网络可以根据一个人的面部图片检测一个人是否中风。我的数据集的图像包含在一个名为 CNNImages 的目录中,该目录包含两个子目录:StrokesRegularFaces。每个子目录都包含我试图输入神经网络的 jpg 图像。

按照this tutorial 中使用的方法,我创建了 CNN,它在输入 MNIST 数据集时可以工作。但是,我无法将自己的图像输入神经网络。我一直在使用Keras tutorial 显示的代码进行图像数据预处理,但它不起作用。

import tensorflow as tf
import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
import numpy as np
 
dataset = tf.keras.preprocessing.image_dataset_from_directory(
    'C:\\Users\\Colin\\CNNImages',
    labels="inferred",
    label_mode="int",
    class_names=None,
    color_mode="rgb",
    batch_size=32,
    image_size=(128, 128),
    shuffle=True,
    seed=1,
    validation_split=0.2,
    subset="training",
    interpolation="bilinear",
    follow_links=False,
)

当我尝试使用 (x_train, y_train), (x_test, y_test) = dataset 将此数据集输入我的神经网络时,我收到以下错误:

ValueError: too many values to unpack (expected 2)

我在下面的神经网络中包含了我的尝试。

batch_size = 128
num_classes = 2
epochs = 12

# input image dimensions
img_rows, img_cols = 128, 128

# the data, split between train and test sets
(x_train, y_train), (x_test, y_test) = dataset

x_train = x_train.reshape(869,128,128,3)
x_test = x_test.reshape(217,128,128,3)

print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')

# convert class vectors to binary class matrices
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3),
                 activation='relu',
                 input_shape=(28,28,1)))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))

model.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.Adadelta(),
              metrics=['accuracy'])

model.fit(x_train, y_train,
          batch_size=batch_size,
          epochs=epochs,
          verbose=1,
          validation_data=(x_test, y_test))
score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])

我认为我将图像错误地导入 CNN,但不确定如何解决此问题。让图像正确导入的解决方案是什么?

编辑:下面是我更新的代码尝试。由于(x_train, y_train), (x_test, y_test) = train_ds 返回ValueError: too many values to unpack (expected 2),它无法运行

import tensorflow as tf
import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
import numpy as np
 
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
  'C:\\Users\\Colin\\Desktop\\CNNImages\\Training',
  validation_split=None,
  subset=None,
  seed=123,
  image_size=(128, 128),
  batch_size=32)

val_ds = tf.keras.preprocessing.image_dataset_from_directory(
  'C:\\Users\\Colin\\Desktop\\CNNImages\\Validation',
  validation_split=None,
  subset=None,
  seed=123,
  image_size=(128, 128),
  batch_size=32)


batch_size = 128
num_classes = 2
epochs = 12

# input image dimensions
img_rows, img_cols = 128, 128

# the data, split between train and test sets
(x_train, y_train), (x_test, y_test) = train_ds

x_train = x_train.reshape(869,128,128,3)
x_test = x_test.reshape(217,128,128,3)

print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')

# convert class vectors to binary class matrices
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3),
                 activation='relu',
                 input_shape=(28,28,1)))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))

model.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.Adadelta(),
              metrics=['accuracy'])

model.fit(
  train_ds,
  validation_data=val_ds,
  epochs=3
)
score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])

【问题讨论】:

【参考方案1】:

(x_train, y_train), (x_test, y_test) = dataset 部分代码引发错误。因为,当您使用 tf.keras.preprocessing.image_dataset_from_director() 时,它会返回成批的图像,它不会将您的数据拆分为训练集和测试集。所以你需要单独声明训练和测试:

# first-approach
train_dataset = tf.keras.preprocessing.image_dataset_from_directory(train_folder, ...)
test_dataset = tf.keras.preprocessing.image_dataset_from_directory(test_folder, ...)

# second approach
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)

model.fit(
  train_ds,
  validation_data=val_ds,
  epochs=3
)

【讨论】:

所以要解决这个问题,我是否只需将训练和测试图像分离到两个子目录中,创建两个数据集,同时将 validation_split 和子集设置为 None,然后使用 @ 将训练数据集调用到 CNN 987654324@? 一种方法是yes 或者看答案,我更新了。 我在第二种方法中实现了两个数据集,并更改了 model.fit 以反映第二种方法中的数据集。为了让 CNN 正常工作,我应该向(x_train, y_train), (x_test, y_test) 输入什么内容?或者我应该用其他东西替换那条线? 你应该删除那行 x_train、y_train、x_test 和 y_test 都通过 CNN 广泛使用。当我删除所有提及它们时,代码无法运行。

以上是关于如何将图像输入 CNN 以进行二元分类的主要内容,如果未能解决你的问题,请参考以下文章

使用深度 CNN 和完全连接的分类器转换分割掩码 numpy 数组以进行图像分割

使用 CNN 进行癌症预测的分类

使用 Keras 稀疏分类交叉熵进行像素级多类分类

Tensorflor实现文本分类

深度学习1-理解卷积神经网络(CNN)

用CNN对文本处理,句子分类(简单理解卷积原理)