Keras框架下的猫狗识别(一)
Keras框架下的猫狗识别(二)
紧接上文
上文构建出最为简单的CNN神经网络模型,从而来达到大概分辨猫和狗的目的。 而在这篇博客中,我们还可以通过另外一种方法来构建模型,从而同样达到识别猫狗的目的。 在这篇博客中,我们使用VGG16-bottleneck的方法,进行猫狗的识别。代码如下(示例):
from tensorflow.keras.applications.vgg16 import VGG16
from tensorflow.keras.preprocessing import image
from tensorflow.keras.applications.vgg16 import preprocess_input
import numpy as np
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from keras.utils import np_utils
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dropout, Flatten, Dense
from tensorflow.keras.optimizers import Adam
同样的,我们也需要像之前那样操作,引入该模型训练所需要的库。 有几个搭建神经网络的常用库,就不再重复介绍。我们需要重点关注VGG16 ,因为我们所使用的VGG16来源于网络,VGG已经是一个较为完善的模型,我们只需要将其下载下来。
使用如下代码:
# 载入预训练的VGG16模型,不包括全连接层
model = VGG16(weights='imagenet', include_top=False)
将VGG16模型下载下来,这一步需要花费一些时间,而下载下来的模型会保存在C:/user/sir/.keras/model中。我们接下来的操作就要开始围绕着VGG16模型展开。 首先使用如下代码,先看看VGG的神经层的构建:
model.summary()
我们会得到这样的表格:
可以看到VGG16的神经层,其中包括卷积层、池化层等。但也不难发现,VGG16并不具备输出层,所以这也明确了我们后续的任务——我们需要往VGG16模型中添加输出层,以满足目的。
代码如下:
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') # 填充方式
batch_size = 32
#
train_steps = int((3528 + batch_size - 1)/batch_size)*10
test_steps = int((1232 + batch_size - 1)/batch_size)*10
generator = datagen.flow_from_directory(
'train',
target_size=(150, 150),
batch_size=batch_size,
class_mode=None, # 不生成标签
shuffle=False) # 不随机打乱
# 得到训练集数据
bottleneck_features_train = model.predict_generator(generator, train_steps)
print(bottleneck_features_train.shape)
# 保存训练集bottleneck结果
np.save(open('bottleneck_features_train.npy', 'wb'), bottleneck_features_train)
generator = datagen.flow_from_directory(
'test',
target_size=(150, 150),
batch_size=batch_size,
class_mode=None, # 不生成标签
shuffle=False) # 不随机打乱
# 得到预测集数据
bottleneck_features_test = model.predict_generator(generator, test_steps)
print(bottleneck_features_test.shape)
# 保存测试集bottleneck结果
np.save(open('bottleneck_features_test.npy', 'wb'), bottleneck_features_test)
train_data = np.load(open('bottleneck_features_train.npy','rb'))
# the features were saved in order, so recreating the labels is easy
labels = np.array([0] * 2016 + [1] * 1512)
train_labels = np.array([])
train_labels=np.concatenate((train_labels,labels))
test_data = np.load(open('bottleneck_features_test.npy','rb'))
labels = np.array([0] * 552 + [1] * 680)
test_labels = np.array([])
test_labels=np.concatenate((test_labels,labels))
train_labels = np_utils.to_categorical(train_labels,num_classes=2)
test_labels = np_utils.to_categorical(test_labels,num_classes=2)
即便VGG16并不具备输出层,但我们仍然可以先运行该模型,并将其保存,为后续任务节约时间。这里就是以'bottleneck_features_train.npy和bottleneck_features_test.npy的形式保存。同时,在这一步中,我们也将图片数据格式进行更改。
model = Sequential()
model.add(Flatten(input_shape=train_data.shape[1:]))
model.add(Dense(256, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(2, activation='softmax'))
# 定义优化器
adam = Adam(lr=1e-4)
# 定义优化器,loss function,训练过程中计算准确率
model.compile(optimizer=adam,loss='categorical_crossentropy',metrics=['accuracy'])
model.fit(train_data, train_labels,
epochs=20, batch_size=batch_size,
validation_data=(test_data, test_labels))
model.save_weights('bottleneck_fc_model.h5')
在这一步中,我们继续补充完善了VGG未完成的部分,补出了输出层,并且开始训练。
使用VGG16-bottleneck模型,相比于CNN简单神经网络搭建的模型,无论是速度还是准确性都大大的提高了。