使用预训练网络(迁移学习)
预训练网络是一个保存好的之前已在大型数据集(大规模图像分类任务)上训练好的卷积神经网络
如果这个原始数据集足够大且足够通用,那么预训练网络学到的特征的空间层次结构可以作为有效的提取视觉世界特征的模型。
即使新问题和新任务与原始任务完全不同学习到的特征在不同问题之间是可移植的,这也是深度学习与浅层学习方法的一个重要优势。它使得深度学习对于小数据问题非常的有效。
Keras内置预训练网络Keras库中包含VGG16、VGG19\ResNet50、Inception v3、Xception等经典的模型架构。
-
ImageNet
-
ImageNet是一个手动标注好类别的图片数据库(为了机器视
觉研究),目前已有22,000个类别。 -
当我们在深度学习和卷积神经网络的背景下听到“ImageNet”一词时,我们可能会提到ImageNet视觉识别比赛,称为ILSVRC。
-
这个图片分类比赛是训练一个模型,能够将输入图片正确分
类到1000个类别中的某个类别。训练集120万,验证集5万,测试集10万。 -
这1,000个图片类别是我们在日常生活中遇到的,例如狗,猫,各种家居物品,车辆类型等等。
-
在图像分类方面,ImageNet比赛准确率已经作为计算机视觉分类算法的基准。自2012年以来,卷积神经网络和深度学习技术主导了这一比赛的排行榜。
-
-
VGG16与VGG19
-
在2014年,VGG模型架构由Simonyan和Zisserman提出,在“极深的大规模图像识别卷积网络”(Very Deep Convolutional Networks for Large Scale Image Recognition)这篇论文中有介绍
-
VGG模型结构简单有效,前几层仅使用3×3卷积核来增加网络深度,通过max pooling(最大池化)依次减少每层的神经元数量,最后三层分别是2个有4096个神经元的全连接层和一个输出softmax层。
-
-
VGG有两个很大的缺点
-
- 网络架构weight数量相当大,很消耗磁盘空间。
-
- 训练非常慢
由于其全连接节点的数量较多,再加上网络比较深,VGG16有533MB+,VGG19有574MB。这使得部署VGG比较耗时。
- 训练非常慢
-
-
微调
-
所谓微调:冻结模型库的底部的卷积层,共同训练新添加的分类器层和顶部部分卷积层。这允许我们“微调”基础模型中的高阶特征表示,以使它们与特定任务更相关。。
-
只有分类器已经训练好了,才能微调卷积基的顶部卷积层。如果有没有这样的话,刚开始的训练误差很大,微调之前这些卷积层学到的表示会被破坏掉
-
-
微调步骤
- 一、在预训练卷积基上添加自定义层
- 二、冻结卷积基所有层
- 三、训练添加的分类层
- 四、解冻卷积基的一部分层
- 五、联合训练解冻的卷积层和添加的自定义层
案例
import tensorflow as tf
from tensorflow import keras
import matplotlib.pyplot as plt
%matplotlib inline
import numpy as np
import glob
import os
gpu_ok = tf.test.is_gpu_available()
print("tf version:", tf.__version__)
print("use GPU", gpu_ok) # 判断是否使用gpu进行训练
# 定义好keras,layers方便后面调用
keras = tf.keras
layers = tf.keras.layers
train_image_path = glob.glob("./dc/maogou/*.jpg")
test_image_path = glob.glob("./dc/maogou_test/*.jpg") # 获取图片数据集
len(train_image_path),len(test_image_path)
train_image_path[995:1005],test_image_path[593:600]
# 定义目标值 如果是猫 = 1 是狗 = 0
train_image_label = [int(p.split("\\")[1].split(".")[0]=="cat") for p in train_image_path]
test_image_label = [int(p.split("\\")[1].split(".")[0]=="cat") for p in test_image_path]
train_image_label[995:1005],test_image_label[593:600]
# 图片加载与预处理
def load_preprosess_image(path,lable):
image = tf.io.read_file(path) # 读取图片路径
image = tf.image.decode_jpeg(image,channels=3) # 对图片进行解码(jpeg格式图片,channels=3 将读入图片统一为三通道)
image = tf.image.resize(image,[256,256])# 对图片进行变形360*360像素(非裁剪)
image = tf.cast(image,tf.float32)