![77e1c32a0b3b84909c69b31d99d467ac.png](https://i-blog.csdnimg.cn/blog_migrate/39af698e11be4f7a7cdd0a2e3ad3ec3f.png)
最近搞毕业论文,想直接在pretrain的模型上进行finetune,使用的框架是tensorflow和keras。所以搜索了下,发现keras的finetune方法很简单(后面简单介绍),然而tensorflow的官网也是看得我乱糟糟,google出来的方法也没有合适的,一是找不到model_weights,二是没有说明后续添加和训练新层的方法。这里自己折腾了一天,含泪总结下,留下个读书笔记,也希望能帮助到有同样需求的人。
------------------------------------------------华丽分割线--------------------------------------------------------
预训练权重的作用:
- 预测
- 特征提取
- 微调
Finetune过程:
- 构建图结构,截取目标张量,添加新层
- 加载目标张量权重
- 训练新层
- 全局微调
1. Keras finetune
Keras的applications模块中就提供了带有预训练权重的深度学习模型。
该模块会根据参数设置,自动检查本地的~/.keras/models/目录下是否含有所需要的权重,没有时会自动下载,在notebook上下载会占用notebook线程资源,不太方便,因此也可以手动wget。
keras应用模块applications,以MobileNet为例说明:
#-----------------------------------构建模型------------------------------------
获取各层名称的方法:
![eb4b4a1aaf27aa8090e569d22197cc56.png](https://i-blog.csdnimg.cn/blog_migrate/559cb42c3fd152831c7031ce3dbc2497.jpeg)
2. Tensorflow finetune
tensorflow的finetune方法有3种:
- 利用tf-slim中构建好的网络结构和权重,手动调整
- 利用tf-slim提供的train_image_classifier.py脚本自动化构建,具体方法这里
- 利用tf.keras,过程与keras相同
这里主要介绍上面的第一种方法,注意事项:
- tensorflow/models在1.0版本后从tf主框架移除,需要手动下载,位置在这里tensorflow/models,可以使用git clone下载到本地目录下,使用时使用下面命令临时添加到python搜索路径里
import
- tf-slim的预训练网络的checkpoint文件在tensorflow/models/research/slim里,常见网络预训练权重
- mobilenet预训练网络的checkpoint文件在slim/nets/mobilenet里面列举得更具体,Mobilenet权重
2.1 模型构建方法
tensorflow有3种方法,从checkpoint文件中恢复模型结构和权重,这里列出的模型恢复后都可以直接进行前向推导计算,进行预测分析。
1) 直接加载图结构,再加载权重
# import_meta_graph可以直接从meta文件中加载图结构
2)先构建图结构,再加载权重
# 临时添加slim到python搜索路径
输出计算图结构内的节点名称,张量名称后面要有:0之类的数字,表示某个计算节点的第一个输出:
![b3a23666f15f7c3503ba329294348673.png](https://i-blog.csdnimg.cn/blog_migrate/00140771ad4077428e3d0de2c903fe41.jpeg)
3) frozen inference
在测试或离线预测时,仅需要神经网络前向推导过程的计算逻辑,而不需要变量初始化、模型保存等辅助节点信息,并且不需要Saver()函数一样将变量和计算图结构分开储存。pb文件将变量取值和计算图整个结构统一放在一个文件中,通过convert_variable_to_constants将变量及取值转化为常量保存,在模型测试的时候,输入只需要经过前向传播至输出层就可以。
# 读取保存的pb文件,并解析成对应的GraphDef Protocol Buffer
2.2 Finetune过程
- 1) 构建图结构,截取目标张量,添加新层
- 2) 加载目标张量权重
- 3) 训练新层
- 4) 全局微调
1) 构建图结构,截取目标张量,添加新层
这个步骤中的图结构,是通过“先构建图结构,再加载权重”方法得到的mobilenet计算图结构。
tf
计算图结构:
![bb28d45ab7e5a22501601554669e492f.png](https://i-blog.csdnimg.cn/blog_migrate/e2dbcffa443c90dfec8741d31b73ec41.jpeg)
红色框内的是Mobilenet网络结构,由上至下的第二个紫色节点为"MobilenetV2/expanded_conv_14/output"节点,可以看出直接与finetune_layers相接。
2) 加载目标权重,训练新层
# one-hot编码
权重初始化注意事项:
1.先利用全局初始化tf.global_variables_initializer(),再利用saver.restore顺序不能错,否则加载的权重会被重新初始化 。
sess
2.先利用saver.restore从模型中加载权重,再利用tf.variable_initializaer()初始化指定的var_list,顺序可以调换.
saver
3.前两种方法会对无用的节点也进行变量初始化,并且需要提前进行saver.restore操作,也就是说需要两次save.restore操作,才能保证finetune过程不会报错。现在可以通过筛选出需要从文件中加载权重的所有变量组成var_list,然后定义saver=tf.train.Saver(var_list),选择性的加载变量.
上面代码使用了第三种方法,以上3种初始化方法的差异可以仔细体会下。可以仔细看看下面的截图。
![85da9b1e5e3c44222b111469bd7e63e7.png](https://i-blog.csdnimg.cn/blog_migrate/322a224e6c487974ae0bfa1622c6b10b.jpeg)
--------------------------------------------20180817更新---------------------------------------------
1) 添加了关于变量初始化3种方法的思考
2) 调整下文章逻辑,2.1模型构建主要用于前向传播推导,2.2阐述了完整的finetune过程
欢迎转载~请注明出处~谢谢~