无法从DenseVariational获得合理的结果

我正在尝试使用以下大小为500的正弦曲线数据集进行回归问题

Dataset

首先,我尝试了两个各有10个单元的密集层

model = tf.keras.Sequential([        tf.keras.layers.Dense(10, activation='tanh'),        tf.keras.layers.Dense(10, activation='tanh'),        tf.keras.layers.Dense(1),        tfp.layers.DistributionLambda(lambda t: tfd.Normal(loc=t, scale=1.))    ])

使用负对数似然损失进行训练,如下所示

model.compile(optimizer=tf.optimizers.Adam(learning_rate=0.01), loss=neg_log_likelihood)model.fit(x, y, epochs=50)

得到的图表Without uncertainty

接下来,我尝试了类似的环境,使用DenseVariational

model = tf.keras.Sequential([        tfp.layers.DenseVariational(            10, activation='tanh', make_posterior_fn=posterior,            make_prior_fn=prior, kl_weight=1/N, kl_use_exact=True),        tfp.layers.DenseVariational(            10, activation='tanh', make_posterior_fn=posterior,            make_prior_fn=prior, kl_weight=1/N, kl_use_exact=True),        tfp.layers.DenseVariational(            1, activation='tanh', make_posterior_fn=posterior,            make_prior_fn=prior, kl_weight=1/N, kl_use_exact=True),        tfp.layers.DistributionLambda(lambda t: tfd.Normal(loc=t, scale=1.))    ])

由于参数数量大约翻倍,我尝试增加数据集大小和/或训练轮数,最多增加到100倍,但没有成功。结果通常如下所示。

With uncertainty

我的问题是如何使用DenseVariational获得与Dense层相当的结果?我还读到它可能对初始值敏感。这里是完整代码的链接。欢迎任何建议。


回答:

你需要定义一个不同的代理后验分布。在Tensorflow的贝叶斯线性回归示例中https://colab.research.google.com/github/tensorflow/probability/blob/master/tensorflow_probability/examples/jupyter_notebooks/Probabilistic_Layers_Regression.ipynb#scrollTo=VwzbWw3_CQ2z

你有如下后验均值场

# Specify the surrogate posterior over `keras.layers.Dense` `kernel` and `bias`.def posterior_mean_field(kernel_size, bias_size=0, dtype=None):  n = kernel_size + bias_size  c = np.log(np.expm1(1.))  return tf.keras.Sequential([      tfp.layers.VariableLayer(2 * n, dtype=dtype),      tfp.layers.DistributionLambda(lambda t: tfd.Independent(          tfd.Normal(loc=t[..., :n],                     scale=1e-5 + 0.01*tf.nn.softplus(c + t[..., n:])),          reinterpreted_batch_ndims=1)),  ])

但请注意,我在Softplus前面加了0.01,减小了标准差的大小。尝试一下这个方法。

比这更好的方法是使用类似于DenseFlipout中默认使用的采样初始化https://www.tensorflow.org/probability/api_docs/python/tfp/layers/DenseFlipout?version=nightly

这里是相同的初始化器,但适用于DenseVariational:

def random_gaussian_initializer(shape, dtype):    n = int(shape / 2)    loc_norm = tf.random_normal_initializer(mean=0., stddev=0.1)    loc = tf.Variable(        initial_value=loc_norm(shape=(n,), dtype=dtype)    )    scale_norm = tf.random_normal_initializer(mean=-3., stddev=0.1)    scale = tf.Variable(        initial_value=scale_norm(shape=(n,), dtype=dtype)    )    return tf.concat([loc, scale], 0)

现在你可以简单地将后验均值场中的VariableLayer更改为

tfp.layers.VariableLayer(2 * n, dtype=dtype, initializer=lambda shape, dtype: random_gaussian_initializer(shape, dtype), trainable=True)

你现在从均值为-3和标准差为0.1的正态分布中采样,以输入你的Softplus。使用后验均值场的均值,我们有scale=Softplus(-3) = 0,048587352,所以它非常小。通过采样,我们将所有尺度初始化为不同但围绕该均值的值。

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注