Keras教学(9):Keras的图像预处理,看这一篇就够了

【写在前面】:大家好,我是【猪葛】
一个很看好AI前景的算法工程师
在接下来的系列博客里面我会持续更新Keras的教学内容(文末有大纲)
内容主要分为两部分
第一部分是Keras的基础知识
第二部分是使用Keras搭建FasterCNN、YOLO目标检测神经网络
代码复用性高
如果你也感兴趣,欢迎关注我的动态一起学习
学习建议:
有些内容一开始学起来有点蒙,对照着“学习目标”去学习即可
一步一个脚印,走到山顶再往下看一切风景就全明了了



本篇博客学习目标:1、掌握Keras中使用ImageDataGenerator 类进行图像预处理的方法;2、理解如何给模型喂数据进行训练的方法(先理解一次,以后会继续讲解的)









一、ImageDataGenerator 类

import tensorflow.keras as keras

# 函数作用:通过实时数据增强生成张量图像数据批次。数据将不断循环(按批次)。
keras.preprocessing.image.ImageDataGenerator(featurewise_center=False,
                                             samplewise_center=False,
                                             featurewise_std_normalization=False,
                                             samplewise_std_normalization=False,
                                             zca_whitening=False,
                                             zca_epsilon=1e-06,
                                             rotation_range=0,
                                             width_shift_range=0.0,
                                             height_shift_range=0.0,
                                             brightness_range=None,
                                             shear_range=0.0,
                                             zoom_range=0.0,
                                             channel_shift_range=0.0,
                                             fill_mode='nearest',
                                             cval=0.0,
                                             horizontal_flip=False,
                                             vertical_flip=False,
                                             rescale=None,
                                             preprocessing_function=None,
                                             data_format=None,
                                             validation_split=0.0,
                                             dtype=None)

函数作用

通过实时数据增强生成张量图像数据批次。数据将不断循环(按批次)。

参数提示

因为这参数比较多,而且比较难以理解,我会在下面解释小例子的时候结合实例来解释这些参数,所以大家一开始看不懂没关系,先跳过也行。一般这些参数都选择默认值,然后对图片的处理使用这个类的方法来实现

常见参数

  • horizontal_flip: 布尔值。随机水平翻转。
  • vertical_flip: 布尔值。随机垂直翻转。
  • rescale: 重缩放因子。默认为 None。如果是 None 或 0,不进行缩放,否则将数据乘以所提供的值(在应用任何其他转换之前)。
  • preprocessing_function: 应用于每个输入的函数。这个函数会在任何其他改变之前运行。这个函数需要一个参数:一张图像(秩为 3 的 Numpy 张量),并且应该输出一个同尺寸的 Numpy 张量。
  • data_format: 图像数据格式,{“channels_first”, “channels_last”} 之一。"channels_last" 模式表示图像输入尺寸应该为 (samples, height, width, channels),"channels_first" 模式表示输入尺寸应该为 (samples, channels, height, width)。默认为 在 Keras 配置文件 ~/.keras/keras.json 中的 image_data_format 值。如果你从未设置它,那它就是 “channels_last”。
  • validation_split: 浮点数。Float. 保留用于验证的图像的比例(严格在0和1之间)。
  • dtype: 生成数组使用的数据类型。
  • rotation_range: 整数。随机旋转的度数范围。
  • featurewise_center: 布尔值。将输入数据的均值设置为 0,逐特征进行。
  • samplewise_center: 布尔值。将每个样本的均值设置为 0。
  • featurewise_std_normalization: 布尔值。将输入除以数据标准差,逐特征进行。
  • samplewise_std_normalization: 布尔值。将每个输入除以其标准差。
  • zca_epsilon: ZCA 白化的 epsilon 值,默认为 1e-6。
  • zca_whitening: 布尔值。是否应用 ZCA 白化。
  • width_shift_range: 浮点数、一维数组或整数,宽度缩放比例
  • height_shift_range: 浮点数、一维数组或整数,高度缩放比例
  • shear_range: 浮点数。剪切强度(以弧度逆时针方向剪切角度)。
  • zoom_range: 浮点数 或 [lower, upper]。随机缩放范围。如果是浮点数,[lower, upper] = [1-zoom_range, 1+zoom_range]。

二、ImageDataGenerator 类的类方法

2-1、flow函数

flow(
             x,
             y=None,
             batch_size=32,
             shuffle=True,
             sample_weight=None,
             seed=None,
             save_to_dir=None,
             save_prefix='',
             save_format='png',
             subset=None)

函数作用:采集数据和标签数组,生成批量增强数据。

参数

  • x: 输入数据。秩为 4 的 Numpy 矩阵或元组。如果是元组,第一个元素应该包含图像,第二个元素是另一个 Numpy 数组或一列 Numpy 数组,它们不经过任何修改就传递给输出。可用于将模型杂项数据与图像一起输入。对于灰度数据,图像数组的通道轴的值应该为 1,而对于 RGB 数据,其值应该为 3。
  • y: 标签。
  • batch_size: 整数 (默认为 32)。
  • shuffle: 布尔值 (默认为 True)。
  • sample_weight: 样本权重。
  • seed: 整数(默认为 None)。
  • save_to_dir: None 或 字符串(默认为 None)。这使您可以选择指定要保存的正在生成的增强图片的目录(用于可视化您正在执行的操作)。
  • save_prefix: 字符串(默认 ‘’)。保存图片的文件名前缀(仅当 save_to_dir 设置时可用)。
  • save_format: “png”, “jpeg” 之一(仅当 save_to_dir 设置时可用)。默认:“png”。
  • subset: 数据子集 (“training” 或 “validation”),如果 在 ImageDataGenerator 中设置了 validation_split。

运行一个小例子就明白了:

from keras.utils import np_utils
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, Flatten, Dense
from tensorflow.keras.datasets import mnist
from tensorflow.keras.preprocessing.image import ImageDataGenerator
import numpy as np

model = Sequential([
    Conv2D(4, (3, 3), 2, 'same', input_shape=(28, 28, 1)),
    Flatten(),
    Dense(10, activation='softmax')
])


(x_train, y_train), (x_test, y_test) = mnist.load_data()  # 加载一些数据来进行验证,假设我们有的全部数据就是这么多
x_train = np.reshape(x_train, (60000, 28, 28, 1))  # 是np数组,重设shape
x_test = np.reshape(x_test, (10000, 28, 28, 1))  # 是np数组,重设shape
y_train = np_utils.to_categorical(y_train, 10)  # 是np数组,one_hot表示
y_test = np_utils.to_categorical(y_test, 10)  # 是np数组,one_hot表示

datagen = ImageDataGenerator()  # 实例化一个对象
a = datagen.flow(x_train, y_train, batch_size=5)  # 生成一个生成器

(batch_x, batch_y) = next(a)  # 展示变量值

pass

运行完之后你可以看到batch_x.shape=(5, 28, 28, 1),batch_y.shape=(5, 10)

返回值

一个生成元组 (x, y) 的 Iterator

2-2、flow_from_directory函数

flow_from_directory(
                        directory,
                        target_size=(256, 256),
                        color_mode='rgb',
                        classes=None,
                        class_mode='categorical',
                        batch_size=32,
                        shuffle=True,
                        seed=None,
                        save_to_dir=None,
                        save_prefix='',
                        save_format='png',
                        follow_links=False,
                        subset=None,
                        interpolation='nearest')

函数作用:一个生成 (x, y) 元组的 DirectoryIterator,其中 x 是一个包含一批尺寸为 (batch_size, *target_size, channels)的图像的 Numpy 数组,y 是对应标签的 Numpy 数组

参数

  • directory: 目标目录的路径。每个类应该包含一个子目录。任何在子目录树下的 PNG, JPG, BMP, PPM 或 TIF 图像,都将被包含在生成器中。更多细节,详见 此脚本。
  • target_size: 整数元组 (height, width),默认:(256, 256)。所有的图像将被调整到的尺寸。
  • color_mode: "grayscale", "rbg" 之一。默认:"rgb"。图像是否被转换成 1 或 3 个颜色通道。
  • classes: 可选的类的子目录列表(例如 [‘dogs’, ‘cats’])。默认:None。如果未提供,类的列表将自动从 directory 下的 子目录名称/结构 中推断出来,其中每个子目录都将被作为不同的类(类名将按字典序映射到标签的索引)。包含从类名到类索引的映射的字典可以通过 class_indices 属性获得。
  • class_mode: “categorical”, “binary”, “sparse”, “input” 或 None 之一。默认:“categorical”。决定返回的标签数组的类型:
    1、"categorical" 将是 2D one-hot 编码标签,
    2、"binary" 将是 1D 二进制标签,“sparse” 将是 1D 整数标签,
    3、"input" 将是与输入图像相同的图像(主要用于自动编码器)。
    如果为 None,不返回标签(生成器将只产生批量的图像数据,对于 model.predict_generator(), model.evaluate_generator() 等很有用)。请注意,如果 class_mode 为 None,那么数据仍然需要驻留在 directory 的子目录中才能正常工作。
  • batch_size: 一批数据的大小(默认 32)。
  • shuffle: 是否混洗数据(默认 True)。
  • seed: 可选随机种子,用于混洗和转换。
  • save_to_dir: None 或 字符串(默认 None)。这使你可以最佳地指定正在生成的增强图片要保存的目录(用于可视化你在做什么)。
  • save_prefix: 字符串。 保存图片的文件名前缀(仅当 save_to_dir 设置时可用)。
  • save_format: “png”, “jpeg” 之一(仅当 save_to_dir 设置时可用)。默认:“png”。
  • follow_links: 是否跟踪类子目录中的符号链接(默认为 False)。
  • subset: 数据子集 (“training” 或 “validation”),如果 在 ImageDataGenerator 中设置了 validation_split。
  • interpolation: 在目标大小与加载图像的大小不同时,用于重新采样图像的插值方法。 支持的方法有 “nearest”, “bilinear”, and “bicubic”。 如果安装了 1.1.3 以上版本的 PIL 的话,同样支持 “lanczos”。 如果安装了 3.4.0 以上版本的 PIL 的话,同样支持 “box” 和 “hamming”。 默认情况下,使用 “nearest”。

返回

一个生成 (x, y) 元组的 DirectoryIterator,其中 x 是一个包含一批尺寸为 (batch_size, *target_size, channels)的图像的 Numpy 数组,y 是对应标签的 Numpy 数组。

小例子:建立自己运行一遍,更改更改参数也就明白里面的意思了,代码已经给你们码好拉,如下

from keras.utils import np_utils
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, Flatten, Dense
from tensorflow.keras.datasets import mnist
from tensorflow.keras.preprocessing.image import ImageDataGenerator
import numpy as np

model = Sequential([
    Conv2D(4, (3, 3), 2, 'same', input_shape=(28, 28, 1)),
    Flatten(),
    Dense(10, activation='softmax')
])


(x_train, y_train), (x_test, y_test) = mnist.load_data()  # 加载一些数据来进行验证,假设我们有的全部数据就是这么多
x_train = np.reshape(x_train, (60000, 28, 28, 1))  # 是np数组,重设shape
x_test = np.reshape(x_test, (10000, 28, 28, 1))  # 是np数组,重设shape
y_train = np_utils.to_categorical(y_train, 10)  # 是np数组,one_hot表示
y_test = np_utils.to_categorical(y_test, 10)  # 是np数组,one_hot表示

datagen = ImageDataGenerator()  # 实例化一个对象
a = datagen.flow_from_directory(directory='/home/huangjx/图片/cifar2/test', batch_size=5)  # 生成一个生成器

(batch_x, batch_y) = next(a)  # 展示b的值

pass

三、结合model.fit_generator()函数演示如何给模型喂数据

3-1、fit_generator()函数

fit_generator(
                    generator,
                    steps_per_epoch=None,
                    epochs=1,
                    verbose=1,
                    callbacks=None,
                    validation_data=None,
                    validation_steps=None,
                    validation_freq=1,
                    class_weight=None,
                    max_queue_size=10,
                    workers=1,
                    use_multiprocessing=False,
                    shuffle=True,
                    initial_epoch=0):

函数作用

使用 Python 生成器或 Sequence 实例逐批生成的数据,按批次训练模型。

生成器与模型并行运行,以提高效率。 例如,这可以让你在 CPU 上对图像进行实时数据增强,以在 GPU 上训练模型。

keras.utils.Sequence 的使用可以保证数据的顺序, 以及当 use_multiprocessing=True 时 ,保证每个输入在每个 epoch 只使用一次。

参数

  • generator: 一个生成器或 Sequence (keras.utils.Sequence) 对象的实例,以避免在使用多进程时出现重复数据。 生成器的输出应该为以下之一:
    一个 (inputs, targets) 元组
    一个 (inputs, targets, sample_weights) 元组。 这个元组(生成器的单个输出)表示一个独立批次。因此,此元组中的所有数组必须具有相同的长度(等于此批次的大小)。不同的批次可能具有不同的大小。例如,如果数据集的大小不能被批量大小整除,则最后一批时期通常小于其他批次。生成器将无限地在数据集上循环。当运行到第 steps_per_epoch 时,记一个 epoch 结束。
  • steps_per_epoch: 整数。在声明一个 epoch 完成并开始下一个 epoch 之前从 generator 产生的总步数(批次样本)。它通常应该等于你的数据集的样本数量除以批量大小。可选参数 Sequence:如果未指定,将使用 len(generator) 作为步数。
  • epochs: 整数,数据的迭代总轮数。一个 epoch 是对所提供的整个数据的一轮迭代,由 steps_per_epoch 所定义。请注意,与 initial_epoch 一起,参数 epochs 应被理解为 「最终轮数」。模型并不是训练了 epochs 轮,而是到第 epochs 轮停止训练。
  • verbose: 日志显示模式。0,1 或 2。0 = 安静模式,1 = 进度条,2 = 每轮一行。
  • callbacks: keras.callbacks.Callback 实例列表。在训练时调用的一系列回调。
  • validation_data: 它可以是以下之一:
    验证数据的生成器或 Sequence 实例
    一个 (inputs, targets) 元组
    一个 (inputs, targets, sample_weights) 元组。
  • validation_steps: 仅当 validation_data 是一个生成器时才可用。 每个 epoch 结束时验证集生成器产生的步数。它通常应该等于你的数据集的样本数量除以批量大小。可选参数 Sequence:如果未指定,将使用 len(generator) 作为步数。
  • class_weight: 可选的字典,用来映射类索引(整数)到权重(浮点)值,用于加权损失函数(仅在训练期间)。这可能有助于告诉模型 「更多关注」来自代表性不足的类的样本。
  • max_queue_size: 整数。生成器队列的最大尺寸。如果未指定,max_queue_size 将默认为 10。
  • workers: 整数。使用基于进程的多线程时启动的最大进程数。如果未指定,worker 将默认为 1。如果为 0,将在主线程上执行生成器。
  • use_multiprocessing: 如果 True,则使用基于进程的多线程。如果未指定,use_multiprocessing 将默认为 False。请注意,因为此实现依赖于多进程,所以不应将不可传递的参数传递给生成器,因为它们不能被轻易地传递给子进程。
  • shuffle: 布尔值。是否在每轮迭代之前打乱 batch 的顺序。只能与 Sequence (keras.utils.Sequence) 实例同用。在 steps_per_epoch 不为 None 是无效果。
  • initial_epoch: 整数。开始训练的轮次(有助于恢复之前的训练)。

返回

一个 History 对象。其 History.history 属性是连续 epoch 训练损失和评估值,以及验证集损失和评估值的记录(如果适用)。

例子

def generate_arrays_from_file(path):
    while True:
        with open(path) as f:
            for line in f:
                # 从文件中的每一行生成输入数据和标签的 numpy 数组
                x1, x2, y = process_line(line)
                    yield ({'input_1': x1, 'input_2': x2}, {'output': y})

model.fit_generator(generate_arrays_from_file('/my_file.txt'),
                    steps_per_epoch=10000, epochs=10)

我们现在就可以通过前面2-1小节和2-2小节学习得到的生成器来给模型喂数据啦

3-2、给模型喂数据(实现mnist手写数字的分类识别)

首先我们先顺便定义一个模型用于测试,这个过程好比自己在搭建神经网络一样,可以参见我本系列的其它文章:

【Keras教学(2)】:使用Sequence搭建LeNet-5卷积神经网络

【Keras教学(3)】:使用函数式API搭建AlexNet、VGG系列卷积神经网络

from keras.utils import np_utils
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, Flatten, Dense, MaxPooling2D
from tensorflow.keras.datasets import mnist
from tensorflow.keras.preprocessing.image import ImageDataGenerator
import numpy as np
from tensorflow.keras.losses import categorical_crossentropy

model = Sequential([
    Conv2D(16, (3, 3), 2, 'same', input_shape=(28, 28, 1), activation='relu'),
    MaxPooling2D((2, 2), 2, 'same'),
    Conv2D(8, (3, 3), 2, 'same', activation='relu'),
    MaxPooling2D((2, 2), 2, 'same'),
    Flatten(),
    Dense(10, activation='softmax')
])

然后给这个模型顺便配置一个优化器和损失函数

model.compile(optimizer='sgd', loss='categorical_crossentropy')

然后准备所有待会要喂进去的数据


(x_train, y_train), (x_test, y_test) = mnist.load_data()  # 加载一些数据来进行验证,假设我们有的全部数据就是这么多
x_train = np.reshape(x_train, (60000, 28, 28, 1))  # 是np数组,重设shape
x_test = np.reshape(x_test, (10000, 28, 28, 1))  # 是np数组,重设shape
y_train = np_utils.to_categorical(y_train, 10)  # 是np数组,one_hot表示
y_test = np_utils.to_categorical(y_test, 10)  # 是np数组,one_hot表示

开始喂数据

datagen = ImageDataGenerator()  # 实例化一个对象
gen = datagen.flow(x=x_train, y=y_train, batch_size=32)  # 生成一个生成器
model.fit_generator(gen, steps_per_epoch=10, epochs=10)  # 训练

完整代码如下

from keras.utils import np_utils
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, Flatten, Dense, MaxPooling2D
from tensorflow.keras.datasets import mnist
from tensorflow.keras.preprocessing.image import ImageDataGenerator
import numpy as np
from tensorflow.keras.losses import categorical_crossentropy

model = Sequential([
    Conv2D(16, (3, 3), 2, 'same', input_shape=(28, 28, 1), activation='relu'),
    MaxPooling2D((2, 2), 2, 'same'),
    Conv2D(8, (3, 3), 2, 'same', activation='relu'),
    MaxPooling2D((2, 2), 2, 'same'),
    Flatten(),
    Dense(10, activation='softmax')
])
model.compile(optimizer='sgd', loss='categorical_crossentropy')

(x_train, y_train), (x_test, y_test) = mnist.load_data()  # 加载一些数据来进行验证,假设我们有的全部数据就是这么多
x_train = np.reshape(x_train, (60000, 28, 28, 1))  # 是np数组,重设shape
x_test = np.reshape(x_test, (10000, 28, 28, 1))  # 是np数组,重设shape
y_train = np_utils.to_categorical(y_train, 10)  # 是np数组,one_hot表示
y_test = np_utils.to_categorical(y_test, 10)  # 是np数组,one_hot表示

datagen = ImageDataGenerator()  # 实例化一个对象
gen = datagen.flow(x=x_train, y=y_train, batch_size=32)  # 生成一个生成器
model.fit_generator(gen, steps_per_epoch=10, epochs=10)  # 开始训练

pass

运行结果

Epoch 1/10
10/10 [==============================] - 0s 33ms/step - loss: 13.8101
Epoch 2/10
10/10 [==============================] - 0s 31ms/step - loss: 13.4682
Epoch 3/10
10/10 [==============================] - 0s 31ms/step - loss: 12.3496
Epoch 4/10
10/10 [==============================] - 0s 31ms/step - loss: 12.3210
Epoch 5/10
10/10 [==============================] - 0s 31ms/step - loss: 11.6730
Epoch 6/10
10/10 [==============================] - 0s 31ms/step - loss: 8.8682
Epoch 7/10
10/10 [==============================] - 0s 32ms/step - loss: 3.5756
Epoch 8/10
10/10 [==============================] - 0s 31ms/step - loss: 2.3343
Epoch 9/10
10/10 [==============================] - 0s 31ms/step - loss: 2.3085
Epoch 10/10
10/10 [==============================] - 0s 31ms/step - loss: 2.2269

Process finished with exit code 0

发现loss还真的会下降哦,如果我加个评价指标上去看看准确率,我猜准确率还挺高哈哈哈(别忘了这只是我顺便写的模型,足以见的神经网络的神奇)

大家也可以自己调节参数去玩一玩。本期的内容就这么多,文末附上本系列keras教学内容,欢迎关注我的动态一起学习呀
在这里插入图片描述

  • 6
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
好的,以下是一篇基于TensorFlow的猫狗图像识别的文章: 图像识别一直是人工智能领域中的一个重要应用,而猫狗图像识别则是其中的一个典型例子。在这篇文章中,我们将使用TensorFlow来训练一个猫狗图像识别模型。 首先,我们需要收集一些猫和狗的图像数据。我们可以从一些公开的数据集中获取这些数据,比如Kaggle上的“Dogs vs. Cats”数据集。该数据集包含了25000张猫和狗的图片,其中12500张是猫的图片,12500张是狗的图片。 接下来,我们需要对这些图片进行预处理。我们将所有的图片大小调整为64x64像素,并将它们转换为灰度图像。这有助于减少数据量,并且可以更好地处理图像的特征。 然后,我们将数据集划分为训练集和测试集。我们使用80%的数据作为训练集,20%的数据作为测试集。 接下来,我们构建一个卷积神经网络模型。我们将使用TensorFlow的Keras API来构建模型。我们的模型包含两个卷积层和两个全连接层。每个卷积层都有一个ReLU激活函数和一个2x2的最大池化层。最后一层是一个softmax层,用于输出猫和狗的概率。 接下来,我们需要编译模型。我们将使用Adam优化器和交叉熵损失函数来编译模型。 然后,我们将模型拟合到训练集上。我们将使用50个epochs和32个batch size来训练模型。 最后,我们将模型评估在测试集上的性能。我们将使用accuracy指标来评估模型的性能。 下面是完整的代码: ``` import tensorflow as tf from tensorflow import keras from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense # Load the data (train_images, train_labels), (test_images, test_labels) = keras.datasets.cifar10.load_data() # Preprocess the data train_images = train_images.reshape(train_images.shape[0], 32, 32, 3) train_images = train_images.astype('float32') / 255.0 test_images = test_images.reshape(test_images.shape[0], 32, 32, 3) test_images = test_images.astype('float32') / 255.0 # Define the model architecture model = keras.Sequential([ Conv2D(32, (3, 3), activation='relu', input_shape=(32, 32, 3)), MaxPooling2D((2, 2)), Conv2D(64, (3, 3), activation='relu'), MaxPooling2D((2, 2)), Flatten(), Dense(64, activation='relu'), Dense(10, activation='softmax') ]) # Compile the model model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) # Train the model model.fit(train_images, train_labels, epochs=50, batch_size=32) # Evaluate the model test_loss, test_acc = model.evaluate(test_images, test_labels) print('Test accuracy:', test_acc) ``` 在上面的代码中,我们加载了CIFAR-10数据集,并对其进行了预处理。然后,我们定义了一个包含两个卷积层和两个全连接层的卷积神经网络模型。我们使用Adam优化器和交叉熵损失函数来编译模型。最后,我们将模型拟合到训练集上,并评估模型在测试集上的性能。 总的来说,我们的模型在猫狗图像识别方面表现出色。使用类似的方法,我们可以训练出更复杂的模型来识别更多种类的图像

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值