看了一下之前做过的有关深度学习的实验,发现InceptionV3这个模型还没有用到,虽然并没有自己实现该网络模型,但是先学习一下它的原理,再利用迁移学习测试一下它的模型准确率,也不失为一种不错的学习方法。 本次实验利用InceptionV3网络模型,实现水果识别。
1.导入库
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import os,pathlib,PIL
gpus = tf.config.experimental.list_physical_devices('GPU')
tf.config.experimental.set_memory_growth(gpus[0], True)
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
2.数据加载
原数据集中给出了训练集、验证集、测试集三个子文件夹,就不需要人为的划分了。每个子文件夹中包含21类水果。
data_dir_train = "E:/tmp/.keras/datasets/fruit_rec/fruits-360-original-size/fruits-360-original-size/Training"
data_dir_test = "E:/tmp/.keras/datasets/fruit_rec/fruits-360-original-size/fruits-360-original-size/Test"
data_dir_validation = "E:/tmp/.keras/datasets/fruit_rec/fruits-360-original-size/fruits-360-original-size/Validation"
data_dir_train = pathlib.Path(data_dir_train)
data_dir_test = pathlib.Path(data_dir_test)
data_dir_validation = pathlib.Path(data_dir_validation)
all_images_paths = list(data_dir_train.glob('*'))
all_images_paths = [str(path) for path in all_images_paths]
all_label_names = [path.split("\\")[8].split(".")[0] for path in all_images_paths]
超参数的设置
height = 256
width = 256
epochs =10
batch_size = 32
分别构建训练集、验证集和测试集的ImageDataGenerator,并进行数据预处理
train_data_gen = tf.keras.preprocessing.image.ImageDataGenerator(
rescale=1./255,
rotation_range=45,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True
)
test_data_gen = tf.keras.preprocessing.image.ImageDataGenerator(
rescale=1./255
)
validation_data_gen = tf.keras.preprocessing.image.ImageDataGenerator(
rescale=1./255,
validation_split=0.2
)
train_ds = train_data_gen.flow_from_directory(
directory=data_dir_train,
target_size=(height,width),
shuffle=True,
batch_size=batch_size,
class_mode='categorical'
)
test_ds = test_data_gen.flow_from_directory(
directory=data_dir_test,
target_size=(height,width),
shuffle=True,
batch_size=batch_size,
class_mode='categorical'
)
validation_ds = validation_data_gen.flow_from_directory(
directory=data_dir_validation,
target_size=(height,width),
shuffle=True,
batch_size=batch_size,
class_mode='categorical'
)
整理后的数据如下所示:
3.InceptionV3网络
InceptionV3模型是谷歌Inception系列里面的第三代模型,相比于其它神经网络模型,Inception网络最大的特点在于将神经网络层与层之间的卷积运算进行了拓展。 就像VGG,AlexNet网络,它就是一直垂直卷积下来的,一层接着一层。 ResNet则是创新性的引入了残差网络的概念,使得靠前若干层的某一层数据输出直接跳过多层引入到后面数据层的输入部分,后面的特征层的内容会有一部分由其前面的某一层线性贡献。
Google Inception Net在2014年的 ImageNet Large Scale Visual Recognition Competition (ILSVRC)中取得第一名,该网络以结构上的创新取胜,通过采用全局平均池化层取代全连接层,极大的降低了参数量,是非常实用的模型,一般称该网络模型为Inception V1。随后的Inception V2中,引入了Batch Normalization方法,加快了训练的收敛速度。在Inception V3模型中,通过将二维卷积层拆分成两个一维卷积层,不仅降低了参数数量,同时减轻了过拟合现象。参考链接
Inception网络采用不同大小的卷积核,使得存在不同大小的感受野,最后实现拼接达到不同尺度特征的融合。
整体结构图如下所示: 模型搭建: 在VGG系列的模型搭建时,利用迁移学习得到网络模型后,会将trainable设置为False,也就意味着前面的参数是不能够训练的。但是InceptionV3网络以及ResNet网络,由于引入了BN层,因此不能直接将trainable设置为False,博主在参考别人的博客时,有的博主提出在整个网络模型搭建完成后,再将trainable设置为False,但是博主的实验效果并不好,在训练集上面的准确率非常高,但是测试集上准确率特别低。因此直接去掉了将trainable设置为False这一步骤,模型的准确率得到提高。
base_model = tf.keras.applications.InceptionV3(weights = 'imagenet',include_top = False,pooling = None,input_shape = (height,width,3))
model = tf.keras.Sequential()
model.add(base_model)
model.add(tf.keras.layers.GlobalAveragePooling2D())
model.add(
tf.keras.layers.Dense(128,activation='relu',kernel_initializer=tf.keras.initializers.glorot_normal(seed=32))
)
model.add(
tf.keras.layers.Dense(64,activation='relu',kernel_initializer=tf.keras.initializers.glorot_normal(seed=33))
)
model.add(
tf.keras.layers.Dense(21,activation='softmax',kernel_initializer=tf.keras.initializers.glorot_normal(seed=3))
)
model.compile(
optimizer=tf.keras.optimizers.Adam(learning_rate=0.001),
loss = "categorical_crossentropy",
metrics = ['accuracy']
)
实验效果如下所示,经过10个epoch之后,模型准确率在90%左右。 利用验证集绘制混淆矩阵,关于混淆矩阵的代码,参考我之前的博客即可。 努力加油a啊
|