Tensorflow2.0 Mobilenetv2进行图片分类

Mobilenet v2 网络

论文:《MobileNetV2: Inverted Residuals and Linear Bottlenecks》
论文地址:https://arxiv.org/abs/1801.04381

MobileNetV2是对MobileNetV1的改进,同样是一个轻量化卷积神经网络,它具有两个创新点:

1、Inverted residual block:先用1x1普通卷积将输入的feature map维度变大,然后用3x3 深度可分离卷积方式做卷积运算,最后使用1x1的普通卷积运算将其维度缩小,如下图所示:
Tensorflow2.0 Mobilenetv2进行图片分类_第1张图片

2、Linear Bottlenecks:在最后的1x1卷积运算后,不再使用ReLU激活函数,而是使用线性激活函数,以保留更多特征信息,保证模型的表达能力。
Tensorflow2.0 Mobilenetv2进行图片分类_第2张图片
当stride=1时,block内会有short cut连接;而当stride=2时,block没有short cut连接。
Tensorflow2.0 Mobilenetv2进行图片分类_第3张图片

MobileNetV2网络整体结构:

Tensorflow2.0 Mobilenetv2进行图片分类_第4张图片
tensorflow.keras.applications模块内置了许多模型,包括Xception、InceptionV3、VGG等,我们可以使用内置的MobileNetV2模型,只需修改最后的全连接层输出类别即可。

数据集

数据集地址:https://www.kaggle.com/slothkong/10-monkey-species
采用kaggle上的猴子数据集,包含两个文件:训练集和验证集。每个文件夹包含10个标记为n0-n9的猴子。图像尺寸为400x300像素或更大,并且为JPEG格式(近1400张图像)。
Tensorflow2.0 Mobilenetv2进行图片分类_第5张图片
图片样本
Tensorflow2.0 Mobilenetv2进行图片分类_第6张图片
图片类别标签,训练集,验证集划分说明
Tensorflow2.0 Mobilenetv2进行图片分类_第7张图片

代码

#导入相应的库
from tensorflow.keras.preprocessing.image import ImageDataGenerator
import matplotlib.pyplot as plt
import tensorflow as tf

#设置图片的高和宽,一次训练所选取的样本数,迭代次数
im_height = 224
im_width = 224
batch_size = 64
epochs = 13

image_path = "../input/10-monkey-species/"  # monkey数据集路径
train_dir = image_path + "training/training" # 训练集路径
validation_dir = image_path + "validation/validation" # 验证集路径

# 定义训练集图像生成器,并进行图像增强
train_image_generator = 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,  #水平翻转
                                            fill_mode='nearest')  
                                             
# 使用图像生成器从文件夹train_dir中读取样本,对标签进行one-hot编码
train_data_gen = train_image_generator.flow_from_directory(directory=train_dir,
                                                           batch_size=batch_size,
                                                           shuffle=True,   #打乱数据
                                                           target_size=(im_height, im_width),
                                                           class_mode='categorical')
# 训练集样本数    
total_train = train_data_gen.n

# 定义验证集图像生成器,并对图像进行预处理
validation_image_generator = ImageDataGenerator(rescale=1./255)  #归一化

# 使用图像生成器从验证集validation_dir中读取样本
val_data_gen = validation_image_generator.flow_from_directory(directory=validation_dir,
                                                              batch_size=batch_size,
                                                              shuffle=False,  #不打乱数据
                                                              target_size=(im_height, im_width),
                                                              class_mode='categorical')
# 验证集样本数    
total_val = val_data_gen.n

#使用tf.keras.applications中的MobileNetV2网络,并且使用官方的预训练模型
covn_base = tf.keras.applications.MobileNetV2(weights='imagenet',include_top=False)
covn_base.trainable = True

#冻结前面的层,训练最后五层
for layers in covn_base.layers[:-5]:
    layers.trainable = False
    
#构建模型    
model = tf.keras.Sequential()
model.add(covn_base)
model.add(tf.keras.layers.GlobalAveragePooling2D()) #加入全局平均池化层
model.add(tf.keras.layers.Dense(10,activation='softmax')) #加入输出层(10分类)

#编译模型
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.0001),  #使用adam优化器,学习率为0.0001
              loss=tf.keras.losses.CategoricalCrossentropy(from_logits=False), #交叉熵损失函数
              metrics=["accuracy"])  #评价函数
# 每层参数信息              
model.summary()

#开始训练
history = model.fit(x=train_data_gen,
                    steps_per_epoch=total_train // batch_size,
                    epochs=epochs,
                    validation_data=val_data_gen,
                    validation_steps=total_val // batch_size)


# 记录训练集和验证集的准确率和损失值
history_dict = history.history
train_loss = history_dict["loss"]
train_accuracy = history_dict["accuracy"]
val_loss = history_dict["val_loss"]
val_accuracy = history_dict["val_accuracy"]

# 绘制损失值
plt.figure()
plt.plot(range(epochs), train_loss, label='train_loss')
plt.plot(range(epochs), val_loss, label='val_loss')
plt.legend()
plt.xlabel('epochs')
plt.ylabel('loss')

# 绘制准确率
plt.figure()
plt.plot(range(epochs), train_accuracy, label='train_accuracy')
plt.plot(range(epochs), val_accuracy, label='val_accuracy')
plt.legend()
plt.xlabel('epochs')
plt.ylabel('accuracy')
plt.show()

执行结果

1.模型参数
由于大部分层被冻结了,所以可训练的参数很少,只有732,810个参数

Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
mobilenetv2_1.00_224 (Model) (None, None, None, 1280)  2257984   
_________________________________________________________________
global_average_pooling2d (Gl (None, 1280)              0         
_________________________________________________________________
dense (Dense)                (None, 10)                12810     
=================================================================
Total params: 2,270,794
Trainable params: 732,810
Non-trainable params: 1,537,984
_________________________________________________________________

2.训练过程
从结果可以看出,使用迁移学习的时候模型收敛的速度很快,当训练第13个epoch时训练集准确率为98.36%,验证集的准确率为96.09%

Epoch 1/13
17/17 [==============================] - 91s 5s/step - loss: 1.6202 - accuracy: 0.5019 - val_loss: 0.8118 - val_accuracy: 0.7539
Epoch 2/13
17/17 [==============================] - 91s 5s/step - loss: 0.5115 - accuracy: 0.9168 - val_loss: 0.3875 - val_accuracy: 0.8945
Epoch 3/13
17/17 [==============================] - 90s 5s/step - loss: 0.2788 - accuracy: 0.9371 - val_loss: 0.2711 - val_accuracy: 0.9180
Epoch 4/13
17/17 [==============================] - 92s 5s/step - loss: 0.1982 - accuracy: 0.9568 - val_loss: 0.2426 - val_accuracy: 0.9297
Epoch 5/13
17/17 [==============================] - 90s 5s/step - loss: 0.1657 - accuracy: 0.9613 - val_loss: 0.2165 - val_accuracy: 0.9297
Epoch 6/13
17/17 [==============================] - 90s 5s/step - loss: 0.1348 - accuracy: 0.9720 - val_loss: 0.1942 - val_accuracy: 0.9219
Epoch 7/13
17/17 [==============================] - 90s 5s/step - loss: 0.1212 - accuracy: 0.9758 - val_loss: 0.1516 - val_accuracy: 0.9375
Epoch 8/13
17/17 [==============================] - 90s 5s/step - loss: 0.1197 - accuracy: 0.9729 - val_loss: 0.1303 - val_accuracy: 0.9570
Epoch 9/13
17/17 [==============================] - 91s 5s/step - loss: 0.1110 - accuracy: 0.9778 - val_loss: 0.1261 - val_accuracy: 0.9531
Epoch 10/13
17/17 [==============================] - 89s 5s/step - loss: 0.0912 - accuracy: 0.9874 - val_loss: 0.1293 - val_accuracy: 0.9531
Epoch 11/13
17/17 [==============================] - 93s 5s/step - loss: 0.0864 - accuracy: 0.9826 - val_loss: 0.1229 - val_accuracy: 0.9570
Epoch 12/13
17/17 [==============================] - 92s 5s/step - loss: 0.0738 - accuracy: 0.9855 - val_loss: 0.1174 - val_accuracy: 0.9609
Epoch 13/13
17/17 [==============================] - 90s 5s/step - loss: 0.0706 - accuracy: 0.9836 - val_loss: 0.1143 - val_accuracy: 0.9609

3.准确率曲线
记录每个epoch的训练集和验证集准确率并绘制出来进行对比,可以看到从第4个epoch开始逐渐趋于稳定
Tensorflow2.0 Mobilenetv2进行图片分类_第8张图片
4.损失值曲线
记录每个epoch的训练集和验证集损失值并绘制出来进行对比,同样从4个epoch开始逐渐趋于稳定
Tensorflow2.0 Mobilenetv2进行图片分类_第9张图片

你可能感兴趣的:(Tensorflow2.0 Mobilenetv2进行图片分类)