【深度学习】ImageDataGenerator的使用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011240016/article/details/85209824

数据预处理

现在模型也定义好了,原始数据也准备好了,但是在将数据填入模型之前,需要进行预处理才能使用,填入模型的是浮点数张量。而当前数据是以JPEG文件的形式保存在硬盘中,预处理步骤如下:

  • 读取图像文件
  • 将JPEG文件解码为RGB像素网格
  • 将像素网格转化为浮点数张量
  • 将像素值缩放到0~1区间

Keras提供了自动完成这些步骤的工具:keras.preprocessing.image,其中有一个ImageDataGenerator类,可以帮助我们快速创建Python生成器,将硬盘上的图像文件自动转换为预处理好的张量。

from keras.preprocessing.image import ImageDataGenerator
train_datagen = ImageDataGenerator(rescale=1./255)
test_datagen = ImageDataGenerator(rescale=1./255)

这里直接通过ImageDataGenerator来生成一个数据生成器,其中rescale参数指定将图像张量的数字缩放。

具体使用起来如下,主要是flow_from_directory函数的使用:

train_generator = train_datagen.flow_from_directory(
                train_dir, # 目标目录
                target_size=(150, 150), # 所有图像调整为150x150
                batch_size=20,
                class_mode='binary') # 二进制标签,我们用了binary_crossentropy损失函数
validation_generator = test_datagen.flow_from_directory(
                validation_dir, # 目标目录
                target_size=(150, 150), # 所有图像调整为150x150
                batch_size=20,
                class_mode='binary')

为了更好的理解,我们先回顾一下Python生成器的概念。

Python生成器

英文名叫Python Generator,是一个类似于迭代器的对象,能够与for...in一起使用,其中生成器是用yield运算符构造的。

举个例子:

def generator():
    i = 0
    while 1:
        i += 1
        yield i
for item in generator():
    print(item)
    if item > 4:
        break

这个生成器一直生成,所以我们需要手动在使用时指定结束条件。

而再看上面的图像生成代码,输出的是150x150的RGB图像,形状为(20, 150, 150, 3)的4D张量,二进制标签的形状是1D张量,即一个向量,形状是(20,)。即一批输出20个样本。生成器h不停生成这些batch,我们自己指定在何时终止循环。

for data_batch, labels_batch in train_generator:
    print('data batch shape: ', data_batch.shape)
    print('labels batch shape: ', labels_batch.shape)
    break # 一把就结束
# 输出结果
# data batch shape:  (20, 150, 150, 3)
# labels batch shape:  (20,)

应用在模型中也很简单直接:

# 使用批量生成器拟合模型
history = model.fit_generator(
    train_generator,
    steps_per_epoch=100,
    epochs=30,
    validation_data=validation_generator,
    validation_steps=50)

使用生成器,我们就可以让模型对数据进行拟合,这里用fit_generator方法,第一个参数就是我们定义好的生成器,数据不断生成,每一轮epoch要生成多少样本呢,由steps_per_epoch指定批量数,生成器中定义的是batch_size,然后拟合时再指定到底要训练多少轮次epochs,这是一种分层次的定义。

本例中,共有2000个样本,所以batch_size=20时,100个批量可以抽完这些样本完成一个轮次的训练。

同时,在fit_generator时,传入validation_data参数,和在fit函数中效果相同。使用数据生成器时,而生成器是源源不断生成数据的,所以需要指定到底要给出多少个批量,因为一个batch_size是20,验证集共1000个样本,所以需要50个批次。

另外,我们在train文件夹中按照类别分成了两个文件夹,训练时是将train文件夹下数据全部采用。

数据增强

# 数据增强增加学习样本
datagen = ImageDataGenerator(
    rotation_range=40, # 角度值,0~180,图像旋转
    width_shift_range=0.2, # 水平平移,相对总宽度的比例
    height_shift_range=0.2, # 垂直平移,相对总高度的比例
    shear_range=0.2, # 随机错切换角度
    zoom_range=0.2, # 随机缩放范围
    horizontal_flip=True, # 一半图像水平翻转
    fill_mode='nearest' # 填充新创建像素的方法
)

from keras.preprocessing import image # 图像预处理模块

fnames = [os.path.join(train_cats_dir, fname) for fname in os.listdir(train_cats_dir)]
img_path = fnames[3] # 选择一张图片进行增强
img = image.load_img(img_path, target_size=(150, 150)) # 读取图像并调整大小
x = image.img_to_array(img) # 形状转换为(150,150,3)的Numpy数组
x = x.reshape((1,) + x.shape)

i = 0
# 生成随机变换后图像批量,循环是无限生成,也需要我们手动指定终止条件
for batch in datagen.flow(x, batch_size=1):
    plt.figure(i)
    imgplot = plt.imshow(image.array_to_img(batch[0]))
    i += 1
    if i % 4 == 0:
        break
plt.show()

对比上面两种使用例子,可以看出,我们首先要定义一个ImageDataGenerator实例,定义实例时,需要指定一些参数,数据增强需要的一些变换参数在这里添加即可。

然后分别调用flow_from_directory函数和flow函数即可,二者都需要指定结束条件,细节有所不同。

数据增强的使用,具体如下:

# 训练
train_datagen = ImageDataGenerator(
    rescale=1./255,
    rotation_range=40,
    width_shift_range=0.2,
    height_shift_range=0.2,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True
)
test_datagen = ImageDataGenerator(rescale=1./255) # 验证集不用增强

train_generator = train_datagen.flow_from_directory(
    train_dir,
    target_size=(150, 150),
    batch_size=32,
    class_mode='binary'
)
validation_generator = test_datagen.flow_from_directory(
    validation_dir,
    target_size=(150, 150),
    batch_size=32,
    class_mode='binary'
)
history = model.fit_generator(
    train_generator,
    steps_per_epoch=100,
    epochs=100,
    validation_data=validation_generator,
    validation_steps=50
)

我们指定steps_per_epoch=100,且batch_size=32,所以训练数据用了3200张图片,本身只有2000张,数据增强造出了1200张。而验证集并没有增强。

END.

参考:
《Deep Learning with Python》

猜你喜欢

转载自blog.csdn.net/u011240016/article/details/85209824