Theano - 如何为部分操作图覆盖梯度

3

我手头有一个相当复杂的模型。这个模型由多个具有 线性 结构的部分组成:

y = theano.tensor.dot(W,x) + b

我希望构建一个优化器,使用自定义规则计算所有线性结构的梯度,同时保持其他操作不变。 有没有最简单的方法来覆盖模型中所有线性部分的梯度运算? 最好无需编写新的操作。

1个回答

4
所以,我花了一些时间在Theano上开发了一个PR(截至2017年1月13日尚未合并,但现已合并),它使用户能够部分覆盖theano.OpFromGraph实例的梯度。用符号图进行覆盖,因此您仍然可以获得Theano优化的全部好处。
典型的用例:
- 数值安全考虑 - 重新缩放/剪辑梯度 - 像黎曼自然梯度这样的专业梯度例程
创建具有覆盖梯度的Op:
- 制作所需的计算图 - 为Op的梯度制作一个OpFromGraph实例(或Python函数) - 将OfG实例设置为您的Op,并设置grad_overrides参数 - 调用OfG实例以构建模型
定义OpFromGraph就像编译Theano函数一样,只是有些不同:
  • 截至2017年1月,不支持更新和给定值(givens)
  • 您将获得一个符号操作而不是数字函数

示例:

'''
This creates an atan2_safe Op with smoothed gradient at (0,0)
'''
import theano as th
import theano.tensor as T

# Turn this on if you want theano to build one large graph for your model instead of precompiling the small graph.
USE_INLINE = False
# In a real case you would set EPS to a much smaller value
EPS = 0.01

# define a graph for needed Op
s_x, s_y = T.scalars('xy')
s_darg = T.scalar(); # backpropagated gradient
s_arg = T.arctan2(s_y, s_x)
s_abs2 = T.sqr(s_x) + T.sqr(s_y) + EPS
s_dx = -s_y / s_abs2
s_dy = s_x / s_abs2

# construct OfG with gradient overrides
# NOTE: there are unused inputs in the gradient expression,
#     however the input count must match, so we pass    
#     on_unused_input='ignore'
atan2_safe_grad = th.OpFromGraph([s_x, s_y, s_darg], [s_dx, s_dy], inline=USE_INLINE, on_unused_input='ignore')
atan2_safe = th.OpFromGraph([s_x, s_y], [s_arg], inline=USE_INLINE, grad_overrides=atan2_safe_grad)

# build graph using the new Op
x, y = T.scalar(), T.scalar()
arg = atan2_safe(x, y)
dx, dy = T.grad(arg, [x, y])
fn = th.function([x, y], [dx, dy])
fn(1., 0.) # gives [-0.0, 0.99099]
fn(0., 0.) # gives [0.0, 0.0], no more annoying nan!

注意: theano.OpFromGraph 仍然处于实验阶段,可能会有错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接