个人博客:http://www.chenjianqu.com/

原文链接:http://www.chenjianqu.com/show-53.html

迁移学习

迁移学习(Transfer Learning)是一种机器学习方法,就是把为任务 A 开发的模型作为初始点,重新使用在为任务 B 开发模型的过程中。迁移学习是通过从已学习的相关任务中转移知识来改进学习的新任务,虽然大多数机器学习算法都是为了解决单个任务而设计的,但是促进迁移学习的算法的开发是机器学习社区持续关注的话题。 迁移学习对人类来说很常见,例如,我们可能会发现学习识别苹果可能有助于识别梨,或者学习弹奏电子琴可能有助于学习钢琴。

找到目标问题的相似性,迁移学习任务就是从相似性出发,将旧领域(domain)学习过的模型应用在新领域上。

迁移学习的需求:

* 大数据与少标注的矛盾:虽然有大量的数据,但往往都是没有标注的,无法训练机器学习模型。人工进行数据标定太耗时。
* 大数据与弱计算的矛盾:普通人无法拥有庞大的数据量与计算资源。因此需要借助于模型的迁移。
* 普适化模型与个性化需求的矛盾:即使是在同一个任务上,一个模型也往往难以满足每个人的个性化需求,比如特定的隐私设置。这就需要在不同人之间做模型的适配。
* 特定应用(如冷启动)的需求。

数据集

牛津大学的Oxford Visual Geometry Group(VGG),该小组隶属于1985年成立的Robotics Research Group,该Group研究范围包括了机器学习到移动机器人。就是他们设计了VGG网络,他们的网站上有各种各样的数据集,本文使用的是vgg网站上的宠物数据集。

数据集的统计如下:

Inception v3模型

Inception 网络是 CNN 分类器发展史上一个重要的里程碑。在 Inception 出现之前,大部分流行 CNN 仅仅是把卷积层堆叠得越来越多,使网络越来越深,以此希望能够得到更好的性能。例如第一个得到广泛关注的 AlexNet,它本质上就是扩展 LeNet 的深度,并应用一些 ReLU、Dropout 等技巧。AlexNet 有 5 个卷积层和 3 个最大池化层,它可分为上下两个完全相同的分支,这两个分支在第三个卷积层和全连接层上可以相互交换信息。与 Inception 同年提出的优秀网络还有 VGG-Net,它相比于 AlexNet 有更小的卷积核和更深的层级。

VGG-Net 的泛化性能非常好,常用于图像特征的抽取目标检测候选框生成等。VGG 最大的问题就在于参数数量,VGG-19 基本上是参数量最多的卷积网络架构。这一问题也是第一次提出 Inception 结构的 GoogLeNet 所重点关注的,它没有如同 VGG-Net 那样大量使用全连接网络,因此参数量非常小。

GoogLeNet 最大的特点就是使用了 Inception 模块,它的目的是设计一种具有优良局部拓扑结构的网络,即对输入图像并行地执行多个卷积运算或池化操作,并将所有输出结果拼接为一个非常深的特征图。因为 1*1、3*3 或 5*5 等不同的卷积运算与池化操作可以获得输入图像的不同信息,并行处理这些运算并结合所有结果将获得更好的图像表征。

另一方面,Inception 网络是复杂的(需要大量工程工作)。它使用大量 trick 来提升性能,包括速度和准确率两方面。它的不断进化带来了多种 Inception 网络版本的出现。常见的版本有:

Inception v1
Inception v2
Inception v3
Inception v4
Inception-ResNet

最原始的inception模块如下:

inception v3是在ImageNet上面训练的分类模型,因此可迁移到宠物分类任务。

测试Inception v3模型

首先把inception模型下载、解压并加载到默认计算图,然后保存图结构用于tensorboard查看。代码如下:

import tensorflow as tf
import os
import tarfile
import requests# inception模型下载地址
inception_pretrain_model_url = 'http://download.tensorflow.org/models/image/imagenet/inception-2015-12-05.tgz'
# 模型存放地址
inception_pretrain_model_dir = "inception_model"
if not os.path.exists(inception_pretrain_model_dir):os.makedirs(inception_pretrain_model_dir)# 获取文件名,以及文件路径
filename = inception_pretrain_model_url.split('/')[-1]
filepath = os.path.join(inception_pretrain_model_dir, filename)
# 下载模型
if not os.path.exists(filepath):print("download: ", filename)r = requests.get(inception_pretrain_model_url, stream=True)with open(filepath, 'wb') as f:for chunk in r.iter_content(chunk_size=1024):if chunk:f.write(chunk)
print("finish: ", filename)# 解压文件
tarfile.open(filepath, 'r:gz').extractall(inception_pretrain_model_dir)
# 模型结构存放文件
log_dir = 'inception_log'
if not os.path.exists(log_dir):os.makedirs(log_dir)#读取模型
# classify_image_graph_def.pb为google训练好的模型
inception_graph_def_file = os.path.join(inception_pretrain_model_dir, 'classify_image_graph_def.pb')
with tf.Session() as sess:# 创建一个图来存放google训练好的模型with tf.gfile.FastGFile(inception_graph_def_file, 'rb') as f:graph_def = tf.GraphDef()graph_def.ParseFromString(f.read())tf.import_graph_def(graph_def, name='')# 保存图的结构writer = tf.summary.FileWriter(log_dir, sess.graph)writer.close()

在inception_log文件夹下打开tensorboard,可以看到inception的网络结构,如下:

inception模型在image net上训练的,那个是包含一千个分类的数据集。下载的模型压缩包解压也得到一些其它的文件,其中包含imagenet_2012_challenge_label_map_proto.pbtxt和imagenet_synset_to_human_label_map.txt这两个文件。这两个文件是模型label和图片类型id,字符串之间的映射,读取并得到字典的代码如下:

#读取inception的字典文件id_to_class={}
id_to_str={}
class_to_str={}with open('D:\Jupyter\TensorflowLearning\inception_model\imagenet_2012_challenge_label_map_proto.pbtxt','r') as f:lines=f.readlines()cls=0for line in lines:line=line.strip()if('target_class:' in line):cls=line[14:]if('target_class_string:' in line):id_to_class[line[-10:-1]]=cls
with open('D:\Jupyter\TensorflowLearning\inception_model\imagenet_synset_to_human_label_map.txt','r') as f:lines=f.readlines()for line in lines:line=line.strip()id_=line[:9]str_=line[10:]id_to_str[id_]=str_for k in id_to_class.keys():class_to_str[id_to_class[k]]=id_to_str[k]print(len(id_to_class))
print(len(id_to_str))
print(len(class_to_str)) #我们想要的

接下来我们测试一下inception,首先读取加载模型到计算图:

import tensorflow as tf#创建一个图存放inception模型
with tf.gfile.FastGFile('inception_model/classify_image_graph_def.pb', 'rb') as f:graph_def = tf.GraphDef()graph_def.ParseFromString(f.read())tf.import_graph_def(graph_def, name='')

接着准备一些狗的图片,丢进模型进行测试,需要说明的是,inception v3模型自带了jpeg图片预处理的节点,因此可以直接把图片丢进去。代码如下:

import os
import numpy as np
import re
from PIL import Image
import matplotlib.pyplot as plt#使用模型
with tf.Session() as sess:softmax_tensor = sess.graph.get_tensor_by_name('softmax:0')# 遍历目录for root, dirs, files in os.walk('images/'):for file in files:image_data = tf.gfile.FastGFile(os.path.join(root, file), 'rb').read() #读入图片predictions = sess.run(softmax_tensor, {'DecodeJpeg/contents:0': image_data}) #喂入网络图片解码节点predictions = np.squeeze(predictions) #从数组的形状中删除单维度条目,即把shape中为1的维度去掉image_path = os.path.join(root, file)print(image_path)img = Image.open(image_path) #打开图片plt.imshow(img)#显示出来plt.axis('off')plt.show()#排序,然后倒序,最后取出最大的5个top_k = predictions.argsort()[-5:][::-1]for node_id in top_k:human_string = class_to_str[str(node_id)]score = predictions[node_id]print('%s (score=%.5f)' % (human_string, score))print()

测试结果如下:

微调模型

谷歌提供了重新训练Inception v3模型的代码,得注意的是,github上面官方给的retrain.py需要翻墙下载inception模型,因此最好使用更早版本的retrain.py使用本地下载好的模型。这里有一个可用的retrain.py。

首先把前面提到的宠物数据集下载并解压。inception模型使用的文件名不能大小写混着,因此需要先把所有的图片名变小写,把'_'换成'vv'字母,然后根据文件名每个类归为一个文件夹。处理代码如下:

import os,shutilbase_dir='D:/CV/datasets/pets/images'#对文件名预处理
for fileName in os.listdir(base_dir):#列出文件if(fileName[-3:]=='jpg'):#判断为jpgnewName=fileName.lower()#变小写newName=newName.replace('_','vv')#替换vvsrc=os.path.join(base_dir,fileName)dst=os.path.join(base_dir,newName)os.rename(src, dst) for fileName in os.listdir(base_dir):#列出文件if(fileName[-3:]=='jpg'):#判断为jpgnameSplitList=fileName.split('vv')nameSplitList.pop()clsName='vv'.join(nameSplitList) #根据文件名将文件移到对应文件夹clsDirName=os.path.join(base_dir,clsName)if(not os.path.exists(clsDirName)):os.mkdir(clsDirName)fliePath=os.path.join(base_dir,fileName)shutil.move(fliePath,clsDirName)
print('done')

接下来就可以调用retrain.py重新训练下载了的inception模型了。我写了一个批处理文件如下:

E:/Anaconda/envs/ai/python retrain.py ^
--bottleneck_dir bottleneck_dir ^
--how_many_training_steps 1000 ^
--model_dir D:/Jupyter/TensorflowLearning/inception_model ^
--output_graph output_graph.pb ^
--output_labels output_labels.txt ^
--image_dir D:/CV/datasets/pets
pause

代码解释如下:

执行retrain.py
E:/Anaconda/envs/ai/python retrain.py ^
存放bottleneck输出的高级特征的路径
--bottleneck_dir bottleneck_dir ^
训练步数
--how_many_training_steps 1000 ^
未解压的模型文件路径
--model_dir D:/Jupyter/TensorflowLearning/inception_model ^
输出训练好的模型路径
--output_graph output_graph.pb ^
输出的标签路径
--output_labels output_labels.txt ^
训练集路径
--image_dir D:/CV/datasets/pets/images
pause

执行之后便开始训练。

首先代码会检查数据集目录下有哪些类别:

然后每个训练样本生成一个bottleneck输出的特征值,并保存至txt文件:

接着使用这些特征值对输出层进行训练:

最后得到测试精度为94%,还算不错。

训练过程中会在本磁盘根目录下生成一个tmp文件夹,里面包含了训练过程中的参数,使用tensorboard查看如下:

新的模型架构,其中就是在原来inception的bottleneck位置新加了一个输出层:

测试迁移模型

我找了猫狗分类的数据集来测试了一下,代码如下:

dict_cls2str={}
with open('output_labels.txt','r') as f:lines=f.readlines()for i,line in enumerate(lines):line=line.strip()line=line.replace('vv',' ')dict_cls2str[i]=line
print(dict_cls2str)

读取并测试模型:

%matplotlib inline
import tensorflow as tf
import numpy as np
import cv2
import matplotlib.pyplot as plt
import os
from PIL import Imagetest_dir='D:/CV/datasets/pets/test'
#读入模型
with tf.gfile.FastGFile('output_graph.pb','rb') as f:graph_def=tf.GraphDef()graph_def.ParseFromString(f.read())tf.import_graph_def(graph_def,name='')with tf.Session() as sess:#获得我们训练的输出张量softmax_tensor=sess.graph.get_tensor_by_name('final_result:0')for fileName in os.listdir(test_dir):pic_path=os.path.join(test_dir,fileName)#载入图片img=tf.gfile.FastGFile(pic_path,'rb').read()#将图片传入计算图pred=sess.run(softmax_tensor,{'DecodeJpeg/contents:0':img})pred=np.squeeze(pred)print(pic_path)#读取图片img=Image.open(pic_path)#显示图片plt.imshow(img)plt.axis('off')plt.show()#排序,然后倒序top_k=pred.argsort()[::-1]for cls in top_k[:5]:name=dict_cls2str[cls]print('%s %f'%(name,pred[cls]))

测试的效果如下:

可以说还是非常不错的。

参考文献

[1]mantch.迁移学习(Transfer),面试看这些就够了!(附代码).http://blog.itpub.net/69942346/viewspace-2654034/  .2019-08-18

[2]机器之心.一文概览Inception家族的「奋斗史」.http://baijiahao.baidu.com/s?id=1601882944953788623&wfr=spider&for=pc  .18-05-30

[3]Christian Szegedy,Wei Liu,etc.Going deeper with convolutions

迁移学习-使用预训练的Inception v3进行宠物分类相关推荐

  1. 迁移学习实战 | 快速训练残差网络 ResNet-101,完成图像分类与预测,精度高达 98%!...

    作者 | AI 菌 出品 | CSDN博客 头图 | CSDN付费下载自视觉中国 前言 笔者在实现ResNet的过程中,由于电脑性能原因,不得不选择层数较少的ResNet-18进行训练.但是很快发现, ...

  2. 直播预告 | AAAI 2022论文解读:基于对比学习的预训练语言模型剪枝压缩

    「AI Drive」是由 PaperWeekly 和 biendata 共同发起的学术直播间,旨在帮助更多的青年学者宣传其最新科研成果.我们一直认为,单向地输出知识并不是一个最好的方式,而有效地反馈和 ...

  3. 无需在数据集上学习和预训练,这种图像修复新方法效果惊人 | 论文

    林鳞 编译自 Github 量子位 出品 | 公众号 QbitAI Reddit上又炸了,原因是一个无需在数据集上学习和预训练就可以超分辨率.修补和去噪的方法:Deep image prior. 帖子 ...

  4. 【神经网络】(7) 迁移学习(CNN-MobileNetV2),案例:乳腺癌二分类

    各位同学好,今天和大家分享一下Tensorflow2.0中如何使用迁移学习的方法构造神经网络.需要数据集的在评论区留个言. 1. 迁移学习 官方文档:Module: tf.keras.applicat ...

  5. AAAI 2022 | 北大 阿里达摩院:基于对比学习的预训练语言模型剪枝压缩

    近年来,预训练语言模型迅速发展,模型参数量也不断增加.为了提高模型效率,各种各样的模型压缩方法被提出,其中就包括模型剪枝. 然而,现有的模型剪枝方法大多只聚焦于保留任务相关知识,而忽略了任务无关的通用 ...

  6. 【Tensorflow】深度学习实战05——Tensorflow实现Inception V3

    [fishing-pan:https://blog.csdn.net/u013921430转载请注明出处] 前言 前些日子在忙其他的事情,一直没有更新自己学习神经网络的博客,就在端午这天更吧!也祝大家 ...

  7. 【深度学习】预训练的卷积模型比Transformer更好?

    引言 这篇文章就是当下很火的用预训练CNN刷爆Transformer的文章,LeCun对这篇文章做出了很有深意的评论:"Hmmm".本文在预训练微调范式下对基于卷积的Seq2Seq ...

  8. 【深度学习】预训练语言模型-BERT

    1.BERT简介         BERT是一种预训练语言模型(pre-trained language model, PLM),其全称是Bidirectional Encoder Represent ...

  9. pytorch深度学习实战——预训练网络

    来源:<Pytorch深度学习实战>,2.1,一个识别图像主体的预训练网络 from torchvision import models from torchvision import t ...

最新文章

  1. 1977中文版_历年星云、雨果获奖长篇中文版汇总
  2. zBrow压力测试图
  3. wireshark C插件开发
  4. java:不同数据类型的转换规则
  5. fopen,fopen_s,fclose, _fcloseall函数用法
  6. 对于嵌入式交叉编译总结
  7. php html标签自定义属性,详解H5的自定义属性data-*
  8. android手机电话铃声设置,安卓手机铃声怎么设置
  9. django序列化器嵌套_Django Rest Framework中用于OneToOne字段的序列化程序中的嵌套关​​系
  10. UGUI字体不清楚——终极探索
  11. Windows下动态库的制作与使用
  12. 玉伯的一道课后题题解(关于 IEEE 754 双精度浮点型精度损失)
  13. CloudFlare Full SSL Strict 报错提示 Error 525 SSL handshake failed
  14. tkmybatis更新无效
  15. java nio wakeup_Java NIO wakeup实现原理
  16. 利用composer安装依赖
  17. 编程中常用的英文单词
  18. 微生物所东秀珠组与北大深圳研究生院余珂组联合招聘启事
  19. 徐州好玩实用的微信小程序
  20. 实验11 虚函数与多态

热门文章

  1. NanoPC-T3 64位裸机编程 —— 启动和运行状态切换
  2. 百度前端学院参考答案:第二十五天到第二十七天 倒数开始 滴答滴 滴答滴(2)...
  3. iOS面试总结(待完善)
  4. 关于@SuppressWarnings(unchecked)注解
  5. CPT:刷爆少样本REC任务!清华刘知远团队提出跨模态预训练Prompt Tuning
  6. 斯坦福大学#深度多任务学习与元学习#视频及讲义下载
  7. EfficientDet 目标检测开源实现
  8. 让目标检测和实例分割互相帮助,地平线实习生论文被AAAI 2020收录
  9. Nature调查再聚焦读博压力:超1/3博士生焦虑抑郁,大学有没有能哭的地方?
  10. 终于我还是没忍住,用Python爬了一波女神