Tensorflow 可以计算积分近似的梯度吗?

Cob*_*les 5 python montecarlo tensorflow

我正在尝试使用 Hamiltonian Monte Carlo(HMC,来自 Tensorflow Probability),但我的目标分布包含一个难以处理的一维积分,我用梯形规则近似。我对 HMC 的理解是它计算目标分布的梯度以构建更有效的过渡内核。我的问题是 Tensorflow 能否根据函数的参数计算出梯度,它们是否有意义?

例如,这是目标分布的对数概率,其中“A”是模型参数:

# integrate e^At * f[t] with respect to t between 0 and t, for all t

t = tf.linspace(0., 10., 100)
f = tf.ones(100)
delta = t[1]-t[0]
sum_term = tfm.multiply(tfm.exp(A*t), f)
integrals = 0.5*delta*tfm.cumsum(sum_term[:-1] + sum_term[1:], axis=0) 
pred = integrals
sq_diff = tfm.square(observed_data - pred)
sq_diff = tf.reduce_sum(sq_diff, axis=0)
log_lik = -0.5*tfm.log(2*PI*variance) - 0.5*sq_diff/variance
return log_lik
Run Code Online (Sandbox Code Playgroud)

这个函数的梯度在 A 方面有意义吗?

pal*_*ain 3

是的,您可以使用tensorflow GradientTape来计算梯度。我假设你有一个数学函数,输出log_lik有许多输入,其中之一是A

GradientTape 获取 A 的梯度

log_lik获得相对于的梯度,您可以在张量流中A使用tf.GradientTape

例如:

with tf.GradientTape(persistent=True) as g:
  g.watch(A)

  t = tf.linspace(0., 10., 100)
  f = tf.ones(100)
  delta = t[1]-t[0]
  sum_term = tfm.multiply(tfm.exp(A*t), f)
  integrals = 0.5*delta*tfm.cumsum(sum_term[:-1] + sum_term[1:], axis=0) 
  pred = integrals
  sq_diff = tfm.square(observed_data - pred)
  sq_diff = tf.reduce_sum(sq_diff, axis=0)
  log_lik = -0.5*tfm.log(2*PI*variance) - 0.5*sq_diff/variance
  z = log_lik

## then, you can get the gradients of log_lik with respect to A like this
dz_dA = g.gradient(z, A)
Run Code Online (Sandbox Code Playgroud)

dz_dA包含变量的所有偏导数A

我只是通过上面的代码向您展示了这个想法。为了使其工作,您需要通过张量运算进行计算。因此更改修改您的函数以使用张量类型进行计算

另一个例子,但在张量运算中

x = tf.constant(3.0)
with tf.GradientTape() as g:
  g.watch(x)
  with tf.GradientTape() as gg:
    gg.watch(x)
    y = x * x
  dy_dx = gg.gradient(y, x)     # Will compute to 6.0
d2y_dx2 = g.gradient(dy_dx, x)  # Will compute to 2.0
Run Code Online (Sandbox Code Playgroud)

在这里您可以从文档中查看更多示例以了解更多信息https://www.tensorflow.org/api_docs/python/tf/GradientTape

进一步讨论“意义”

我先把python代码翻译成数学(我使用https://www.codecogs.com/latex/eqneditor.php,希望它能正常显示):

# integrate e^At * f[t] with respect to t between 0 and t, for all t
Run Code Online (Sandbox Code Playgroud)

从上面看,这意味着你有一个函数。我称之为g(t, A)

然后你正在做积分。我称之为G(t,A)

从你的代码来看,t不再是变量,它被设置为 10。因此,我们简化为一个只有一个变量的函数h(A)

到目前为止,函数h内部已经有了定积分。但既然你正在逼近它,我们不应该将它视为一个真正的积分(dt -> 0),它只是另一个简单数学链。这里没有什么神秘的。

然后,最后一个输出log_lik,这只是一些带有一个新输入变量的简单数学运算observed_data,我称之为y

z那么计算的函数log_lik是:

z与张量流中其他正常的数学运算链没有什么不同。因此,在wrt的梯度为您提供可以最小化的更新梯度dz_dA的意义上是有意义的zAAz