『TensorFlow』迁移学习

彻底版见github:TransforLearninggit

零、迁移学习

将一个领域的已经成熟的知识应用到其余的场景中称为迁移学习。用神经网络的角度来表述,就是一层层网络中每一个节点的权重从一个训练好的网络迁移到一个全新的网络里,而不是从头开始,为每特定的个任务训练一个神经网络。github

假设你已经有了一个能够高精确度分辨猫和狗的深度神经网络,你以后想训练一个可以分别不一样品种的狗的图片模型,你须要作的不是从头训练那些用来分辨直线,锐角的神经网络的前几层,而是利用训练好的网络,提取初级特征,以后只训练最后几层神经元,让其能够分辨狗的品种。节省资源是迁移学习最大意义之一,举图像识别中最多见的例子,训练一个神经网络。来识别不一样的品种的猫,你如果从头开始训练,你须要百万级的带标注数据,海量的显卡资源。而如果使用迁移学习,你可使用Google发布的Inception或VGG16这样成熟的物品分类的网络,只训练最后的softmax层,你只须要几千张图片,使用普通的CPU就能完成,并且模型的准确性不差。api

使用迁徙学习时要注意,原本预训练的神经网络要和当前的任务差距不大,否则迁徙学习的效果会不好。例如若是你要训练一个神经网络来识别肺部X光片中是否包含肿瘤,那么使用VGG16的网络就不如使用一个已训练好的判断脑部是否包含肿瘤的神经网络。后者与当前的任务有类似的场景,不少底层的神经员能够作相同的事,而用来识别平常生活中照片的网络,则难以从X光片中提取有效的特征。数组

另外一种迁移学习的方法是对整个网络进行微调(fine turing),假设你已训练好了识别猫品种的神经网络,你的网络能对50种猫按品种进行分类。接下来你想对网络进行升级,让其可以识别100种猫,这时你不该该只训练网络的最后一层,而应该逐层对网络中每一个节点的权重进行微调。显然,只训练最后几层,是迁移学习最简单的1.0版,而对节点权重进行微调,就是更难的2.0版,经过将其余层的权重固定,只训练一层这样的逐层训练,能够更好的完成上述任务。bash

迁移方式和数据集规模关系

 

1)右下角场景,待训练的数据集较小,已训练的模型和当前任务类似。此时能够只是从新训练已有模型的靠近输出的几层,例如将ImageNet中输出层原来能够判别一万种输出的网络改的只能判别猫的品种,从而利用已有网络来作低层次的特征提取。网络

2)左下角场景,待训练的数据集较小,已训练的模型和当前任务场景差距较大。例如你有的已训练网络能识别出白天高速路上的违章车辆,你须要训练一个能识别出夜间违章车辆的模型,因为无论白天夜晚,交通规则是没有变化的,因此你须要将网络靠近输入的那几层从新训练,等到新的网络可以提取出夜间车辆的基本信息后,就能够借用已有的,在大数据集下训练好的神经网络来识别违章车辆,而不用等夜间违章的车辆的照片积累的足够多以后再从新训练。框架

3)左上角场景,待训练的数据集较大,已有的模型和新模型的数据差别度很高。此时应该作的是从头开始,从新训练。curl

4)右上角场景,待训练的数据集较大,已有模型的训练数据和现有的训练数据相似。此时应该使用原网络的结构微调。函数

1、实验目的

使用google已经训练好的模型,将最后的全链接层修改成咱们本身的全链接层,将原有的1000分类分类器修改成咱们本身的5分类分类器,利用原有模型的特征提取能力实现咱们本身数据对应模型的快速训练。实际中对于一个陌生的数据集,原有模型通过不高的迭代次数便可得到很好的准确率。学习

2、代码实战

实机文件夹以下:

花朵图片数据下载:

curl -O http://download.tensorflow.org/example_images/flower_photos.tgz

已经训练好的Inception-v3的1000分类模型下载:

wget https://storage.googleapis.com/download.tensorflow.org/models/inception_dec_2015.zip

迁移学习代码以及使用指南见github,本次的代码能够将新保存的模型迁移到本身的数据集上,并对本身的数据进行预测。

新添加的测试部分,直接运行TransferLearning_reload.py便可,输出以下,

第二行白字的五个值对应第一行的5个分类的几率。

 

3、问题&建议

1.建议从main函数开始阅读,跳到哪里读到那里;

2.我给的注释很详尽,原书《TensorFlow实战Google深度学习框架》也有更为详尽的注释,因此这里很少说了

 

以前本部分对输入图片的过程进行了分析,当时水平有限,如今看来很幼稚,实际上分析一下图上节点便可了解:

  • InceptionV3接受二进制数据便可自行解码,即接收open().read()的二进制流便可
  • 保存的模型文件Graph包含了InceptionV3和新的classer,可是二者是隔离的,这是因为程序中并没将二者联通,是先把InceptionV3的瓶颈张量feed出来,而后是用这个数组去feed新的classer,可是因为saver、InceptionV三、classer使用的sess是同一个,因此最终二者都保存在了model模型中
相关文章
相关标签/搜索