人工智能和机器学习系列(七) Keras库

2021-08-25 10:29:41 浏览数 (4484)

本篇文章是我们学习 Python 及其在机器学习(ML)和 人工智能(AI) 中的应用系列的第七个模块。在上一模块中,我们讨论了使用 NLTK 进行文本分析。接下来,我们将要讨论的是Keras,一个用于处理神经网络的高级 Python 库。在本模块中,将演示如何使用 Keras 解决图像分类问题。

安装

使用Anaconda的conda install就可以安装Keras库:

conda install keras

该命令也会立即帮你安装好相关依赖。

后端配置

Keras 可以使用多个可用库之一作为其后端,这是处理低级操作(例如张量)的部分。我们将使用 TensorFlow,这是默认设置。

首先,我们将稍微调整 TensorFlow 的配置。具体来说,我们将allow_growth选项设置为 true,这允许 TensorFlow 动态增加使用的 GPU 内存,而不是预先分配所有内容。如果我们不这样做,TensorFlow 可能会尝试分配太多内存,导致你的 GPU 会立即耗尽内存(对我来说确实如此)。为此,请把以下代码放在文件的开头:

如果您的后端是 TensorFlow 1.x:

from keras.backend.tensorflow_backend import set_session
import tensorflow as tf
config = tf.ConfigProto()
config.gpu_options.allow_growth = True
set_session(tf.Session(config=config))

对于 TensorFlow 2.x,你必须set_memory_growth设置为你的 GPU调用该函数。你可以在tf.config.experimental.set_memory_growth文档中阅读更多关于这背后的细节。

怎么查看你所拥有的版本?可以通过conda list来查看您的 TensorFlow 版本。即便使用相同的 Anaconda 安装命令,例如我在一台计算机上安装了 1.13.1,在另一台上安装了 2.1.0。

如果你想强制 Keras 使用你的 CPU 而不是你的 GPU,请在第一次 Keras import 之前添加:

import os
os.environ['CUDA_VISIBLE_DEVICES'] = '-1'

虽然这样一来比在 GPU 上慢很多,但如果你没有足够的多 GPU 内存,你还真得考虑一下这样做。

使用 Keras 进行图像分类

我们将使用英特尔图像分类数据集演示用于图像分类的 Keras 。该数据集包含六个类别的图像,分为六个不同的目录,这非常方便,因为 Keras 提供了处理该格式数据的内置功能。

虽然你不用过多担心神经网络背后的数学问题,但你还需要对此有足够的理解,因为你才能准确指定你的模型由哪些层组成。

Keras 提供的模型之一是顺序模型,即一堆层。创建顺序模型和添加层非常简单:

from keras.models import Sequential

model = Sequential()
model.add(layer_one)
model.add(layer_two)
# ...

以下是我们的模型用于图像分类的样子:

from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Dropout, Flatten, Dense
from keras.layers.normalization import BatchNormalization

model = Sequential()

model.add(Conv2D(32, kernel_size=(3, 3), activation="relu", input_shape=(150, 150, 3))) # our images are 150*150
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(BatchNormalization())

model.add(Conv2D(64, kernel_size=(3, 3), activation="relu"))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(BatchNormalization())

model.add(Conv2D(128, kernel_size=(3, 3), activation="relu"))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(BatchNormalization())

model.add(Flatten())
model.add(Dense(128, activation="relu"))
model.add(Dropout(0.15))
model.add(Dense(64, activation="relu"))
model.add(Dense(6, activation="softmax"))

神经网络模型的构建超出了本模块的范围,但简而言之:卷积层的重复模式(由于模式变得更复杂,过滤器数量越来越多)、最大池化层和批处理归一化通常用作图像分类问题的第一步。该步骤的输出是多维的,我们将其展平为具有展平层的一维向量。我们以几个密集连接的层结束,中间有一个 dropout 层,以帮助对抗过度拟合。最后一层必须输出一个包含六个元素的向量,因为我们有六个类别。

接下来,我们编译模型,这意味着我们对其进行配置以进行训练:

model.compile(loss='sparse_categorical_crossentropy',
          	   optimizer='adam',
          	   metrics=['accuracy'])

我们的损失函数sparse_categorical_crossentropy非常适合分类问题,而类别之间没有重叠。有关损失函数的完整讨论,请参阅Keras 文档。我们正在使用 Adam 优化器。可以在相关文档中找到优化器的完整列表。并metrics指定模型在训练和测试期间评估的内容。

拟合模型

现在我们有了模型的结构,我们可以将它拟合到我们的数据集。

from keras.preprocessing.image import ImageDataGenerator

datagen = ImageDataGenerator(validation_split=0.2)
train_generator = 
    datagen.flow_from_directory("intel-images/seg_train/seg_train", 
    batch_size=32, target_size=(150,150), class_mode="sparse", 
    subset="training")
validation_generator = 
    datagen.flow_from_directory("intel-images/seg_train/seg_train", 
    batch_size=32, target_size=(150, 150), class_mode="sparse", 
    subset="validation")
model.fit_generator(train_generator, epochs=40, 
                    validation_data=validation_generator)

(如果你想要以较低的准确度更快地完成该过程,请自定义减少 epoch 的数量,尤其是在你使用 CPU 的情况下。40 个 epoch 需要相当长的时间。)

根据 Keras 文档,这就是 an 的ImageDataGenerator作用:

使用实时数据增强生成批量张量图像数据。数据将被循环(分批)。

我们的例子没有做任何数据增强。稍后我们将介绍该功能。

在前面的代码中,validation_split=0.2意味着我们将使用 20% 的训练集进行验证。由于数据集只有一个训练集和一个测试集,我们必须使用训练集的一个子集作为验证集。

flow_from_directory 是一个简洁的内置函数,非常适合像我们这样的数据集结构:每个类别的子目录。

class_mode="sparse" 意味着我们正在处理一维整数标签。

fit_generatorImageDataGenerator在我们指定的多个时期中将模型拟合到。

测试模型

训练完成后,我们可以用evaluate_generator函数测试模型。就像fit_generator,它需要一个生成器作为参数。我们可以为我们的测试数据创建一个,类似于我们为训练数据所做的:

test_datagen = ImageDataGenerator()
test_generator = 
    datagen.flow_from_directory(
        "intel-images/seg_test/seg_test", 
        target_size=(150,150), class_mode="sparse")
print(model.evaluate_generator(test_generator))

这将为我们的示例返回一个包含两个值的数组:损失和准确性。(你还可以通过查看model.metrics_names值来检查。)

我的准确率为 81.7%,这对于非平凡数据集上的相对简单模型来说还不错。

生成预测

你现在可以使用该model.predict方法对任何图像生成预测。此方法将 NumPy 图像数组作为输入,其中图像也是形状为 (150, 150, 3) 的 NumPy 数组。要对一张图像进行预测,你可以执行以下操作:

import skimage.io
import numpy as np

model.predict(np.expand_dims(skimage.io.imread("file.jpg"), axis=0))

skimage.io.imread将读取图像expand_dims并将另一个维度添加到数组。输出是一个预测数组,其中每个预测是一个值数组,指示每个类别的概率。

数据增强

数据增强是指根据现有训练集生成新的训练数据,以提高准确性和泛化性并减少过度拟合。

对于图像,数据增强可以通过对图像进行多种变换来完成:旋转、翻转、缩放、移位、剪切等。

ImageDataGenerator使这变得容易。要将数据增强应用于我们的模型,只需更改两行代码。

首先,ImageDataGenerator使用更多参数实例化,指定我们想要的转换:

Python复制代码

datagen = ImageDataGenerator(rotation_range=30, 
                             horizontal_flip=True, 
                             zoom_range=0.2, 
                             shear_range=0.2)

还有更多的可能性——请参阅图像预处理文档以获取完整的参数列表。

第二行是fit_generator电话。这个函数有可选steps_per_epoch和validation_steps参数,我们可以离开了前面,因为我们有训练样本的固定数量。通过数据增强,我们可能有更多的训练样本,因此我们必须指定要使用的数量。如果我们不这样做,该函数将只使用我们固定大小的样本集。一个步骤对应于一批给定的batch_size。

model.fit_generator(train_generator, epochs=40, 
                    validation_data=validation_generator, 
                    steps_per_epoch=1600, validation_steps=32)

同样,如果您希望该过程更快,请随时减少 epoch 数或步骤数。经过 2-3 小时的训练,我的准确率为 85.5%。

保存和恢复模型

Keras 允许你以 HDF5 格式保存经过训练的模型:

model.save("images_model.h5")

恢复模型也是一行:

import keras.models
model = keras.models.load_model("images_model.h5")

这需要h5py软件包,如果你使用的是conda install. 如果没有,请在 Jupyter Notebook 单元中运行此 pip 命令:

Python复制代码

!pip install --upgrade h5py

结论

在本模块中,我们演练了 Keras 在图像分类问题中的使用。Keras 的可用层比我们在这里使用的层多得多。如果您想深入了解,可以使用Keras 文档作为起点。它还提供了大量常见深度学习问题的示例。