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

PyTorch自动编码器:数据缩放训练后结果形状失真问题求解

自动编码器保留正负数据形状的解决方案

问题核心分析

  1. 不缩放时负数被置0:解码器最后使用Sigmoid激活函数,输出范围固定为[0,1],原始数据中的负数部分无法被还原,直接被截断为0。
  2. [0,1]缩放后效果差:将包含正负的原始数据强行压缩到[0,1]区间,再配合Sigmoid激活,会导致数据分布扭曲,网络难以学习到有效的特征表示。

最优解决方案:零均值标准化 + Tanh激活函数

针对包含正负的连续数值数据,零均值标准化(Standardization) 比[0,1]缩放更适配,配合Tanh激活函数(输出范围[-1,1]),可以完美覆盖标准化后的数据分布,避免信息丢失和截断。

1. 修改数据集预处理类

替换原有的[0,1]缩放为零均值标准化,同时新增反标准化方法用于还原输出:

import numpy as np
import torch

class AirfoilDataset(torch.utils.data.Dataset):
    def __init__(self, data):
        self.airfoils = np.copy(data).astype(np.float32)
        # 计算训练集的均值和标准差(按特征列计算)
        self.mean = self.airfoils.mean(axis=0)
        self.std = self.airfoils.std(axis=0)
        # 避免标准差为0导致除零错误,添加极小值
        self.std[self.std == 0] = 1e-8
        # 标准化:(x - 均值) / 标准差
        self.airfoils = (self.airfoils - self.mean) / self.std

    def __len__(self):
        return len(self.airfoils)

    def __getitem__(self, idx):
        return torch.from_numpy(self.airfoils[idx]), idx

    # 反标准化:将网络输出还原为原始数据范围
    def inverse_transform(self, x):
        return x * self.std + self.mean

2. 修改自动编码器结构

将编码器和解码器的Sigmoid替换为Tanh,让输出范围匹配标准化后的数据:

class Autoencoder(torch.nn.Module):
    def __init__(self):
        super().__init__()

        self.encoder = torch.nn.Sequential(
            torch.nn.Linear(10, 5),
            torch.nn.Tanh()  # 输出范围[-1,1],适配标准化数据
        )

        self.decoder = torch.nn.Sequential(
            torch.nn.Linear(5, 10),
            torch.nn.Tanh()  # 输出范围[-1,1],后续反标准化还原原始范围
        )

    def forward(self, x):
        x = self.encoder(x)
        x = self.decoder(x)
        return x

3. 训练与推理示例

# 假设data是你的原始10列数据集(shape: [N, 10])
dataset = AirfoilDataset(data)
dataloader = torch.utils.data.DataLoader(dataset, batch_size=32, shuffle=True)

# 初始化模型、损失函数和优化器
model = Autoencoder()
criterion = torch.nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)

# 训练循环
for epoch in range(50):
    model.train()
    total_loss = 0.0
    for batch_data, _ in dataloader:
        optimizer.zero_grad()
        outputs = model(batch_data)
        loss = criterion(outputs, batch_data)
        loss.backward()
        optimizer.step()
        total_loss += loss.item() * batch_data.size(0)
    avg_loss = total_loss / len(dataset)
    print(f"Epoch {epoch+1}, Average Loss: {avg_loss:.6f}")

# 推理并还原结果
model.eval()
with torch.no_grad():
    # 取一个样本测试
    sample_input, idx = dataset[0]
    sample_output = model(sample_input.unsqueeze(0))
    # 反标准化回到原始数据范围
    original_output = dataset.inverse_transform(sample_output.squeeze(0).numpy())
    print("原始输入(反标准化后):", dataset.inverse_transform(sample_input.numpy()))
    print("还原输出:", original_output)

备选方案:保留[0,1]缩放但调整网络输出层

如果坚持使用[0,1]缩放,可将解码器最后一层改为无激活的线性层(输出范围无限制),避免Sigmoid的范围约束:

class Autoencoder(torch.nn.Module):
    def __init__(self):
        super().__init__()

        self.encoder = torch.nn.Sequential(
            torch.nn.Linear(10, 5),
            torch.nn.Sigmoid()
        )

        self.decoder = torch.nn.Sequential(
            torch.nn.Linear(5, 10)  # 去掉Sigmoid,直接输出任意值
        )

    def forward(self, x):
        x = self.encoder(x)
        x = self.decoder(x)
        return x

但此方案训练稳定性不如零均值标准化+Tanh的组合,仅作为特殊场景下的备选。

内容的提问来源于stack exchange,提问作者rafal.sz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 11:15:58