当前位置 博文首页 > tensorflow中的梯度求解及梯度裁剪操作

    tensorflow中的梯度求解及梯度裁剪操作

    作者:orangerfun 时间:2021-08-13 18:47

    1. tensorflow中梯度求解的几种方式

    1.1 tf.gradients

    tf.gradients(
        ys,
        xs,
        grad_ys=None,
        name='gradients',
        colocate_gradients_with_ops=False,
        gate_gradients=False,
        aggregation_method=None,
        stop_gradients=None,
        unconnected_gradients=tf.UnconnectedGradients.NONE
    )

    计算ys关于xs的梯度,tf.gradients返回的结果是一个长度为len(xs)的tensor列表list,例如

    tf.gradients(y, [x1, x2, x3]返回[dy/dx1, dy/dx2, dy/dx3]

    当y与x无关时,即graph无x到y的路径, 则求y关于x的梯度时返回[None];参数stop_gradients指定的变量对当前梯度求解而言, 梯度求解将止于这些变量。

    a = tf.constant(0.)
    b = 2 * a
    g = tf.gradients(a + b, [a, b], stop_gradients=[a, b]) #梯度计算不再追溯a,b之前的变量

    输出:

    In: sess.run(g)

    out:[1.0, 1.0]

    如果不设置stop_gradients参数则反向传播梯度计算将追溯到最开始的值a,输出结果为:

    In : sess.run(g)

    Out: [3.0, 1.0]

    1.2 optimizer.compute_gradients

    compute_gradients(
        loss,
        var_list=None,
        gate_gradients=GATE_OP,
        aggregation_method=None,
        colocate_gradients_with_ops=False,
        grad_loss=None
    )

    optimizer.compute_gradients是tf.gradients的封装,作用相同,但是tfgradients只返回梯度,compute_gradients返回梯度和可导的变量;tf.compute_gradients是optimizer.minimize()的第一步,optimizer.compute_gradients返回一个[(gradient, variable),…]的元组列表,其中gradient是tensor。

    直观上,optimizer.compute_gradients只比tf.gradients多了一个variable输出。

    optimizer = tf.train.GradientDescentOptimizer(learning_rate = 1.0)
    self.train_op = optimizer.minimize(self.cost)
    sess.run([train_op], feed_dict={x:data, y:labels})

    在这个过程中,调用minimize方法的时候,底层进行的工作包括:

    (1) 使用tf.optimizer.compute_gradients计算trainable_variables 集合中所有参数的梯度

    (2) 用optimizer.apply_gradients来更新计算得到的梯度对应的变量

    上面代码等价于下面代码

    optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.1)
    grads_and_vars = optimizer.compute_gradients(loss)
    train_op = optimizer.apply_gradients(grads_and_vars)

    1.3 tf.stop_gradient

    tf.stop_gradient(
        input,
        name=None
    )

    tf.stop_gradient阻止input的变量参与梯度计算,即在梯度计算的过程中屏蔽input之前的graph。

    返回:关于input的梯度

    2. 梯度裁剪

    如果我们希望对梯度进行截断,那么就要自己计算出梯度,然后进行clip,最后应用到变量上,代码如下所示,接下来我们一一介绍其中的主要步骤

    #return a list of trainable variable in you model
    params = tf.trainable_variables()
    
    #create an optimizer
    opt = tf.train.GradientDescentOptimizer(self.learning_rate)
    
    #compute gradients for params
    gradients = tf.gradients(loss, params)
    
    #process gradients
    clipped_gradients, norm = tf.clip_by_global_norm(gradients,max_gradient_norm)
    
    train_op = opt.apply_gradients(zip(clipped_gradients, params)))
    

    2.1 tf.clip_by_global_norm介绍

    tf.clip_by_global_norm(t_list, clip_norm, use_norm=None, name=None)

    t_list 表示梯度张量

    clip_norm是截取的比率

    在应用这个函数之后,t_list[i]的更新公示变为:

    global_norm = sqrt(sum(l2norm(t)**2 for t in t_list))
    t_list[i] = t_list[i] * clip_norm / max(global_norm, clip_norm)

    也就是分为两步:

    (1) 计算所有梯度的平方和global_norm

    (2) 如果梯度平方和 global_norm 超过我们指定的clip_norm,那么就对梯度进行缩放;否则就按照原本的计算结果

    梯度裁剪实例2

    loss = w*x*x
    optimizer = tf.train.GradientDescentOptimizer(0.1)
    grads_and_vars = optimizer.compute_gradients(loss,[w,x])
    grads = tf.gradients(loss,[w,x])
    # 修正梯度
    for i,(gradient,var) in enumerate(grads_and_vars):
        if gradient is not None:
            grads_and_vars[i] = (tf.clip_by_norm(gradient,5),var)
    train_op = optimizer.apply_gradients(grads_and_vars)
    with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        print(sess.run(grads_and_vars))
         # 梯度修正前[(9.0, 2.0), (12.0, 3.0)];梯度修正后 ,[(5.0, 2.0), (5.0, 3.0)]
        print(sess.run(grads))  #[9.0, 12.0],
        print(train_op)

    补充:tensorflow框架中几种计算梯度的方式

    1. tf.gradients

    tf.gradients(
        ys,
        xs,
        grad_ys=None,
        name='gradients',
        colocate_gradients_with_ops=False,
        gate_gradients=False,
        aggregation_method=None,
        stop_gradients=None,
        unconnected_gradients=tf.UnconnectedGradients.NONE
    )

    计算ys关于xs的梯度,tf.gradients返回的结果是一个长度为len(xs)的Tensor列表list,每个张量为sum(dy/dx),即ys关于xs的导数。

    例子:

    tf.gradients(y, [x1, x2, x3]返回[dy/dx1, dy/dx2, dy/dx3]

    当y与x无关时,即graph无x到y的路径, 则求y关于x的梯度时返回[None]

    参数stop_gradients指定的变量对当前梯度求解而言, 梯度求解将止于这些变量。

    实例:

    a = tf.constant(0.)
    b = 2 * a
    g = tf.gradients(a + b, [a, b], stop_gradients=[a, b]) #梯度计算不再追溯a,b之前的变量

    输出:

    In: sess.run(g)

    out:[1.0, 1.0]

    如果不设置stop_gradients参数则反向传播梯度计算将追溯到最开始的值a,输出结果为:

    In : sess.run(g)

    Out: [3.0, 1.0]

    2. optimizer.compute_gradients

    compute_gradients(
        loss,
        var_list=None,
        gate_gradients=GATE_OP,
        aggregation_method=None,
        colocate_gradients_with_ops=False,
        grad_loss=None
    )

    optimizer.compute_gradients是tf.gradients的封装1.

    是optimizer.minimize()的第一步,返回(gradient, variable)的列表,其中gradient是tensor。

    直观上,optimizer.compute_gradients只比tf.gradients多了一个variable输出。

    3. tf.stop_gradient

    tf.stop_gradient(
        input,
        name=None
    )

    tf.stop_gradient阻止input的变量参与梯度计算,即在梯度计算的过程中屏蔽input之前的graph。

    返回:关于input的梯度

    应用:

    1、EM算法,其中M步骤不应涉及通过E步骤的输出的反向传播。

    2、Boltzmann机器的对比散度训练,在区分能量函数时,训练不得反向传播通过模型生成样本的图形。

    3、对抗性训练,通过对抗性示例生成过程不会发生反向训练。

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持站长博客。

    jsjbwy
    下一篇:没有了