目录
5.1 卷积神经网络简介
卷积神经网络接收形状为(image_height, image_width, image_channels)的输入张量(不包括批量维度)
1.卷积运算
Dense 层从输入特征空间中学到的是全局模式,卷积层学到的是局部模式。
卷积神经网络具有平移不变性(卷积神经网络在图像某处学到某个模式之后,它可以在任何地方识别这个模式),并可以学到模式的空间层次结构
(1)边界效应与填充
输出特征图的空间维度与输入相同,那么可以使用填充。填充是在输入特征图的每一边添加适当数目的行和列,使得每个输入方块都能作为卷积窗口的中心
(2)卷积步幅
两个连续窗口的距离是卷积的一个参数,叫作步幅,默认值为1。为了对特征图进行下采样,我们不用步幅
2.最大池化
最大池化的作用:对特征图进行下采样。是从输入特征图中提取窗口,并输出每个通道的最大值
最大池化通常使用2×2 的窗口和步幅2,卷积通常使用3×3 窗口和步幅1。
使用下采样的原因,一是减少需要处理的特征图的元素个数,二是通过让连续卷积层的观察窗口越来越大(即窗口覆盖原始输入的比例越来越大),从而引入空间过滤器的层级结构。
平均池化来代替最大池化,将每个局部输入图块变换为取该图块各通道的平均值
5.2 小型数据集
1.下载数据
https://www.kaggle.com/c/dogs-vs-cats/data
这个数据集包含25 000 张猫狗图像(每个类别都有12 500 张),大小为543MB(压缩后)。下载数据并解压之后,你需要创建一个新数据集,其中包含三个子集:每个类别各1000 个样本的训练集、每个类别各500 个样本的验证集和每个类别各500 个样本的测试集。
代码如下:
# 导入文件操作库
import os,shutil
# 原始数据集地址
original_dataset_dir=r'C:\Users\Administrator\Desktop\train'
# 小数据集地址
base_dir=r'C:\Users\Administrator\Desktop\little datasets'
# 以数字权限创建目录
os.mkdir(base_dir)
# 训练、验证、测试集地址
train_dir=os.path.join(base_dir,'train')
os.mkdir(train_dir)
validation_dir=os.path.join(base_dir,'validation')
os.mkdir(validation_dir)
test_dir=os.path.join(base_dir,'test')
os.mkdir(test_dir)
# 训练集
train_cats_dir=os.path.join(train_dir,'cats')
os.mkdir(train_cats_dir)
train_dogs_dir=os.path.join(train_dir,'dogs')
os.mkdir(train_dogs_dir)
# 验证集
validation_cats_dir=os.path.join(validation_dir,'cats')
os.mkdir(validation_cats_dir)
validation_dogs_dir=os.path.join(validation_dir,'dogs')
os.mkdir(validation_dogs_dir)
# 测试集
test_cats_dir=os.path.join(test_dir,'cats')
os.mkdir(test_cats_dir)
test_dogs_dir=os.path.join(test_dir,'dogs')
os.mkdir(test_dogs_dir)
# 原数据集中前1000张猫送入猫训练集
fnames = ['cat.{}.jpg'.format(i) for i in range(1000)]
for fname in fnames:
src = os.path.join(original_dataset_dir, fname)
dst = os.path.join(train_cats_dir, fname)
shutil.copyfile(src, dst)
# 原数据集中1000-1500张猫送入猫验证集
fnames = ['cat.{}.jpg'.format(i) for i in range(1000, 1500)]
for fname in fnames:
src = os.path.join(original_dataset_dir, fname)
dst = os.path.join(validation_cats_dir, fname)
shutil.copyfile(src, dst)
# 原数据集中1500-2000张猫送入猫测试集
fnames = ['cat.{}.jpg'.format(i) for i in range(1500, 2000)]
for fname in fnames:
src = os.path.join(original_dataset_dir, fname)
dst = os.path.join(test_cats_dir, fname)
shutil.copyfile(src, dst)
# 原数据集中前1000张狗送入狗训练集
fnames = ['dog.{}.jpg'.format(i) for i in range(1000)]
for fname in fnames:
src = os.path.join(original_dataset_dir, fname)
dst = os.path.join(train_dogs_dir, fname)
shutil.copyfile(src, dst)
# 原数据集中1000-1500张狗送入狗验证集
fnames = ['dog.{}.jpg'.format(i) for i in range(1000, 1500)]
for fname in fnames:
src = os.path.join(original_dataset_dir, fname)
dst = os.path.join(validation_dogs_dir, fname)
shutil.copyfile(src, dst)
# 原数据集中1500-2000张狗送入狗测试集
fnames = ['dog.{}.jpg'.format(i) for i in range(1500, 2000)]
for fname in fnames:
src = os.path.join(original_dataset_dir, fname)
dst = os.path.join(test_dogs_dir, fname)
shutil.copyfile(src, dst)
2.构建网络
from keras import layers
from keras import models
# 构建网络
model=models.Sequential()
model.add(layers.Conv2D(32,(3,3),activation='relu',input_shape=(150,150,3)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(128, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(128, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Flatten())
model.add(layers.Dense(512, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
# 配置模型
import tensorflow
from tensorflow import optimizers
model.compile(loss='binary_crossentropy',
optimizer=optimizers.RMSprop(learning_rate=1e-4),
metrics=['acc'])
3.数据预处理
(1) 读取图像文件。
(2) 将JPEG 文件解码为RGB 像素网格。
(3) 将这些像素网格转换为浮点数张量。
(4) 将像素值(0~255 范围内)缩放到[0, 1] 区间(正如你所知,神经网络喜欢处理较小的输
入值)
from keras.preprocessing.image import ImageDataGenerator
# 图像缩放
train_datagen = ImageDataGenerator(rescale=1./255)
test_datagen = ImageDataGenerator(rescale=1./255)
# 调整图像大小
train_generator = train_datagen.flow_from_directory(
train_dir,
target_size=(150, 150),
batch_size=20,
class_mode='binary')
validation_generator = test_datagen.flow_from_directory(
validation_dir,
target_size=(150, 150),
batch_size=20,
class_mode='binary')
4.模型配置
# 拟合模型
history = model.fit_generator(
train_generator,
steps_per_epoch=100,
epochs=30,
validation_data=validation_generator,
validation_steps=50)
# 保存模型
model.save('cats_vs_dogs.h5')
# 绘制曲线
import matplotlib.pyplot as plt
acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(1, len(acc) + 1)
plt.plot(epochs, acc, 'bo', label='Training acc')
plt.plot(epochs, val_acc, 'b', label='Validation acc')
plt.title('Training and validation accuracy')
plt.legend()
plt.figure()
plt.plot(epochs, loss, 'bo', label='Training loss')
plt.plot(epochs, val_loss, 'b', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()
plt.show()
5.数据增强
对图像进行处理,以新增更多样本
5.3 使用预训练的卷积神经网络
1.特征提取
特征提取是使用之前网络学到的表示来从新样本中提取出的特征。然后将这些特征输入一个新的分类器,从头开始训练。
对于卷积神经网络而言,特征提取就是取出之前训练好的网络的卷积基,在上面运行新数据,然后在输出上面训练一个新的分类器
VGG16卷积基
from keras.applications import VGG16
conv_base = VGG16(weights='imagenet',
include_top=False,
input_shape=(150, 150, 3))
weights指定模型初始化的权重检查点;include_top 指定模型最后是否包含密集连接分类器;input_shape 是输入到网络中的图像张量的形状
2.微调模型
特征提取冻结了模型基,微调就是将顶部的几层解冻,并将解冻的这几层与新增加的部分联合训练
步骤:
(1) 在已经训练好的基网络(base network)上添加自定义网络。
(2) 冻结基网络。
(3) 训练所添加的部分。
(4) 解冻基网络的一些层。
(5) 联合训练解冻的这些层和添加的部分。
一文读懂迁移学习和预训练_healingwounds的博客-优快云博客_预训练3
3.结论
(1)卷积神经网络是用于计算机视觉任务的最佳机器学习模型
(2)在小型数据集上的主要问题是过拟合。数据增强是一种降低过拟合的方法。
(3)利用特征提取,可以很容易将现有的卷积神经网络复用于新的数据集
(4)可以使用微调,将现有模型之前学到的一些数据表示应用于新问题。这种方法可以进一步提高模型性能。
5.4 卷积神经网络可视化
1.可视化中间激活
对于给定输入,展示网络中各个卷积层和池化层输出的特征图
2.可视化过滤器
以通过在输入空间中进行梯度上升来实现