构建网络
构建卷积神经网络,包括4对卷积层和池化层,输出层用sigmoid激活(二分类),并且对
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.Dropout(0.5))
model.add(layers.Dense(512, activation="relu"))
model.add(layers.Dense(1, activation="sigmoid"))
编译模型
使用二分类交叉熵损失函数
#编译模型
from keras import optimizers
model.compile(loss="binary_crossentropy",
optimizer=optimizers.RMSprop(lr=1e-4),
metrics=["accuracy"]
)
数据预处理
利用keras将本地存储的训练图像数据读取出来返回生成器,并对图像进行数据增强
#数据预处理
from keras.preprocessing.image import ImageDataGenerator
#存储数据的路径
train_img_dir = "E:/code/python deeplearning/dataset/c_d_0/train"
validation_img_dir = "E:/code/python deeplearning/dataset/c_d_0/validation"
#数据生成器,将原像素值压缩到0-1之间并对训练数据进行数据增强
train_datagen = ImageDataGenerator(
rescale=1./255,
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True
)
test_datagen = ImageDataGenerator(rescale=1./255,)
#训练数据生成器
train_generator = train_datagen.flow_from_directory(
train_img_dir,
target_size=(150,150),
batch_size=20,
class_mode="binary"
)
#验证数据生成器
validation_generator = test_datagen.flow_from_directory(
validation_img_dir,
target_size=(150,150),
batch_size=20,
class_mode="binary"
)
读取到训练数据2000条,验证数据500条
模型训练
fit进训练数据进行训练,batch大小为20,所有每轮次需要100步,验证每轮次需要25步
history = model.fit_generator(
train_generator,
steps_per_epoch=100,
epochs=100,
validation_data=validation_generator,
validation_steps=25
)
结果显示验证集准确率达到0.8240
模型保存至本地
model.save("E:/code/python deeplearning/model/cats_dogs_1.h5")
保存结果如下:
绘制损失和精度曲线
import matplotlib.pyplot as plt
acc = history.history["accuracy"]
loss = history.history["loss"]
val_acc = history.history["val_accuracy"]
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()
特征图可视化
从测试数据中读取一条样本
img_path = "E:/code/python deeplearning/dataset/c_d_1/test/cat.2018.jpg"
from keras.preprocessing import image
import numpy as np
img = image.load_img(img_path, target_size=(150,150))
img_tensor = image.img_to_array(img)
img_tensor = np.expand_dims(img_tensor, axis=0)
img_tensor /= 255.
print(img_tensor.shape)
显示该样本
import matplotlib.pyplot as plt
plt.imshow(img_tensor[0])
plt.show()
建立模型,输入为原图像,输出为原模型的前8层的激活输出的特征图
from keras import models
layer_outputs = [layer.output for layer in model.layers[:8]]
activation_model = models.Model(inputs=model.input, outputs=layer_outputs)
获得改样本的特征图
activations = activation_model.predict(img_tensor)
显示第一层激活输出特的第一个滤波器的特征图
import matplotlib.pyplot as plt
first_layer_activation = activations[0]
plt.matshow(first_layer_activation[0,:,:,1], cmap="viridis")
显示前8层激活输出的全部特征图
#存储层的名称
layer_names = []
for layer in model.layers[:8]:
layer_names.append(layer.name)
# 每行显示16个特征图
images_pre_row = 16 #每行显示的特征图数
# 循环8次显示8层的全部特征图
for layer_name, layer_activation in zip(layer_names, activations):
n_features = layer_activation.shape[-1] #保存当前层的特征图个数
size = layer_activation.shape[1] #保存当前层特征图的宽高
n_col = n_features // images_pre_row #计算当前层显示多少行
#生成显示图像的矩阵
display_grid = np.zeros((size*n_col, images_pre_row*size))
#遍历将每个特张图的数据写入到显示图像的矩阵中
for col in range(n_col):
for row in range(images_pre_row):
#保存该张特征图的矩阵(size,size,1)
channel_image = layer_activation[0,:,:,col*images_pre_row+row]
#为使图像显示更鲜明,作一些特征处理
channel_image -= channel_image.mean()
channel_image /= channel_image.std()
channel_image *= 64
channel_image += 128
#把该特征图矩阵中不在0-255的元素值修改至0-255
channel_image = np.clip(channel_image, 0, 255).astype("uint8")
#该特征图矩阵填充至显示图像的矩阵中
display_grid[col*size:(col+1)*size, row*size:(row+1)*size] = channel_image
scale = 1./size
#设置该层显示图像的宽高
plt.figure(figsize=(scale*display_grid.shape[1],scale*display_grid.shape[0]))
plt.title(layer_name)
plt.grid(False)
#显示图像
plt.imshow(display_grid, aspect="auto", cmap="viridis")