GradientDescentOptimizer有哪些输入?

时间:2018-05-23 18:06:25

标签: tensorflow

我正在尝试创建一个最小的代码段来理解GradientDescentOptimizer类,以帮助我更深入地理解tensorflow API文档。

我想为GradientDescentOptimizer提供一些硬编码输入,运行minimize()方法并检查输出。到目前为止,我创建了以下内容:

loss_data = tf.Variable([2.0], dtype=tf.float32)
train_data = tf.Variable([20.0], dtype=tf.float32, name='train')

optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.02)
gradients = optimizer.compute_gradients(loss_data, var_list=[train_data])

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

我得到的错误是:

TypeError: Fetch argument None has invalid type <class 'NoneType'>

但是,我只是猜测输入的样子。任何指示赞赏,以帮助我理解我应该传递给这个功能。

更多背景......

我按照类似的过程来理解激活功能,通过隔离它们并将它们视为一个黑盒子,我发送一系列输入并检查相应的输出。

# I could have used a list of values but I wanted to experiment 
# by passing in one parameter value at a time.
placeholder = tf.placeholder(dtype=tf.float32, shape=[1], name='placeholder')
activated = tf.nn.sigmoid(placeholder)

with tf.Session() as sess:
    x_y = {}
    for x in range(-10, 10):
        x_y[x] = sess.run(activated, feed_dict={ placeholder: [x/1.0]})

import matplotlib.pyplot as plt
%matplotlib inline

x, y = zip(*x_y.items())
plt.plot(x, y)

enter image description here

上述过程对于我对激活函数的理解非常有用,我希望为优化器做类似的事情。

2 个答案:

答案 0 :(得分:2)

您的损失不应该是变量(它不是您的模型的参数),而是操作的结果,例如

loss_data = train_data**2

目前您的损失不依赖于train_data,这解释了为什么不能计算梯度。

答案 1 :(得分:1)

this discussion on GitHub。基本上,tf.compute_gradients为所有与其输入无关的变量返回None的渐变,session.run如果获得None值则会引发此错误。简单的解决方法;只告诉它与你传递的损失函数相关的变量:

gradients = optimizer.compute_gradients(loss_data, var_list=[loss_data])

现在当你跑:

print(sess.run(gradients))
# [(gradient, input)]
# [(array([1.], dtype=float32), array([2.], dtype=float32))]

哪个有道理。您正在计算x相对于x的渐变,该渐变始终为1.

更多说明性示例

对于更具说明性的内容,让我们定义一个用输入变量更改的loss op:

x = tf.Variable([1], dtype=tf.float32, name='input_x')
loss = tf.abs(x)

您的优化程序定义相同,但您的gradient操作系统现在已根据此loss操作计算:

optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.02)
gradients = optimizer.compute_gradients(loss, [x])

最后,我们可以在具有不同输入的循环中运行它,并查看渐变如何变化:

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    for i in range(-3, 3):
        grad = sess.run(gradients, feed_dict={x: (i,)})
        print(grad)

# [(gradient, input)]
# [(array([-1.], dtype=float32), array([-3.], dtype=float32))]
# [(array([-1.], dtype=float32), array([-2.], dtype=float32))]
# [(array([-1.], dtype=float32), array([-1.], dtype=float32))]
# [(array([0.], dtype=float32), array([0.], dtype=float32))]
# [(array([1.], dtype=float32), array([1.], dtype=float32))]
# [(array([1.], dtype=float32), array([2.], dtype=float32))]

如果loss = -x为负数,则为x;如果loss = +x为正数,则为x,因此对于负数,d_loss/d_x为-1 ,+为正数,如果输入为零则为零。