如何为TensorFlow的DenseVariational层配置多输出
修改方案
你需要调整以下3处核心配置,不需要额外加层也能实现需求,要是时序特征拟合效果不好可以额外加时序特征提取层:
- 调整
DenseVariational的units参数:原来的1+1对应1个预测值+1个标准差,现在你需要2个角度分量(sin、cos)+2个对应标准差,所以改成2+2即可 - 修改
DistributionLambda中的参数切片逻辑:把原来取前1维作为均值、后1维作为标准差的逻辑,改成取前2维作为sin、cos的均值,后2维作为两个分量的对应标准差 - 修正拼写错误:你提到的
DenseVariatal是笔误,正确类名是DenseVariational
如果你的输入是时序结构没有展平,也可以在DenseVariational之前加一层LSTM或者GRU提取时序特征,拟合效果会更好。
修改后的可运行代码如下:
import numpy as np import tensorflow as tf import tensorflow_probability as tfp from tensorflow.keras import Sequential, optimizers from tensorflow_probability import distributions as tfd from tensorflow_probability.layers import DenseVariational, VariableLayer, DistributionLambda def nll(y_true, y_pred): return -y_pred.log_prob(y_true) def build(rows) -> tf.keras.Model: """Builds model architecture :return: model architecture """ def posterior_mean_field(kernel_size, bias_size=0, dtype=None): n = kernel_size + bias_size c = np.log(np.expm1(1.0)) return Sequential( [ VariableLayer(2 * n, dtype=dtype), DistributionLambda( lambda t: tfd.Independent( tfd.Normal( loc=t[..., :n], scale=1e-5 + tf.nn.softplus(c + t[..., n:]) ), reinterpreted_batch_ndims=1, ) ), ] ) def prior_trainable(kernel_size, bias_size=0, dtype=None): n = kernel_size + bias_size return Sequential( [ VariableLayer(n, dtype=dtype), DistributionLambda( lambda t: tfd.Independent( tfd.Normal(loc=t, scale=1), reinterpreted_batch_ndims=1 ) ), ] ) model = Sequential( [ # 若要加时序层,这里可以加 LSTM(32, input_shape=(时间步, 特征数)) 替换下面的input_shape配置 DenseVariational( 2 + 2, posterior_mean_field, prior_trainable, kl_weight=1 / rows, input_shape=(21,) ), DistributionLambda( lambda t: tfd.Independent( tfd.Normal( loc=t[..., :2], scale=1e-3 + tf.math.softplus(0.01 * t[..., 2:]) ), reinterpreted_batch_ndims=1 ) ), ] ) model.compile(optimizer=optimizers.Adam(learning_rate=0.01), loss=nll) return model
调用模型预测时,输出的分布取mean就能得到长度为2的数组,分别对应sin、cos的预测值,取stddev就能得到两个分量对应的标准差。
内容的提问来源于stack exchange,提问作者kiaora
相关产品推荐
相关产品推荐

