基于CNN算法自定义模型的动物识别项目1
资源文件
一、数据集介绍
(1)数据集分为训练集train、测试集test两部分
(2)动物类别:bird、cat、cattle、chicken、dog、dolphin、duck、elephant、giraffe、monkey、pig、rabbit、rat、sheep、tiger。
(3)train数据集中每类动物有200张图片
(4)test数据集中每类动物有20张图片
二、开发步骤
1.引入库
from keras.models import Sequential
from keras.layers import Conv2D,MaxPool2D,Dropout,Flatten,Dense
from keras.optimizers import Adam
from keras.preprocessing.image import ImageDataGenerator
import matplotlib.pyplot as plt
from keras_preprocessing.image import img_to_array,load_img
from keras.models import load_model
from keras import models
from keras.preprocessing import image
import numpy as np
2.定义模型
#定义模型
model = Sequential()
# 150*150*3的彩色图片 32个卷积核 卷积核大小3*3 RELU激活函数
model.add(Conv2D(input_shape=(150,150,3),filters=32,kernel_size=3,padding='same',activation='relu'))
model.add(Conv2D(filters=32,kernel_size=3,padding='same',activation='relu'))
# 池化大小2 池化步长2
model.add(MaxPool2D(pool_size=2,strides=2))
model.add(Conv2D(filters=64,kernel_size=3,padding='same',activation='relu'))
model.add(Conv2D(filters=64,kernel_size=3,padding='same',activation='relu'))
model.add(MaxPool2D(pool_size=2,strides=2))
model.add(Conv2D(filters=128,kernel_size=3,padding='same',activation='relu'))
model.add(Conv2D(filters=128,kernel_size=3,padding='same',activation='relu'))
model.add(MaxPool2D(pool_size=2,strides=2))
# 得到二维特征图
# 转换变成一维
model.add(Flatten())
model.add(Dense(64,activation='relu')) # 全连接层
model.add(Dropout(0.5)) #抵抗过拟合
model.add(Dense(15,activation='softmax')) #15为15分类,一般用在分类任务的输出层
model.summary()
3.定义优化器
#定义优化器,交叉熵计算准确率,optimizer梯度下降的优化方法
adam = Adam(lr=1e-4)
model.compile(optimizer=adam,loss='categorical_crossentropy',metrics=['accuracy'])
4.训练数据增强
train_datagen = ImageDataGenerator(
rotation_range=40,
width_shift_range=0.2, #随机旋转度数
height_shift_range=0.2, #随机水平位移
rescale=1/255, #数据归一化
shear_range=0.2, #随机裁剪
zoom_range=0.2, #随机放大
horizontal_flip=True, #水平翻转
fill_mode='nearest', #填充方式
)
5.测试数据归一化
test_data = ImageDataGenerator(
rescale=1/255, #数据归一化
)
6.数据生成
# 定义数据生成
batch_size = 32 #每次传32张照片
#生成训练数据
train_generator = train_datagen.flow_from_directory(
'/BASICCNN/image/train',
target_size=(150,150),
batch_size=batch_size,
)
#生成测试数据
test_generator = test_data.flow_from_directory(
'/BASICCNN/image/test',
target_size=(150,150),
batch_size=batch_size,
)
7.查看类别定义
print(train_generator.class_indices)
8.训练模型
#训练模型 20个周期 测试集数据
history=model.fit_generator(train_generator,epochs=20,validation_data=test_generator)
model.save('/BASICCNN/TrainModel_h5/model_CNNTrain.h5')
9.模型可视化
#训练模型可视化
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.title('Model_Accuracy')
plt.ylabel('Accuracy')
plt.xlabel('Epochs')
plt.legend(['Train_Accuracy','Valid_Accuracy'],loc='upper left')
plt.savefig('/BASICCNN/TrainImage/CNNTrain_accuracy.png')
plt.show()
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('Model_Loss')
plt.ylabel('Loss')
plt.xlabel('Epochs')
plt.legend(['Train_Loss','Valid_Loss'],loc='upper left')
plt.savefig('/BASICCNN/TrainImage/CNNTrain_loss.png')
plt.show()
10.显示指定层
#通过model的属性layers查询模型中的各层
model.layers
print(len(model.layers))
#通过各层的属性output获取各层输出张量
layer_outputs = [layer.output for layer in model.layers[:9]]
#创建新的模型,一个输入,多个输出
new_model = models.Model(inputs=model.input,outputs=layer_outputs)
11.预测每一层输出
#加载测试图片
img_path = '/BASICCNN/image/test/duck/duck.1010.jpg'
img = image.load_img(img_path,target_size=(150,150))
plt.imshow(img)
#图片预处理
#(1)将image转化为数组
img_tensor_3D = image.img_to_array(img)
#(2)由3D扩展为4D
img_tensor_4D = np.expand_dims(img_tensor_3D,axis=0)
#(3)归一化处理
img_tensor_4D = img_tensor_4D/255.
print(img_tensor_4D.shape)
img_tensor_4D
#将第二部分处理后的图片张量作为输入,得到各层实际输出张量值,使用model.predict()
activations = new_model.predict(img_tensor_4D)
#(1)查看第1层输出的张量值,输出张量空间大小可与model.summary()比对
first_layer_activation = activations[0]
print(first_layer_activation.shape)
print(first_layer_activation[0][0][0][0])
print(activations[2].shape)
12.可视化单层网络输出
plt.imshow(first_layer_activation[0,:,:,0],cmap='viridis')
plt.matshow(first_layer_activation[0,:,:,3],cmap='viridis')
13.增强可视化效果
characters = activations[0][0,:,:,0]
characters -= characters.mean() #平均值
characters /= characters.std() #标准差
characters *=64
characters +=128
characters = np.clip(characters,0,255).astype('uint8')
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
ax1 = plt.subplot(121)
ax1.set_title('原始数据可视化效果')
ax1.imshow(activations[0][0,:,:,0],cmap='viridis')
ax2 = plt.subplot(122)
ax2.set_title('处理后数据可视化效果')
ax2.imshow(characters,cmap='viridis')
plt.savefig('/BASICCNN/TrainImage/CNN_TestGen_layer1.png')
characters
14.可视化所有中间网络层
layer_name = []
for i in model.layers[:9]:
layer_name.append(i.name)
print(layer_name)
images_per_row = 16
for name,act in zip(layer_name,activations):
n_features = act.shape[-1]
rows = n_features//images_per_row
size = act.shape[1]
display_grid = np.zeros((size*rows,size*images_per_row))
for r in range(rows):
for k in range(images_per_row):
channel_img = act[0,:,:,r*images_per_row+k]
channel_img -= channel_img.mean() #平均值
# channel_img /= channel_img.std()
channel_img *=64
channel_img +=128
channel_img = np.clip(channel_img,0,255).astype('uint8')
display_grid[r*size:(r+1)*size,k*size:(k+1)*size] = channel_img
scale = 1./size
scale = 1./size
fig = plt.figure(figsize=(scale*display_grid.shape[1],scale*display_grid.shape[0]))
plt.title(name)
plt.grid(False)
plt.imshow(display_grid,aspect='auto',cmap='viridis')
plt.axis('off')
fig.savefig('/BASICCNN/TrainImage/CNNintlayer' + str(k) + '.png')
plt.show()
plt.cla()
plt.close('all')
15.验证模型预测结果
label = np.array(['bird', 'cat', 'cattle', 'chicken', 'dog', 'dolphin', 'duck', 'elephant',
'giraffe', 'monkey', 'pig', 'rabbit', 'rat', 'sheep', 'tiger'])
# 载入模型
model = load_model('/BASICCNN/TrainModel_h5/model_CNNTrain.h5')
# 导入图片
image = load_img('image/test/bird/bird.1010.jpg')
image = image.resize((150,150))
image = img_to_array(image)
image = image/255
image = np.expand_dims(image,0)
image.shape
print(label[model.predict_classes(image)])