前言

前面用CNN卷积神经网络对猫狗数据集进行了分类,可以看出一个层数比较低的CNN在做分类的时候效果达不到特别好,前面的CNN只能达到75%-80%的正确率,但是那是由于我们的CNN结构比较简单,所以要想分类效果更好,我们需要用更加复杂的模型,这里我就采用更加复杂的深度残差神经网络(ResNet)对猫狗数据集进行训练分类。

我们可以直接采用预训练模型ResNet50进行模型训练,如果不知道预训练是什么意思,可以去网上搜索相关知识,预训练是迁移学习思想的很好实现,简单来说就是用别人训练好的一个比较复杂的神经网络模型来运用到自己的任务中,采用预训练模型的一个好处就是节省计算资源,我们不需要重新对网络进行训练,只需要训练自己需要的某些层即可,从而大大节省训练时间和计算资源

数据预处理

这里就不进行数据增强操作了,因为我发现增强后效果并不好,所以直接构建了训练集和验证集进行训练,代码如下:

from tensorflow.keras.preprocessing.image import *
batch_size = 64
train_datagen = ImageDataGenerator()
validation_datagen = ImageDataGenerator()
train_generator = train_datagen.flow_from_directory(
        train_dir,
        target_size=(224, 224),
        batch_size=batch_size,
        class_mode='binary')
validation_generator = validation_datagen.flow_from_directory(
        validation_dir,
        target_size=(224, 224),
        batch_size=batch_size,
        class_mode='binary')

网络构建

直接加载ResNet50模型,选取卷积层的权重参数,然后在卷积层的后面接上自己的全连接层或者其他层,然后根据自己的需求进行训练,可以全部训练,也可以冻结其中某些层进行训练,这里就冻结了全部卷积层,只训练自己的GAP层,关于预训练模型的训练问题可以参考其他资料,我们选择训练哪些层是根据我们的数据需求来定的,这里就不细说了,代码如下:

from tensorflow.keras.models import *
from tensorflow.keras.layers import *
from tensorflow.keras.applications import *
#这里加载ResNet50预训练模型,并且不要全连接层,只选取卷积层的权重参数为自己所用
conv_base = ResNet50(weights='imagenet', include_top=False, input_shape=(224, 224, 3))
model = Sequential()
model.add(conv_base)
#model.add(layers.Flatten())	#这里可以接自己的全连接层,我接的是GAP层,可能效果要好一点点
model.add(layers.GlobalAveragePooling2D())
#这里也可以添加Dropout层对模型训练神经元进行控制,防止过拟合
model.add(layers.Dense(1, activation='sigmoid'))
conv_base.trainable = False	#冻结预训练模型的全部层
model.compile(loss='binary_crossentropy', optimizer=Adam(lr=0.001), metrics=['acc'])

猫狗识别代码 tensorflow resnet猫狗识别_神经网络


可以看到,模型总共的参数是两千三百多万个,而冻结之后我们只需要训练2049个参数,所以是相当省时间了,这就是预训练模型的好处,有强大的功能,也节省了时间。

模型训练

训练和前面的CNN是一样的,但是要慢很多,毕竟CNN只构建了两层卷积,一共三层,并且总共的参数也少很多,所以花时间很少。代码如下:

model.fit_generator(
      train_generator,
      steps_per_epoch=train_generator.samples//batch_size,
      epochs=6,
      validation_data=validation_generator,
      validation_steps=validation_generator.samples//batch_size)
model.save('Resnet50.h5')

模型训练过程如下(才6个epoch我电脑跑了几个小时,太慢了,要换个电脑了),可以看到预训练模型的效果非常好,验证集准确率可以达到97%左右,比前面的CNN效果好太多了,其实也可以尝试Xception,InceptionV3等模型,效果可以达到**98%-99%**左右,所以预训练模型的强大之处就体现得淋漓尽致,特别是在NLP和CV领域

猫狗识别代码 tensorflow resnet猫狗识别_神经网络_02

写在最后

预训练模型的效果是非常好的,但是要熟练运用还是要花很多时间去研究。本人才疏学浅,如果有理解不到位或者错误的地方请指正!

完整代码详见:https://github.com/CquptDJ/CquptDJ