贝叶斯神经网络含噪时序预测:线性关系与递增噪声学习困境
贝叶斯神经网络时序预测问题的优化建议
核心问题
- 模型无法学习数据中的线性趋势
- 无法捕捉随x递增的噪声特征,推理阶段无法输出递增的预测标准差
1. 数据预处理与构建修正
修复语法错误
数据构建代码中shape[0]未定义,需替换为y_data.shape[0]:
for ii in range(y_data.shape[0] - lookBack - lookAHead): train_data_input.append(np.array(y_data[ii:ii+lookBack])) train_data_target.append(y_data[ii+lookBack + lookAHead])
调整归一化策略
当前全局归一化会压缩噪声的递增幅度特征,导致模型难以捕捉噪声随x变化的规律。建议:
- 保留原始数据的绝对尺度(去掉全局归一化),或对每个时序窗口做局部归一化
- 将
x_data作为额外输入特征,因为噪声与x直接相关,模型需要明确的x信息来学习递增噪声:# 修改输入构建,加入x的历史信息 for ii in range(y_data.shape[0] - lookBack - lookAHead): y_window = y_data[ii:ii+lookBack] x_window = x_data[ii:ii+lookBack] # 拼接y和x作为输入 train_data_input.append(np.stack([y_window, x_window], axis=-1)) # 输入维度变为2 inputDim = 2
2. 模型架构优化
替换Flatten为时序模型
Flatten会丢失时间序列的顺序依赖,改用LSTM/GRU捕捉时序特征:
inputModel = Input(shape=(lookBack, inputDim)) # 用LSTM提取时序特征 features = layers.LSTM(64, return_sequences=False)(inputModel) features = layers.Dense(32, activation="relu")(features) # 改用relu避免tanh的梯度消失 features = tfp.layers.DenseVariational( units=16, # 增加单元数提升表达能力 make_prior_fn=prior2, # 用可学习先验增加灵活性 make_posterior_fn=posterior2, kl_weight=1/(train_data_input.shape[0]*(1-split)), # 对应训练集样本数 activation="relu", )(features)
增加网络深度
贝叶斯模型需要足够的容量学习复杂模式,可在DenseVariational后再添加一层普通Dense:
features = layers.Dense(8, activation="relu")(features)
3. 贝叶斯输出与损失设置
灵活控制标准差输出
放弃IndependentNormal,手动定义Normal分布并约束标准差,确保其能随输入递增:
if output_type == "dist": distribution_params = Dense(2)(features) c = np.log(np.expm1(1.0)) # 确保初始标准差不为0 outputs = tfp.layers.DistributionLambda(lambda t: tfp.distributions.Normal( loc=t[..., :1], scale=1e-3 + tf.math.softplus(c + 0.1 * t[..., 1:]) # 调大系数0.1,增强尺度的可学习性 ))(distribution_params)
修正损失函数
仅使用负对数似然作为分布输出的损失,KLD损失不适用于单点目标的回归任务:
def negative_loglikelihood(targets, estimated_distribution): return -estimated_distribution.log_prob(targets) if output_type == "dist": loss = negative_loglikelihood
4. 训练策略调整
增加训练轮次与学习率调度
贝叶斯模型收敛较慢,需更多训练轮次,并加入学习率衰减:
optimizer = tf.keras.optimizers.Adam(learning_rate=1e-3) # 添加学习率调度器 lr_scheduler = tf.keras.callbacks.ReduceLROnPlateau( monitor='val_loss', factor=0.5, patience=5, min_lr=1e-5 ) model.fit( x=train_data_input, y=train_data_target, epochs=100, # 提升至100轮 validation_split=split, callbacks=[lr_scheduler] )
5. 评估方式优化
简化分布预测的采样逻辑
当输出为分布时,无需多次采样模型,直接提取每个输入对应的mean和stddev即可:
if output_type == "dist": prediction_dist = model(train_data_input) predicted_mean = prediction_dist.mean().numpy() predicted_std = prediction_dist.stddev().numpy()
对齐绘图的x轴
确保预测结果的x轴与原始数据的x轴对应,避免偏移:
# 预测结果对应的原始x索引 pred_x = x_data[lookBack + lookAHead : lookBack + lookAHead + predicted_mean.shape[0]] plt.plot(pred_x, np.squeeze(predicted_mean), color="r") plt.plot(pred_x, predicted_std, color="g") plt.plot(pred_x, np.squeeze(lower_bound), color="r", alpha=0.5) plt.plot(pred_x, np.squeeze(upper_bound), color="r", alpha=0.5)
内容的提问来源于stack exchange,提问作者Usaint
相关产品推荐
相关产品推荐

