TF2实现卷积神经网络模型构建之复杂的图像应用
此次我们使用Tensorflow通过卷积神经网络实现复杂的图像应用,仍按照下列流程图顺序进行操作:
文章目录
一、复杂图像处理前言
1.现实生活中的数据
我们真正要处理起生活中的图片集时,并不会像Fashion MNIST数据集中图片那么均匀,Fashion MNIST数据集中的图片主体均位于中央,形状全为28*28像素,并且都为灰度图。然而在现实中,我们所拥有的图片往往有以下的特点:
- 图片尺寸大小不一样,有不同大小,不同纵横比。
- 主题位于图片中不同位置,在某些情况下,甚至有多个主题。
- 数据量大,不能一下装入内存。
- 经常需要修改参数。
2.图片集介绍
此次我们通过包含人马图片的压缩包来进行训练模型,最后实现用于辨别人与马的功能。
该压缩包内包含了两个文件夹,分别为horses和humans。
两文件夹中分别存放着若干张计算机合成的人与马的彩色图片,如下所示。图片中主体的姿态、动作各异。我们将使用这些图片进行卷积神经网络模型的构建。
同样的,我们也有人马测试图片数据包供我们检验模型的好坏,该压缩包与训练用的压缩包除图片内容不一样外,其他方面基本一致,这里不做详细介绍。
3.图片压缩包下载
关于该模型训练以及验证的图片压缩包下载链接也在此处给出,供大家下载学习使用。
点击下载人马图片数据包
二、了解ImageGenerator
在Fashion MNIST数据集已经分配好了训练集以及测试集并且标签可用。但在现实中,这些均需要我们自己去操做。所以,在此处我们引入Tensorflow中方便可用的API帮助我们解决这一问题。
1.特性
ImageGenerator的一个特性就是你可以将它指向一个目录,然后它的子目录将为你自动生成标签。如果你在那里有一个图像目录,你有训练和验证的子目录,ImageGenerator会为这些图片建立一个feeder并且为你自动标记。
2.训练生成器与验证生成器
通过目录流方法从该目录及其子目录加载图像。
通过设定rescale将图片进行标准化。
下面是对训练生成器代码一些参数设定的简单解释
- 目录名,需要注意的是,人们把子目录指向生成器,那是一个常见的错误,你应该始终将其指向包含你图像的子目录的那个目录;
- target_size:设定图片形状,进行图片的调整,这样就不需要我们对文件系统里的图片进行数以千计的处理,这里将图片调整为300*300的规格;
- batch_size:我们设置一下输入的批次大小,图片将为训练和测试批次载入,这样将比一张一张图片载入的效率要高很多,这里是一次载入128张图片,关于如何确定batch_size的大小,我们这里不做讨论,后面将单独地进行探讨。但这里我们可以自己改变barch_size的大小来观察通过更改此参数的影响;
- class_mode:分类模型,我们这个模型是二分类模型,它的输出结果只有“人”和“马”。所以这里使用"binary"。
代码如下:
from tensorflow.keras.preprocessing.image import ImageDataGenerator
# All images will be rescaled by 1./255
train_datagen = ImageDataGenerator(rescale=1./255)
# Flow training images in batches of 128 using train_datagen generator
train_generator = train_datagen.flow_from_directory(
'horse-or-human', # This is the source directory for training images
target_size=(300, 300), # All images will be resized to 300x300
batch_size=128,
# Since we use binary_crossentropy loss, we need binary labels
class_mode='binary')
验证生成器应完全相同,只在输入批次大小上改为了32,并且验证生成器指向的目录也不一样。
test_datagen = ImageDataGenerator(rescale=1./255)
validation_generator = test_datagen.flow_from_directory(
'validation-horse-or-human',
target_size=(300, 300),
batch_size=32,
class_mode='binary')
会得到以下输出,说明训练生成器与验证生成器各含两类1027和256张图片。
Found 1027 images belonging to 2 classes.
Found 256 images belonging to 2 classes.
三、模型的构建
1.建立Sequential模型
代码如下:
model = tf.keras.models.Sequential([
#请注意,输入形状是3字节300x300的彩色图像
# 第一层卷积层
tf.keras.layers.Conv2D(16, (3,3), activation='relu', input_shape=(300, 300, 3)),
tf.keras.layers.MaxPooling2D(2, 2),
# 第二层卷积层
tf.keras.layers.Conv2D(32, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
# 第三次卷积层
tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
# 第四层卷积层
tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
# 第五层卷积层
tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
# 将结果展平输入进DNN
tf.keras.layers.Flatten(),
# 512个神经元的隐藏层
tf.keras.layers.Dense(512, activation='relu'),
# 只有1个输出神经元。 它将包含一个0-1的值,其中0代表1类(“马”),而1代表其他类(“人”)
# 这里是二分类问题使用sigmoid激活函数(如果是多分类问题,我们就要使用softmax)
tf.keras.layers.Dense(1, activation='sigmoid')
])
2.模型结构
print(model.summary())
Model: "sequential_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d_5 (Conv2D) (None, 298, 298, 16) 448
_________________________________________________________________
max_pooling2d_5 (MaxPooling2 (None, 149, 149, 16) 0
_________________________________________________________________
conv2d_6 (Conv2D) (None, 147, 147, 32) 4640
_________________________________________________________________
max_pooling2d_6 (MaxPooling2 (None, 73, 73, 32) 0
_________________________________________________________________
conv2d_7 (Conv2D) (None, 71, 71, 64) 18496
_________________________________________________________________
max_pooling2d_7 (MaxPooling2 (None, 35, 35, 64) 0
_________________________________________________________________
conv2d_8 (Conv2D) (None, 33, 33, 64) 36928
_________________________________________________________________
max_pooling2d_8 (MaxPooling2 (None, 16, 16, 64) 0
_________________________________________________________________
conv2d_9 (Conv2D) (None, 14, 14, 64) 36928
_________________________________________________________________
max_pooling2d_9 (MaxPooling2 (None, 7, 7, 64) 0
_________________________________________________________________
flatten_1 (Flatten) (None, 3136) 0
_________________________________________________________________
dense_2 (Dense) (None, 512) 1606144
_________________________________________________________________
dense_3 (Dense) (None, 1) 513
=================================================================
Total params: 1,704,097
Trainable params: 1,704,097
Non-trainable params: 0
_________________________________________________________________
None
3.编译及训练
compile过程:
- 损失函数使用二值交叉熵;
- 优化方法选用RMSprop(Root Mean Square prop,均方根传递),可以调整学习率;
- 评价函数使用accuracy
代码如下:
from tensorflow.keras.optimizers import RMSprop
model.compile(loss='binary_crossentropy',
optimizer=RMSprop(lr=0.001),
metrics=['acc'])
fit过程
model.fit_generator(
train_generator,
steps_per_epoch=8,
epochs=15,
verbose=1,
validation_data = validation_generator,
validation_steps=8)
训练可能要耗费几分钟的时间,需要简单等待。
Epoch 1/15
8/8 [==============================] - 35s 4s/step - loss: 0.8859 - acc: 0.5017 - val_loss: 0.6365 - val_acc: 0.8398
Epoch 2/15
8/8 [==============================] - 32s 4s/step - loss: 0.6408 - acc: 0.6240 - val_loss: 0.6436 - val_acc: 0.5000
Epoch 3/15
8/8 [==============================] - 34s 4s/step - loss: 0.6176 - acc: 0.6151 - val_loss: 0.5451 - val_acc: 0.8672
Epoch 4/15
8/8 [==============================] - 36s 4s/step - loss: 0.6189 - acc: 0.7930 - val_loss: 0.9589 - val_acc: 0.5859
Epoch 5/15
8/8 [==============================] - 31s 4s/step - loss: 0.3440 - acc: 0.8576 - val_loss: 1.7280 - val_acc: 0.7773
Epoch 6/15
8/8 [==============================] - 31s 4s/step - loss: 0.1539 - acc: 0.9388 - val_loss: 0.9769 - val_acc: 0.8633
Epoch 7/15
8/8 [==============================] - 32s 4s/step - loss: 0.1485 - acc: 0.9455 - val_loss: 0.4789 - val_acc: 0.8828
Epoch 8/15
8/8 [==============================] - 32s 4s/step - loss: 0.2715 - acc: 0.9077 - val_loss: 1.4785 - val_acc: 0.7852
Epoch 9/15
8/8 [==============================] - 32s 4s/step - loss: 0.0405 - acc: 0.9867 - val_loss: 1.7133 - val_acc: 0.8047
Epoch 10/15
8/8 [==============================] - 32s 4s/step - loss: 0.5239 - acc: 0.9010 - val_loss: 0.6040 - val_acc: 0.8516
Epoch 11/15
8/8 [==============================] - 32s 4s/step - loss: 0.1309 - acc: 0.9611 - val_loss: 2.0991 - val_acc: 0.7930
Epoch 12/15
8/8 [==============================] - 32s 4s/step - loss: 0.0277 - acc: 0.9922 - val_loss: 1.8542 - val_acc: 0.8125
Epoch 13/15
8/8 [==============================] - 32s 4s/step - loss: 0.0035 - acc: 1.0000 - val_loss: 2.3456 - val_acc: 0.8164
Epoch 14/15
8/8 [==============================] - 33s 4s/step - loss: 0.0202 - acc: 0.9944 - val_loss: 1.4247 - val_acc: 0.8594
Epoch 15/15
8/8 [==============================] - 33s 4s/step - loss: 0.0349 - acc: 0.9900 - val_loss: 0.9970 - val_acc: 0.8438
我们看到了经过15次epoch训练之后对于训练集和测试集loss都处于较低值,accuracy都处于了较高的值,说明该预测模型预测能力良好。