tensorflow冻结变量方法(tensorflow freeze variable)
最近由于项目需要,要对tensorflow构造的模型中部分变量冻结,然后继续训练,因此研究了一下tf中冻结变量的方法,目前找到三种,各有优缺点,记录如下:
1.名词解释
冻结变量,指的是在训练模型时,对某些可训练变量不更新,即仅参与前向loss计算,不参与后向传播,一般用于模型的finetuning等场景。例如:我们在其他数据上训练了一个resnet152模型,然后希望在目前数据上做finetuning,一般来讲,网络的前几层卷积是用来提取底层图像特征的,因此可以对前3个卷积层进行冻结,不改变其weight和bias的数值。
2.方法介绍
目前我找到了三种tf冻结变量的方法,各有优缺点,具体如下:
2.1 trainable=False
一切tf.Variable或tf.Variable的子类,在创建时,都有一个trainable参数,在tf官方文档(https://www.tensorflow.org/api_docs/python/tf/Variable)中有对这个参数的定义,

意思是,如果trainable设置为True,就会把变量添加到GraphKeys.TRAINABLE_VARIABLES集合中,如果是False,则不添加。而在计算梯度进行后向传播时,我们一般会使用一个optimizer,然后调用该optimizer的compute_gradients方法。在compute_gradients中,第二个参数var_list如果不传入,则默认为GraphKeys.TRAINABLE_VARIABLES。

总结下,trainable=False冻结变量的逻辑:trainable=False → 该变量不会放入GraphKeys.TRAINABLE_VARIABLES → 调用optimizer.compute_gradients方法时默认变量列表为GraphKeys.TRAINABLE_VARIABLES,该变量不在其中,因此不参与后向传播,值不进行更新,达到冻结变量效果。
优点:操作简单,只要在你创建变量时设置trainable=False即可
缺点:不知道大家发现没有,我上面的总结中,optimizer.compute_gradients方法默认变量列表是GraphKeys.TRAINABLE_VARIABLES,这句话还意味着,如果我不想用默认变量列表,而使用自定义变量列表,那么即使设置了trainable=False,只要把该变量加入到自定义变量列表中,变量还是会参与后向传播的,值也会更新。另外,tf.layers、tf.contrib.rnn等一些高度封装的API是不支持这个参数的,没法用该方法冻结变量。最后,如果我们在使用Saver保存ckpt时,一般调动tf.trainable_variables()方法只保存可训练参数,这时返回的变量列表,也有上面的问题,即设置了trainable=False的变量不会在里面。
2.2 tf.stop_gradient()
我们还可以通过在某个变量外面包裹一层tf.stop_gradient()函数来达到冻结变量的目的。例如我们想冻结w1,可以写成这样:
w1 = tf.stop_gradient(w1)
在后向传播时,w1的值就不会更新。下面说下优缺点。
优点:操作简单,针对想冻结的变量,添加上面这一行即可,而且相比于上一个方法,设置了tf.stop_gradient()的变量,不会从GraphKeys.TRAINABLE_VARIABLES集合中去除,因此不会影响梯度计算和保存模型
缺点:和上一个方法类似,tf.stop_gradient()的输入是Tensor,tf.layers、tf.contrib.rnn等一些高度封装的API的返回值没法作为参数传入,即不能用该方法冻结
2.3 optimizer.compute_gradients(loss,var_list=no_freeze_vars)
optimizer.compute_gradients在2.1中提到过,其实我们只需要在计算梯度时,指定变量列表,把希望冻结的变量去除,即可完成冻结变量。但这么做有一个前提,我们必须知道所有可训练变量的名字,并根据一些规则去除变量。获取所有可训练变量名字调用tf.trainable_variables()方法即可,但去除变量则需要我们在构建网络的时候,合理利用tf.variable_scope,对不同变量做区分。例如,我们如果想把可训练变量中所有卷积层变量冻结,可以这么写:
trainable_vars = tf.trainable_variables()
freeze_conv_var_list = [t for t in trainable_vars if not t.name.startswith(u'conv')]
grads = opt.compute_gradients(loss, var_list=freeze_conv_var_list)
下面总结下优缺点,
优点:没有2.1和2.2的缺点,是一种适用范围更加广泛的方法
缺点:相对2.1,2.2使用起来比较复杂,需要自己去除冻结变量,并且variable_scope不能随意改动,因为可能使去除变量的过滤操作无效化。例如:如果把原来'cnn' scope改为'vgg',那么上面的代码就无效了
3.总结
tf对于一些常用操作,往往会提供多种方法,但每种方法一般都是有区别的,并且操作原理和后面的逻辑也会有不同,要谨慎使用
tensorflow冻结变量方法(tensorflow freeze variable)的更多相关文章
- Tensorflow模型变量保存
Tensorflow:模型变量保存 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考文献Tensorflow实战Google深度学习框架 实验平台: Tensorflow1.4.0 pyt ...
- 111、TensorFlow 初始化变量
# 显式的初始化时非常有用的 # 因为它可以让你不用重复进行繁重的初始化工作 # 当你重新从checkpoint文件中加载一个模型的时候 # 当随机初始化变量被配置在分布式的配置文件中 # 为了在开始 ...
- 05 Tensorflow中变量的初始化
打开Python Shell,输入import tensorflow as tf,然后可以执行以下代码. 1.创建一个2*3的矩阵,并让所有元素的值为0.(类型为tf.float) a = tf.ze ...
- TF:Tensorflow定义变量+常量,实现输出计数功能—Jason niu
#TF:Tensorflow定义变量+常量,实现输出计数功能 import tensorflow as tf state = tf.Variable(0, name='Parameter_name_c ...
- Java获取系统环境变量(System Environment Variable)和系统属性(System Properties)以及启动参数的方法
系统环境变量(System Environment Variable): 在Linux下使用export $ENV=123指定的值.获取的方式如下: Map<String,String> ...
- [tensorflow in a nutshell] tensorflow简明教程 (第一部分)
原文链接: https://medium.com/@camrongodbout/tensorflow-in-a-nutshell-part-one-basics-3f4403709c9d#.31jv5 ...
- tensorflow学习笔记——使用TensorFlow操作MNIST数据(2)
tensorflow学习笔记——使用TensorFlow操作MNIST数据(1) 一:神经网络知识点整理 1.1,多层:使用多层权重,例如多层全连接方式 以下定义了三个隐藏层的全连接方式的神经网络样例 ...
- tensorflow学习笔记——使用TensorFlow操作MNIST数据(1)
续集请点击我:tensorflow学习笔记——使用TensorFlow操作MNIST数据(2) 本节开始学习使用tensorflow教程,当然从最简单的MNIST开始.这怎么说呢,就好比编程入门有He ...
- Tensorflow r1.12及tensorflow serving r1.12 GPU版本编译遇到的问题
1.git clone tensorflow serving 及tensorflow代码 2. ERROR: /root/.cache/bazel/_bazel_root/f71d782da17fd8 ...
随机推荐
- 通过xml处理sql语句时对小于号与大于号的处理转换
以上方法,很容易使用,直接ss < #{ss} 法二 <![CDATA[>=]]>表示大于等于 变量<![CDATA[ < ]]>#{变量}表示 ...
- 删除office拥有多个都需要激活的授权信息
首先确认office目录下存在“ospp.vbs”文件,可以搜索确认文件路径. 我的是在C:\Program Files\Microsoft Office\Office16 然后以管理员身份打开cm ...
- word2vec skip-gram系列2
Word2Vec的CBOW模型和Skip-gram模型 故事先从NNLM模型说起,网络结构图如下图所示,接下来先具体阐述下这个网络, 输入是个one-hot representation的向量.比如你 ...
- js,css文件更新之后,浏览器端还有缓存,久久不能消除
解决方案,每次更新之后修改下配置信息 /// <summary> /// VersionInfo 版本信息 /// </summary> public static class ...
- Delphi 获取当前鼠标下的控件内容
Delphi 获取当前鼠标下的控件内容 主要函数: GetCursorPos://获取鼠标的位置 WindowFromPoint://获取制定point下的handle GetClassName:// ...
- 用DirectX实现多视图渲染
什么是多视图 一般的3D程序都只有一个视图,对应整个窗口的客户区.多视图就是在一个窗口中放置多个视图,以便从不同的角度观察模型或者场景.很多图形软件都有这个功能,比如大家熟知的3DMax就有四个视图, ...
- Java全栈程序员之08:MAVEN+JAVA配置
从Spring3.0开始,Spring支持以Java配置的方式来代替XML配置.这一点说起来其实有点可笑,XML配置的方式最初被创建出来就是为了让配置与程序员无关.可是最终我们发现,绝大多数的那些配置 ...
- IIS安装、配置 发布网站 报错解决方案
错误一: HTTP 错误 500.19- Internal Server Error法请求该页面配置,因为页面的相关配置数据无效#### HTTP 错误 500.21 - Internal S ...
- 为RecyclerView打造通用Adapter
##RecycleView简单介绍 RecyclerView控件和ListView的原理有非常多相似的地方,都是维护少量的View来进行显示大量的数据.只是RecyclerView控件比ListVie ...
- 硬盘SMART检测参数详解[转]
一.SMART概述 要说Linux用户最不愿意看到的事情,莫过于在毫无警告的情况下发现硬盘崩溃了.诸如RAID的备份和存储技术可以在任何时候帮用户恢复数据,但为预防硬件崩溃造成数据丢失所 ...