使用Keras预训练模型完成猫狗识别
VGG16是一种深度卷积神经网络,由牛津大学计算机视觉研究小组在2014年提出。它是ImageNet图像识别竞赛的冠军,拥有较好的图像识别和分类效果。VGG16架构非常简单,特征提取部分由13个卷积层和5个池化层组成,分类器部分有3个全连接层。VGG16中的卷积层均为3×3的卷积核,池化层为2×2的最大池化,卷积核数量逐层增加,以提取越来越复杂的特征。
VGG16可以分为两个部分:特征提取和分类。特征提取部分包括13个卷积层和5个池化层。其中前12个卷积层都是由两个卷积层和一个池化层组成,每个卷积层都有64个卷积核,激活函数为ReLU。这样的设计使得VGG16的特征提取能力更加强大,可以提取较为复杂的特征。第13个卷积层有512个卷积核,激活函数也为ReLU,该层的作用是将图像特征进行更深入的抽象。在特征提取部分之后,VGG16还包括一个分类器部分,即3个全连接层,其中第一个全连接层有4096个节点,第二个全连接层也有4096个节点。最后一个全连接层有1000个节点,对应ImageNet的1000个类别。
VGG16的优点是具有良好的表现,但是它的模型参数较多,需要较大的存储空间和计算资源。针对这个问题,VGG16的作者提出了VGG19模型,它在VGG16的基础上增加了几个卷积层和池化层,但是模型参数更多,计算资源更加消耗。
总的来说,VGG16是一个简单而有效的深度卷积神经网络,特征提取能力强,可以有效地提取图像的特征信息,从而得到较好的图像识别和分类效果。
1. 导入Keras库
from keras import layers import tensorflow as tf import keras import numpy as np import os import shutil import warnings warnings.filterwarnings('ignore')
Using TensorFlow backend.
2. 导入数据集
base_dir = './dataset/cat_dog' train_dir = base_dir + '/train' train_dog_dir = train_dir + '/dog' train_cat_dir = train_dir + '/cat' test_dir = base_dir + '/test' test_dog_dir = test_dir + '/dog' test_cat_dir = test_dir + '/cat' dc_dir = './dataset/dc/train'
if not os.path.exists(base_dir): os.mkdir(base_dir) os.mkdir(train_dir) os.mkdir(train_dog_dir) os.mkdir(train_cat_dir) os.mkdir(test_dir) os.mkdir(test_dog_dir) os.mkdir(test_cat_dir) fnames = ['cat.{}.jpg'.format(i) for i in range(1000)] for fname in fnames: src = os.path.join(dc_dir, fname) dst = os.path.join(train_cat_dir, fname) shutil.copyfile(src, dst) fnames = ['cat.{}.jpg'.format(i) for i in range(1000, 1500)] for fname in fnames: src = os.path.join(dc_dir, fname) dst = os.path.join(test_cat_dir, fname) shutil.copyfile(src, dst) fnames = ['dog.{}.jpg'.format(i) for i in range(1000)] for fname in fnames: src = os.path.join(dc_dir, fname) dst = os.path.join(train_dog_dir, fname) shutil.copyfile(src, dst) fnames = ['dog.{}.jpg'.format(i) for i in range(1000, 1500)] for fname in fnames: src = os.path.join(dc_dir, fname) dst = os.path.join(test_dog_dir, fname) shutil.copyfile(src, dst)
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=(200, 200), batch_size=20, class_mode='binary' ) test_generator = test_datagen.flow_from_directory( test_dir, target_size=(200, 200), batch_size=20, class_mode='binary' )
Found 2000 images belonging to 2 classes. Found 1000 images belonging to 2 classes.
3. Keras内置经典网络实现
covn_base = keras.applications.VGG16(weights=None, include_top=False)
WARNING:tensorflow:From /home/nlp/anaconda3/lib/python3.7/site-packages/keras/backend/tensorflow_backend.py:4070: The name tf.nn.max_pool is deprecated. Please use tf.nn.max_pool2d instead.
covn_base.summary()
Model: "vgg16" _________________________________________________________________ Layer (type) Output Shape Param # _________________________________________________________________ input_1 (InputLayer) (None, None, None, 3) 0 _________________________________________________________________ block1_conv1 (Conv2D) (None, None, None, 64) 1792 _________________________________________________________________ block1_conv2 (Conv2D) (None, None, None, 64) 36928 _________________________________________________________________ block1_pool (MaxPooling2D) (None, None, None, 64) 0 _________________________________________________________________ block2_conv1 (Conv2D) (None, None, None, 128) 73856 _________________________________________________________________ block2_conv2 (Conv2D) (None, None, None, 128) 147584 _________________________________________________________________ block2_pool (MaxPooling2D) (None, None, None, 128) 0 _________________________________________________________________ block3_conv1 (Conv2D) (None, None, None, 256) 295168 _________________________________________________________________ block3_conv2 (Conv2D) (None, None, None, 256) 590080 _________________________________________________________________ block3_conv3 (Conv2D) (None, None, None, 256) 590080 _________________________________________________________________ block3_pool (MaxPooling2D) (None, None, None, 256) 0 _________________________________________________________________ block4_conv1 (Conv2D) (None, None, None, 512) 1180160 _________________________________________________________________ block4_conv2 (Conv2D) (None, None, None, 512) 2359808 _________________________________________________________________ block4_conv3 (Conv2D) (None, None, None, 512) 2359808 _________________________________________________________________ block4_pool (MaxPooling2D) (None, None, None, 512) 0 _________________________________________________________________ block5_conv1 (Conv2D) (None, None, None, 512) 2359808 _________________________________________________________________ block5_conv2 (Conv2D) (None, None, None, 512) 2359808 _________________________________________________________________ block5_conv3 (Conv2D) (None, None, None, 512) 2359808 _________________________________________________________________ block5_pool (MaxPooling2D) (None, None, None, 512) 0 _________________________________________________________________ Total params: 14,714,688 Trainable params: 14,714,688 Non-trainable params: 0
model = keras.Sequential() model.add(covn_base) model.add(layers.GlobalAveragePooling2D()) model.add(layers.Dense(512, activation='relu')) model.add(layers.Dense(1, activation='sigmoid'))
model.summary()
Model: "sequential_1" _________________________________________________________________ Layer (type) Output Shape Param # _________________________________________________________________ vgg16 (Model) (None, None, None, 512) 14714688 _________________________________________________________________ global_average_pooling2d_1 ( (None, 512) 0 _________________________________________________________________ dense_1 (Dense) (None, 512) 262656 _________________________________________________________________ dense_2 (Dense) (None, 1) 513 _________________________________________________________________ Total params: 14,977,857 Trainable params: 14,977,857 Non-trainable params: 0
covn_base.trainable = False #设置权重不可变,卷积基不可变
model.summary()
Model: "sequential_1" _________________________________________________________________ Layer (type) Output Shape Param # _________________________________________________________________ vgg16 (Model) (None, None, None, 512) 14714688 _________________________________________________________________ global_average_pooling2d_1 ( (None, 512) 0 _________________________________________________________________ dense_1 (Dense) (None, 512) 262656 _________________________________________________________________ dense_2 (Dense) (None, 1) 513 _________________________________________________________________ Total params: 14,977,857 Trainable params: 263,169 Non-trainable params: 14,714,688
model.compile(optimizer=keras.optimizers.Adam(lr=0.001), loss='binary_crossentropy', metrics=['acc'])
WARNING:tensorflow:From /home/nlp/anaconda3/lib/python3.7/site-packages/tensorflow/python/ops/nn_impl.py:180: add_dispatch_support.<locals>.wrapper (from tensorflow.python.ops.array_ops) is deprecated and will be removed in a future version. Instructions for updating: Use tf.where in 2.0, which has the same broadcast rule as np.where
4. 训练模型
history = model.fit_generator( train_generator, steps_per_epoch=10, epochs=15, validation_data=test_generator, validation_steps=50)
WARNING:tensorflow:From /home/nlp/anaconda3/lib/python3.7/site-packages/keras/backend/tensorflow_backend.py:422: The name tf.global_variables is deprecated. Please use tf.compat.v1.global_variables instead. Epoch 1/15 9/10 [==========================>...] - ETA: 5s - loss: 0.6912 - acc: 0.5500 ……
5. 分析模型
import matplotlib.pyplot as plt %matplotlib inline plt.plot(history.epoch, history.history['loss'], 'r', label='loss') plt.plot(history.epoch, history.history['val_loss'], 'b--', label='val_loss') plt.plot(history.epoch, history.history['acc'], 'r') plt.plot(history.epoch, history.history['val_acc'], 'b--') plt.legend()