在笔者之前的博客中,有提到对tensorflow编程的一些总结。里面提到,tensorflow框架是一个在很大程度上支持用户自己定制程序的框架,在定制自己的训练代码时,我们往往只需要关注网络的前向传播,而网络的反向传播过程对于工程师们而言是透明的,这很大程度上减轻了深度学习工程师们的代码负担。可是,众所周知,在深度神经网络进行反传时,参数的更新是和参数各自的梯度相关的。因此,在深度神经网络进行反传时,对参数的梯度进行反转是能够影响深度神经网络的前传结果的。在很多科研工程中,对于梯度的反转也是客观需要的。
那么,在tensorflow框架下,如何去对参数的梯度进行反转呢?其实,tensorflow官方已经提供了一个接口。
这个函数可以使我们对梯度扩充任意倍数,而将梯度变为-1倍就可以完成反转梯度的功能。如上图所示,tf.contrib.training.multiply_gradients接收两个参数:
(1) grads_and_vars,是一个二元组列表,即列表的元素是一个二元组,这个元组就是(梯度,参数)对。
(2) gradient_multipliers,是一个“映射”,从参数到对该参数对应的梯度的乘数因子的映射。
那么,第一个参数怎么得到呢?其实笔者在这篇博客中已经埋下了伏笔,笔者提到在设置训练器进行网络的反传时,更新参数应该按照两步走,第一步compute_gradients,第二步apply_gradients。而这个compute_gradients返回的就是(梯度,参数)元组列表。
对于第二个参数,应该利用怎样的数据结构去构造一个映射呢?答案是利用字典,将需要反转梯度的参数名设为键,而值就置为-1即可。
总而言之,反转梯度的过程分成三步走:
利用compute_gradients求出(梯度,参数)元组列表->利用字典构造参数与梯度变换因子(-1)的映射并使用multiply_gradients反转梯度->使用apply_gradients结合反转后的梯度更新相应的参数
核心代码如下所示:
#Please set your train optimizer, compute loss and get variable list first.
grads_and_vars = train_optim.compute_gradients(loss, var_list=vars_to_reverse_gradients)
D = {}
for grad, var in grads_and_vars:
key = var
D[key] = -1.0
reverse_grads_and_vars = tf.contrib.training.multiply_gradients(grads_and_vars, D)
train_op = train_optim.apply_gradients(reverse_grads_and_vars)
到这里,就完成了对相应参数的梯度的反转了。
如果各位读者朋友们觉得笔者的博客对自己的科研或工程有帮助的话,欢迎订阅和分享哦!
欢迎阅读笔者后续博客,各位读者朋友的支持与鼓励是我最大的动力!
written by jiong
非学无以广才,非志无以成学