五种卷积神经网络解决猫狗分类问题(三):V3 预训练-特征提取-分步式

版本描述epochs训练精度验证精度
V1.0简单线性卷积神经网络10099%75%
V2.0添加了数据增强和dropout层10083%83%
V3.0使用预训练-特征提取-分步式10099%90%
V4.0使用预训练-特征提取-合并式10090%90%
V5.0使用预训练-微调模型10099%94%

五种卷积神经网络解决猫狗分类问题(零):总概要
五种卷积神经网络解决猫狗分类问题(一):V1 简单线性网络
五种卷积神经网络解决猫狗分类问题(二):V2 简单线性网络上添加数据增强和dropout层
五种卷积神经网络解决猫狗分类问题(三):V3 预训练-特征提取-分步式
五种卷积神经网络解决猫狗分类问题(四):V4 预训练-特征提取-合并式
五种卷积神经网络解决猫狗分类问题(五):V5 预训练-微调模型

1. 预训练网络

  • 预训练网络是一个保存好的网络,之前已经在大型数据集上训练好。如果这个原始数据足够大且足够通用,那么预训练网络学到的特征的空间层次结构可以有效地作为视觉世界的通用模型,因此这些特征可用于各种不同的计算机视觉问题。比如在ImageNet上训练了一个网络(其类别主要是动物和日常用品),然后将这个训练好的网络应用于某个不相干的任务(比如图像中识别家具)。这种学到的特征在不同问题间的可移植性,是深度学习与许多早期浅层学习方法的重要优势。
  • 本例中,假设有一个在ImageNet数据集(140万张图像,1000个不同的类别)上训练好的大型卷积神经网络。ImageNet中包含许多动物类别,其中包括不同种类的猫和狗,因此可以认为它在猫狗分类上也能有良好的表现

2. 预训练网络之特征提取

  • 图像分类的卷积神经网络包括两部分:首先是一系列池化层和卷积层(称为卷积基)后是两个密集连接层(称为分类器)
    而特征提取是指:只是用原模型的卷积基,自己定义新的密集层
    在这里插入图片描述

  • 为什么仅重复使用卷积基?我们能否也重复使用密集连接分类器?一般来说,应该避免这么做。原因在于卷积基学到的表示可能更加通用,因此更适合重复使用。卷积神经网络的特征图表示通用概念在图像中是否存在,无论面对什么样的计算机视觉问题,这种特征图都可能很有用。但是,分类器学到的表示必然是针对于模型训练的类别,其中仅包含某个类别出现在整张图像中的概率信息。此外,密集连接层的表示不再包含物体在输入图像中的位置信息。密集连接层舍弃了空间的概念,而物体位置信息仍然由卷积特征图所描述。如果物体位置对于问题很重要,那么密集连接层的特征在很大程度上是无用的。

  • 注意:也不是卷积基全部重复使用:
    型中更靠近底部的层提取的是局部的、高度通用的特征图(比如视觉边缘、颜色和纹理),而更靠近顶部的层提取的是更加抽象的概念(比如“猫耳朵”或“狗眼睛”)。°因此,如果你的新数据集与原始模型训练的数据集有很大差异,那么最好只使用模型的前几层来做特征提取,而不是使用整个卷积基。

3. 实现特征提取的方法

  • 特征提取主要是使用原始模型的卷积基+自定义的密集层,在实际中有两种使用方法:
3.1 分步式

描述:将自己的训练集输入到卷积基,得到卷积基的输出,保存为numpy;再将numpy作为输入来训练自己的密集层,最终得到训练好的网络
优点:对于卷积基只进行前向运算,不用训练,大大节省训练代价。而只需要训练密集层
缺点:不能进行数据增强

3.2 合并式

描述:在顶部添加Dense层来扩展卷积基,直接拉通运行
优点:可以使用数据增强
缺点:合并训练即训练整个卷积基和密集层,训练代价高

4.代码实践(基于方法一:分步式)

  • 我们将使用ImageNet,它是一种简单而又广泛使用的卷积神经网络架构。VGG16是一个比较旧性能也不及当前最先进的模型,还复杂,本文使用它主要是因为它的结构和学习进度相似,无需新的概念
  • VGG16等模型内置于Keras中,可以从keras.applications模块中导入,该模块中还包括了(都是基于ImageNet数据集上训练得到的):Xception、Inception V3、ResNet50、VGG16、VGG19、MobileNet等
4.1 导入VGG16预训练的网络模型
from keras.applications import VGG16

conv_base=VGG16(weights='imagenet', #指定模型初始化的权重检查点
               include_top=False, #指定模型最后是否包含密集链接分类器。默认是密集连接器对应于ImageNet的1000个分类
               input_shape=(150,150,3)) #可选参数,若不选则网络能够处理任意形状的输入
conv_base.summary() # 打印网络模型架构             
4.2 定义数据集文件夹路径
import os
import numpy as np
from keras.preprocessing.image import ImageDataGenerator

# 改成你的实际路径
base_dir='../dogs-vs-cats_small/'
train_dir=os.path.join(base_dir,'train')
validation_dir=os.path.join(base_dir,'validation')
test_dir=os.path.join(base_dir,'test')
4.3 定义一个函数来返回卷积基的输出结果
datagen=ImageDataGenerator(rescale=1./255)
batch_size=20


# features先定义了总数据的样本卷积基输出的空间
# 后面将小批次feature赋值给features中对应位置

def extract_features(directory,sample_count):
    features=np.zeros(shape=(sample_count,4,4,512))  # 先定义储存所有图像特征图的数组空间
    labels=np.zeros(shape=(sample_count))            # 2000张图像的标签
    generator=datagen.flow_from_directory(directory,    # 触发一次就返回参数设置的一批(batch_size)数据
                                         target_size=(150,150),
                                          batch_size=batch_size,
                                          class_mode='binary')
    i=0
    #inputs_batch:(20, 150, 150, 3)
    #lables_batch:(20,)
    for inputs_batch,lables_batch in generator:  
        features_batch=conv_base.predict(inputs_batch) #数批量数据的卷积基前向运算,得到输出结果
        features[i*batch_size:(i+1)*batch_size]=features_batch  # 将小批次feature赋值给features中对应位置
        labels[i*batch_size:(i+1)*batch_size]=lables_batch
        i+=1
        if i*batch_size>=sample_count: #如果超出2000,说明数据都生成完了
            break
    return features,labels # 总数据的所有特征和label
    
train_features,train_labels=extract_features(train_dir,2000) # 调用函数
validation_features,validation_lables=extract_features(validation_dir,1000)
test_features,test_lables=extract_features(test_dir,1000)
4.4 密集层
# 先将待输入密集层的数据(也就是卷积基的输出结果)展开
train_features=np.reshape(train_features,(2000,4*4*512))   
validation_features=np.reshape(validation_features,(1000,4*4*512))
test_features=np.reshape(test_features,(1000,4*4*512))

# 定义密集层网络
from keras import models
from keras import layers
from keras import optimizers

model=models.Sequential()
model.add(layers.Dense(256,activation='relu',input_dim=4*4*512))
model.add(layers.Dropout(0.5))
model.add(layers.Dense(1,activation='sigmoid'))

# 网络配置
model.compile(optimizer=optimizers.RMSprop(lr=2e-5),
             loss='binary_crossentropy',
             metrics=['accuracy'])
4.5 开始训练
#训练网络
history=model.fit(train_features,
                  train_labels,
                  epochs=30,
                  batch_size=20,
                  validation_data=(validation_features,validation_lables))
4.6 可视化
import matplotlib.pyplot as plt

dic=history.history
train_acc=dic['accuracy']
val_acc=dic['val_accuracy']
train_loss=dic['loss']
val_loss=dic['val_loss']

epoch=range(1,len(train_acc)+1)

plt.plot(epoch,train_acc,'bo',label='Train acc')
plt.plot(epoch,val_acc,'b',label='validation acc')
plt.title('training and validation accuracy')
plt.legend()  # 给图像加图例
plt.figure()
plt.plot(epoch,train_loss,'bo',label='Training loss')
plt.plot(epoch,val_loss,'b',label='Validation loss')
plt.title('Taining and calidation loss')
plt.legend()
plt.show()
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是一个对称矩阵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值