深入理解Tensorflow中的梯度计算算子-tf.gradients()

转载:https://blog.csdn.net/hustqb/article/details/80260002

声明:

  1. 参考官方文档
  2. 参考tensorflow学习笔记(三十)
  3. 关于神经网络中的梯度计算,推荐吴恩达的deeplearning公开课

tf.gradients()

在tensorflow中,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)

先不给出参数的意义~

对求导函数而言,其主要功能即求导公式:yx∂y∂x。在tensorflow中,yyxx都是tensor。

更进一步,tf.gradients()接受求导值ysxs不仅可以是tensor,还可以是list,形如[tensor1, tensor2, …, tensorn]。当ysxs都是list时,它们的求导关系为:

gradients() adds ops to the graph to output the derivatives of ys with respect to xs. It returns a list of Tensor of length len(xs) where each tensor is the sum(dy/dx) for y in ys.

意思是:

  1. tf.gradients()实现ysxs求导
  2. 求导返回值是一个list,list的长度等于len(xs)
  3. 假设返回值是[grad1, grad2, grad3],ys=[y1, y2],xs=[x1, x2, x3]。则,真实的计算过程为: 

基础实践

以线性回归为例,实践tf.gradients()的基础功能。线性回归:y=3×x+2y=3×x+2

import numpy as np
import tensorflow as tf


sess = tf.Session()

x_input = tf.placeholder(tf.float32, name='x_input')
y_input = tf.placeholder(tf.float32, name='y_input')
w = tf.Variable(2.0, name='weight')
b = tf.Variable(1.0, name='biases')
y = tf.add(tf.multiply(x_input, w), b)
loss_op = tf.reduce_sum(tf.pow(y_input - y, 2)) / (2 * 32)
train_op = tf.train.GradientDescentOptimizer(0.01).minimize(loss_op)

'''tensorboard'''
# gradients_node = tf.gradients(loss_op, w)
# print(gradients_node)
# tf.summary.scalar('norm_grads', gradients_node)
# tf.summary.histogram('norm_grads', gradients_node)
# merged = tf.summary.merge_all()
# writer = tf.summary.FileWriter('log')

init = tf.global_variables_initializer()
sess.run(init)

'''构造数据集'''
x_pure = np.random.randint(-10, 100, 32)
x_train = x_pure + np.random.randn(32) / 10  # 为x加噪声
y_train = 3 * x_pure + 2 + np.random.randn(32) / 10  # 为y加噪声

for i in range(20):
    _, gradients, loss = sess.run([train_op, gradients_node, loss_op],
                                  feed_dict={x_input: x_train[i], y_input: y_train[i]})
    print("epoch: {} \t loss: {} \t gradients: {}".format(i, loss, gradients))

sess.close()

输出:

epoch: 0     loss: 94.6083221436     gradients: [-187.66052]
epoch: 1     loss: 1.52120530605     gradients: [3.0984864]
epoch: 2     loss: 101.41834259      gradients: [241.91911]
...
epoch: 18    loss: 0.0215022582561   gradients: [-0.44370675]
epoch: 19    loss: 0.0189439821988   gradients: [-0.31349587]

可以看到梯度逐渐减小,说明模型逐渐收敛。同时也可以看到参数更新的方向主要是梯度下降的方向(尽管伴随着震荡)。

其他参数

其他参数都不太常用(其实是比较难用)。

grad_ys

grad_ys也是一个list,其长度等于len(ys)。这个参数的意义在于对xs中的每个元素的求导加权种。

假设grad_ys=[grad_ys1, grad_ys2, grad_ys3],xs=[x1, x2, x3],则list中每个元素,如grad_ys1的shape与xs的shape相同。

举个简单的例子:

import tensorflow as tf

w1 = tf.get_variable('w1', shape=[3])
w2 = tf.get_variable('w2', shape=[3])

w3 = tf.get_variable('w3', shape=[3])
w4 = tf.get_variable('w4', shape=[3])

z1 = 3 * w1 + 2 * w2+ w3
z2 = -1 * w3 + w4

grads = tf.gradients([z1, z2], [w1, w2, w3, w4], grad_ys=[[-2.0, -3.0, -4.0], [-2.0, -3.0, -4.0]])

with tf.Session() as sess:
    tf.global_variables_initializer().run()
    print(sess.run(grads))

如果不考虑参数grad_ys,输出应该是:

[array([ 3.,  3.,  3.], dtype=float32), 
array([ 2.,  2.,  2.], dtype=float32), 
array([ 0.,  0.,  0.], dtype=float32), 
array([ 1.,  1.,  1.], dtype=float32)]

现在在权重参数grad_ys = [[-2.0, -3.0, -4.0], [-2.0, -3.0, -4.0]]的加权下,输出实际为:

[array([ -6.,  -9., -12.], dtype=float32),
array([-4., -6., -8.], dtype=float32), 
array([0., 0., 0.], dtype=float32), 
array([-2., -3., -4.], dtype=float32)]

stop_gradients

stop_gradients也是一个list,list中的元素是tensorflow graph中的op,一旦进入这个list,将不会被计算梯度,更重要的是,在该op之后的BP计算都不会运行。

例如:

a = tf.constant(0.)
b = 2 * a
c = a + b
g = tf.gradients(c, [a, b])

计算得g = [3.0, 1.0]。因为

但如果冻结operator a和b的梯度计算:

a = tf.constant(0.)
b = 2 * a
g = tf.gradients(a + b, [a, b], stop_gradients=[a, b])

计算得g=[1.0, 1.0]。

上面的代码也等效于:

a = tf.stop_gradient(tf.constant(0.))
b = tf.stop_gradient(2 * a)
g = tf.gradients(a + b, [a, b])

猜你喜欢

转载自blog.csdn.net/qq_23981335/article/details/80759714
今日推荐