从tf.GradientTape
开始的梯度似乎与我要最小化的函数中的最小最小值不匹配。
我正在尝试通过keras优化器tf.GradientTape
使用tensorflowprobability的黑盒变分推断(使用tf2),并调用apply_gradients
函数。后代是简单的一维法线。我正在尝试近似一对法线,请参见pdist函数。为简单起见,我只是尝试优化scale参数。
当前代码:
from scipy.special import erf
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
import tensorflow as tf
import tensorflow_probability as tfp
from tensorflow_probability import distributions as tfd
def pdist(x):
return (.5/np.sqrt(2*np.pi)) * np.exp((-(x+3)**2)/2) + (.5/np.sqrt(2*np.pi)) * np.exp((-(x-3)**2)/2)
def logpdist(x):
logp = np.log(1e-30+pdist(x))
assert np.all(np.isfinite(logp))
return logp
optimizer = tf.keras.optimizers.Adam(learning_rate=0.1)
mu = tf.Variable(0.0,dtype=tf.float64)
scale = tf.Variable(1.0,dtype=tf.float64)
for it in range(100):
with tf.GradientTape() as tape:
surrogate_posterior = tfd.Normal(mu,scale)
elbo_loss = tfp.vi.monte_carlo_variational_loss(logpdist,surrogate_posterior,sample_size=10000)
gradients = tape.gradient(elbo_loss, [scale])
optimizer.apply_gradients(zip(gradients, [scale]))
if it%10==0: print(scale.numpy(),gradients[0].numpy(),elbo_loss.numpy())
输出(每10次迭代显示一次):
SCALE GRAD ELBO_LOSS
1.100, -1.000, 2.697
2.059, -0.508, 1.183
2.903, -0.354, 0.859 <<< (right answer about here)
3.636, -0.280, 1.208
4.283, -0.237, 1.989
4.869, -0.208, 3.021
5.411, -0.187, 4.310
5.923, -0.170, 5.525
6.413, -0.157, 7.250
6.885, -0.146, 8.775
由于某种原因,梯度不能反映真实的梯度,在scale = 2.74左右应为零。
为什么梯度与实际的elbo_loss不相关?
答案 0 :(得分:0)
希望有人可以详细说明以前的实现失败的原因(以及为什么没有失败,而答案却是错误的)。无论如何,我发现我可以通过确保键表达式使用tensorflow数学库而不是numpy的库来修复它。专门将上述两种方法替换为;
def pdist(x):
return (.5/np.sqrt(2*np.pi)) * tf.exp((-(x+3)**2)/2) + (.5/np.sqrt(2*np.pi)) * tf.exp((-(x-3)**2)/2)
def logpdist(x):
return tf.math.log(pdist(x))
随机优化现在有效。
输出:
2.020, -0.874, 1.177
2.399, -0.393, 0.916
2.662, -0.089, 0.857
2.761, 0.019, 0.850
2.765, 0.022, 0.843
2.745, -0.006, 0.851
2.741, 0.017, 0.845
2.752, 0.005, 0.852
2.744, 0.015, 0.852
2.747, 0.013, 0.862
我不会接受我自己的答案,如果能给出一些答案,使我对现在为什么起作用以及为什么以前失败了(以及为什么失败模式不是例外或失败)感到直觉,我将不胜感激。类似,但梯度不正确。