一、图像预处理
通常我们获得的图像并不能直接输入到模型中,需要先将图像转换为float值张量,keras中的ImageDataGenerator可以快速生成python生成器,将图像自动转换为预处理的张量批量。
from keras.preprocessing.image import ImageDataGenerator
# All images will be rescaled by 1./255
train_datagen = ImageDataGenerator(rescale=1./255)
test_datagen = ImageDataGenerator(rescale=1./255)
train_generator = train_datagen.flow_from_directory(
# This is the target directory
train_dir,
# All images will be resized to 150x150
target_size=(150, 150),
batch_size=20,
# Since we use binary_crossentropy loss, we need binary labels
class_mode='binary')
validation_generator = test_datagen.flow_from_directory(
validati00on_dir,
target_size=(150, 150),
batch_size=20,
class_mode='binary')
二、增强模型的泛化能力
当我们训练样本较少时,模型容易出现过拟合现象,常见的方法是数据增强、添加Dropout层以及权重衰减(L2)。
2.1 数据增强通过对原始图像进行随即变换而获得新的样本数(与原始图像不同),往往能增强网络的泛化能力。keras中的ImageDataGenerator模块可以执行多次随机变量来实现。
from keras.preprocessing.image import ImageDataGenerator
datagen = ImageDataGenerator(
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest')
2.2 添加Dropout层,通常添加到密集连接分类器之前。
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.Dropout(0.5))
###############################
model.add(layers.Dense(512, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy',
optimizer=optimizers.RMSprop(lr=1e-4),
metrics=['acc'])
三、预训练的神经网络
对于已经在各个比赛中得到验证的模型,通常可以将预训练模型中学习到的特征的空间层次结构有效的作为视觉世界的通用模型。如何使用预训练模型,常用的方法有:特征提取与微调模型。
3.1特征提取
特征提取是使用之前网络学到的表示来重新样本中提取的有趣的特征,然后将这些特征输入一个新的分类器中,重新开始训练,通常只提取卷积基(卷积与池化层)而不重复使用全连接层。在编译全连接层时,应该’冻结‘卷积基,在keras中冻结网络的方法是将其trainable属性设置为Flase。
3.2 微调模型
微调模型即冻结某些conv层,对某些conv层进行微调,通常微调模型的最后两三层。如下面的模型在训练时只更改block5_conv1层参数的权重,而不更改之前已经冻结的参数。
conv_base.trainable = True
set_trainable = False
for layer in conv_base.layers:
if layer.name == 'block5_conv1':
set_trainable = True
if set_trainable:
layer.trainable = True
else:
layer.trainable = False
model.compile(loss='binary_crossentropy',
optimizer=optimizers.RMSprop(lr=1e-5),
metrics=['acc'])
history = model.fit_generator(
train_generator,
steps_per_epoch=100,
epochs=100,
validation_data=validation_generator,
validation_steps=50)
四、模型保存
model.save('modelname.h5')
五、卷积神经网络的可视化
5.1 可视化卷积神经网络的中间输出(中间激活)
from keras import models
import matplotlib.pyplot as plt
# Extracts the outputs of the top 8 layers:
layer_outputs = [layer.output for layer in model.layers[:8]]
# Creates a model that will return these outputs, given the model input:
activation_model = models.Model(inputs=model.input, outputs=layer_outputs)
# This will return a list of 5 Numpy arrays:
# one array per layer activation
activations = activation_model.predict(img_tensor)
first_layer_activation = activations[0]
print(first_layer_activation.shape)
plt.matshow(first_layer_activation[0, :, :, 3], cmap='viridis')
plt.show()
5.2 可视化卷积网络的过滤器
5.3 可视化类激活的热力图