如何将图像输入 CNN

时间:2021-02-17 15:48:30

标签: python tensorflow keras conv-neural-network tf.data.dataset

我是 tensorflow 的新手,正在尝试创建一个用于二元分类的卷积神经网络,该网络可以区分正常人脸和中风患者的人脸。

我的数据集的图像包含在名为 CNNImages 的目录中,并包含两个子目录:RegularFacesStrokes。每个子目录中都有我试图输入神经网络的 PNG 图像。

按照此参考文献中建议的方法:https://towardsdatascience.com/build-your-own-convolution-neural-network-in-5-mins-4217c2cf964f,我已经成功地使用 Spyder 创建了神经网络本身,该网络在使用 mnist.load_data() 运行时有效。

但是,我在使用 tf.data.Dataset 将我自己的图像上传到神经网络时遇到了问题。当我尝试在我创建的图像数据库上训练我的神经网络时,它返回一个 ValueError 并指出“解包的值太多(预期为 2)”。我相信我要么错误地调用了我的数据库,要么在创建数据库时搞砸了。

import tensorflow as tf
import os
import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
import numpy as np

os.chdir("/Users/Colin/CNNImages")

files = tf.data.Dataset.list_files("/Users/Colin/CNNImages/*/*.png")

def load_images(path):
    image = tf.io.read_file(path)
    image = tf.io.decode_jpeg(image)
    image = tf.image.convert_image_dtype(image, tf.float32)
    image = tf.image.resize(image, (128, 128))

    parts = tf.strings.split(path, os.path.sep)
    bool_values = tf.equal(parts[-2], 'strokes')
    indices = tf.cast(bool_values, tf.int32)
    return image, indices

ds = files.map(load_images).batch(1)

next(iter(ds))

"""
Above: Image Formatter
Below: CNN
"""


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) = 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(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])

当我为 (x_train, y_train), (x_test, y_test) = ds 调用 ds 时,我收到 ValueError,指出“解包的值太多(预期为 2)”。我把那条线弄乱了吗?还是我的 tf 数据集设计不当?

1 个答案:

答案 0 :(得分:0)

tf.data.Dataset 的每个元素都是一个元组 (img,label)。如果要创建验证拆分,则应使用 takeskip 来创建它。您也不能像稍后在脚本中所做的那样重塑和应用函数到 Dataset


要在数据集上创建训练/验证拆分,请使用 skiptake

# number of element in the validation dataset
n_elem_validation_ds = 267 
val_ds = ds.take(n_elem_validation_ds)
train_ds = ds.skip(n_elem_validation_ds)

要将函数应用于数据集,请使用 map :

# convert class vectors to binary class matrices
helper_categorical = lambda x: keras.utils.to_categorical(x, num_classes)
ds = ds.map(lambda img, label: (img, helper_categorical(label)))

注意:您可以跳过 keras.utils.to_categorical( 函数并使用 sparse_categorical_crossentropy 作为损失函数。


要在数据集上拟合您的模型,只需将 tf.data.Dataset 传递给拟合函数:

model.fit(train_ds, validation_data=val_ds)

要更进一步,您应该阅读以下指南:tf.data: Build TensorFlow input pipelines