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

PyTorch训练输出值量级差异极大的神经网络优化方案求助

可行训练方案

针对输出向量尺度差异极大的训练问题,以下是几个实用的优化方案,附代码示例:

1. 自适应加权MSE损失(基于真实值尺度)

你之前的固定掩码权重方法存在阈值僵化的问题,不如直接用真实值的动态尺度调整损失权重,让小数值的损失贡献自动放大,平衡不同尺度的学习优先级。

代码示例:

import torch
import numpy as np

gnd_truth = torch.from_numpy(np.array([20.42, -1.56e-4, -3.11, 4.2e-2, -7e-3, 10.11]))[None]
dnn_in = torch.from_numpy(np.array([0.76, 0.34]))[None]

optimizer.zero_grad()
dnn_out = net(dnn_in)

# 计算自适应权重:用真实值绝对值的倒数,加1e-8防止除以零
weights = 1.0 / (torch.abs(gnd_truth) + 1e-8)
# 可选:归一化权重,避免极端值主导损失
weights = weights / weights.mean()

# 加权MSE损失
loss = torch.mean((dnn_out - gnd_truth)**2 * weights)

loss.backward()
optimizer.step()

如果觉得倒数权重过于极端,也可以用平方根倒数:weights = 1.0 / torch.sqrt(torch.abs(gnd_truth) + 1e-8),效果更温和。

2. 分分支多输出头训练

将输出向量按数值尺度拆分为大、小数值两组,用网络的两个独立分支分别预测,再加权合并损失。这样模型可以针对不同尺度的输出单独优化参数,避免互相干扰。

代码示例:
假设你将网络net修改为返回两个分支输出:

import torch
import numpy as np

gnd_truth = torch.from_numpy(np.array([20.42, -1.56e-4, -3.11, 4.2e-2, -7e-3, 10.11]))[None]
# 手动划分大/小数值维度(也可根据batch真实值动态划分)
large_indices = [0,2,5]
small_indices = [1,3,4]
gnd_large = gnd_truth[:, large_indices]
gnd_small = gnd_truth[:, small_indices]

dnn_in = torch.from_numpy(np.array([0.76, 0.34]))[None]

optimizer.zero_grad()
# 修改后的网络返回两个分支输出
out_large, out_small = net(dnn_in)

# 给小数值损失加权重,提升学习优先级
loss_large = torch.nn.functional.mse_loss(out_large, gnd_large)
loss_small = torch.nn.functional.mse_loss(out_small, gnd_small)
loss = loss_large + 100 * loss_small  # 权重可根据效果调整

loss.backward()
optimizer.step()

3. 对数变换+符号保留

通过对数变换把跨数量级的数值拉到同一范围,降低模型学习难度。对真实值做「符号 × log10(绝对值 + 小常数)」的变换,模型输出变换后的值,再反向变换得到原始尺度的预测结果。

代码示例:

import torch
import numpy as np

gnd_truth = torch.from_numpy(np.array([20.42, -1.56e-4, -3.11, 4.2e-2, -7e-3, 10.11]))[None]
dnn_in = torch.from_numpy(np.array([0.76, 0.34]))[None]

# 真实值变换函数
def transform_target(target):
    sign = torch.sign(target)
    abs_log = torch.log10(torch.abs(target) + 1e-8)  # 加1e-8避免log(0)
    return sign * abs_log

# 反向变换得到原始尺度预测
def inverse_transform(pred):
    sign = torch.sign(pred)
    abs_pred = torch.pow(10, torch.abs(pred))
    return sign * abs_pred

optimizer.zero_grad()
# 模型输出变换后的数值
dnn_out_transformed = net(dnn_in)
gnd_transformed = transform_target(gnd_truth)

# 用变换后的MSE计算损失
loss_transformed = torch.nn.functional.mse_loss(dnn_out_transformed, gnd_transformed)

# 可选:叠加原始尺度的相对误差损失,双重约束
dnn_out = inverse_transform(dnn_out_transformed)
loss_relative = torch.mean(torch.abs(dnn_out - gnd_truth)/(torch.abs(gnd_truth)+1e-8))
loss = loss_transformed + 0.1 * loss_relative  # 权重可调

loss.backward()
optimizer.step()

4. 相对误差损失(优先保证比例正确)

对于尺度差异大的场景,相对误差比绝对误差更有参考价值。比如真实值1e-5预测成2e-5,绝对误差极小但相对误差达100%;真实值100预测成101,绝对误差大但相对误差仅1%。用相对误差作为损失,能让模型优先保证每个维度的预测比例准确。

代码示例:

import torch
import numpy as np

gnd_truth = torch.from_numpy(np.array([20.42, -1.56e-4, -3.11, 4.2e-2, -7e-3, 10.11]))[None]
dnn_in = torch.from_numpy(np.array([0.76, 0.34]))[None]

optimizer.zero_grad()
dnn_out = net(dnn_in)

# 平方相对误差损失
loss = torch.mean(((dnn_out - gnd_truth) / (torch.abs(gnd_truth) + 1e-8)) ** 2)

# 或者用绝对相对误差
# loss = torch.mean(torch.abs(dnn_out - gnd_truth) / (torch.abs(gnd_truth) + 1e-8))

loss.backward()
optimizer.step()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 10:52:09