Using autodiff
前面的代码工作正常,但它需要从代价函数(MSE)中利用数学公式推导梯度。 在线性回归的情况下,这是相当容易的,但是如果你必须用深层神经网络来做这个事情,你会感到头痛:这将是乏味和容易出错的。 您可以使用符号求导来为您自动找到偏导数的方程式,但结果代码不一定非常有效。
为了理解为什么,考虑函数f(x) = exp(exp(exp(x)))
。如果你知道微积分,你可以计算出它的导数f'(x) = exp(x) * exp(exp(x)) * exp(exp(exp(x)))
。如果您按照普通的计算方式分别去写f(x)
和f'(x)
,您的代码将不会如此有效。 一个更有效的解决方案是写一个首先计算exp(x)
,然后exp(exp(x))
,然后exp(exp(exp(x)))
的函数,并返回所有三个。这直接给你(第三项)f(x)
,如果你需要求导,你可以把这三个子式相乘,你就完成了。 通过传统的方法,您不得不将exp
函数调用 9 次来计算f(x)
和f'(x)
。 使用这种方法,你只需要调用它三次。
当您的功能由某些任意代码定义时,它会变得更糟。 你能找到方程(或代码)来计算以下函数的偏导数吗?
提示:不要尝试。
def my_func(a, b):
z = 0
for i in range(100):
z = a * np.cos(z + i) + z * np.sin(b - i)
return z
幸运的是,TensorFlow 的自动计算梯度功能可以计算这个公式:它可以自动高效地为您计算梯度。 只需用以下面这行代码替换上一节中代码的gradients = ...
行,代码将继续工作正常:
gradients = tf.gradients(mse, [theta])[0]
gradients()
函数使用一个op
(在这种情况下是MSE)和一个变量列表(在这种情况下只是theta
),它创建一个ops
列表(每个变量一个)来计算op
的梯度变量。 因此,梯度节点将计算 MSE 相对于theta
的梯度向量。
自动计算梯度有四种主要方法。 它们总结在表 9-2 中。 TensorFlow 使用反向模式,这是完美的(高效和准确),当有很多输入和少量的输出,如通常在神经网络的情况。 它只需要通过 次图遍历即可计算所有输出的偏导数。