You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用变分自编码器(VAE)实现向量预测?代码修改咨询

VAE修改:实现X到Y的单向映射预测

我找到了一段变分自编码器(VAE)的代码,但无法理解。我希望训练模型学习(X,Y)的映射关系,训练完成后仅输入X即可预测Y,无需将Y作为输入。请问需要修改代码的哪些部分?

核心修改点

  • 移除Y作为模型输入:原代码把Y(inputs_r)作为编码器输入,不符合"仅用X预测Y"的需求,需删除所有和inputs_r相关的输入分支。
  • 重构模型目标:原VAE是重建输入X,现在要改成预测Y,模型输出应为Y的概率分布参数(均值/方差),损失函数结合回归损失和VAE的KL散度损失,保证模型的概率特性。
  • 简化编码器结构:让编码器仅从X提取特征,输出Y的均值(y_mean)和对数方差(y_log_var),保留VAE的重参数化采样逻辑。
  • 构建专用预测模型:训练完成后,单独构建只接收X、输出Y预测值(如直接用均值)的模型,方便部署使用。
  • 调整训练数据:训练时输入只有X,标签是Y,验证数据同理。

修改后的完整代码

from keras.layers import Lambda, Input, Dense, Dropout
from keras.models import Model
from keras.losses import mse
from keras import backend as K
from keras.constraints import unit_norm
import tensorflow as tf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import mean_squared_error, r2_score

# 重参数化技巧
def sampling(args):
    z_mean, z_log_var = args
    batch = K.shape(z_mean)[0]
    dim = K.int_shape(z_mean)[1]
    epsilon = K.random_normal(shape=(batch, dim))
    return z_mean + K.exp(0.5 * z_log_var) * epsilon

# 加载数据(替换为你的实际数据)
# X.shape: (n_samples, 32), Y.shape: (n_samples, 16)
X = ...
Y = ...
XX = ...  # 验证集X
YY = ...  # 验证集Y

np.random.seed(seed=0)

# 模型参数
input_shape_x = (32, )
output_shape_y = (16, )  # Y的维度
intermediate_dim = 32
batch_size = 64
latent_dim = 32
epochs = 800

# 构建编码器:仅输入X,输出Y的分布参数和采样值
inputs_x = Input(shape=input_shape_x, name='encoder_input')
inputs_x_dropout = Dropout(0.25)(inputs_x)

inter_x1 = Dense(128, activation='tanh', name='encoder_intermediate')(inputs_x_dropout)
inter_x2 = Dense(intermediate_dim, activation='tanh', name='encoder_intermediate_2')(inter_x1)

# 输出Y的均值和对数方差(概率回归核心)
y_mean = Dense(output_shape_y[0], name='y_mean')(inter_x2)
y_log_var = Dense(output_shape_y[0], name='y_log_var')(inter_x2)

# 重参数化采样得到Y的样本
y_sampled = Lambda(sampling, output_shape=output_shape_y, name='y_sampled')([y_mean, y_log_var])

# 编码器模型:输入X,输出Y的均值、方差、采样值
encoder = Model(inputs_x, [y_mean, y_log_var, y_sampled], name='encoder')

# 定义VAE损失:MSE损失 + KL散度损失
def vae_loss(y_true, y_pred):
    # MSE损失:预测值和真实Y的误差
    recon_loss = mse(y_true, y_pred)
    recon_loss *= output_shape_y[0]  # 乘以维度缩放
    # KL散度:约束Y的分布接近标准正态
    kl_loss = 1 + y_log_var - K.square(y_mean) - K.exp(y_log_var)
    kl_loss = K.sum(kl_loss, axis=-1)
    kl_loss *= -0.5
    return K.mean(recon_loss + kl_loss)

# 构建完整VAE模型:输入X,输出采样的Y
vae = Model(inputs_x, y_sampled, name='vae_regressor')
vae.compile(optimizer='adam', loss=vae_loss)

# 训练模型:输入X,标签是Y
history = vae.fit(X, Y, epochs=epochs, batch_size=batch_size, shuffle=True, validation_data=(XX, YY))

# 构建预测模型:输入X,直接输出Y的均值(最稳定的预测值)
predictor = Model(inputs_x, y_mean, name='y_predictor')

# 保存模型
encoder.save("BrmEnco_Third.h5")
vae.save("BrmVAE_Third.h5")
predictor.save("BrmPredictor_Third.h5")

# 可视化训练损失
plt.figure(figsize=(8, 4))
plt.plot(history.history['loss'], label='训练损失')
plt.plot(history.history['val_loss'], label='验证损失')
plt.title('训练与验证损失')
plt.ylabel('损失值')
plt.xlabel('轮次')
plt.legend()
plt.show()

# 测试预测效果
y_pred = predictor.predict(XX)
print(f"验证集MSE: {mean_squared_error(YY, y_pred):.4f}")
print(f"验证集R²: {r2_score(YY, y_pred):.4f}")

关键修改说明

  1. 移除Y输入分支:彻底删除原代码中inputs_r相关的所有层和输入逻辑,编码器仅接收X作为输入。
  2. 自定义损失函数:vae_loss同时考虑回归精度(MSE)和分布合理性(KL散度),避免模型过拟合且保证输出符合概率分布特性。
  3. 分离预测模型:单独构建的predictor模型直接输出Y的均值,避免采样带来的随机性,适合实际预测场景。
  4. 调整训练逻辑:fit函数输入仅为X,标签为Y,完全贴合X→Y的映射学习目标。

内容的提问来源于stack exchange,提问作者stevGates

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 13:42:07