深度学习调试记录

今天编写了一个轨迹编码解码的神经网络,但是训练的时候loss下降的非常慢,最后在0.2附件徘徊。所以,记录一下轨迹编码的网络的训练过程:

看起来是长期在 ~0.25 左右平台期 。这种情况先别盲改"层数/学习率",按下面顺序快速定位------从"能不能在极简场景上学到接近 0 的损失"开始。如果连极简都不行,多半是数据/损失/对齐问题;如果极简能,才去调容量/学习率。

A. 10 分钟定位流程(强烈建议照做)

  1. 极小样本过拟合测试(必须过!)

    • 取 1--4 条轨迹,循环训练直到训练 loss≈1e-4(或明显下降到接近 0)。
    • 过不了 ⇒ 高概率是:数据未标准化 / 角度处理错误 / 目标对齐错位 / 损失维度权重失衡 / 代码 bug。
    python 复制代码
    subset = torch.utils.data.Subset(train_dataset, list(range(4)))
    loader = DataLoader(subset, batch_size=4, shuffle=True)
    for p in model.parameters(): p.requires_grad_(True)
    model.train()
    opt = torch.optim.Adam(model.parameters(), lr=1e-3)
    for step in range(3000):
        x = next(iter(loader)).to(device)          # x: (B,T,3) -> x,y,yaw
        y_hat = model(x)                            # 与你的前向一致
        loss = loss_fn(y_hat, x)                    # 见下文改进的loss
        opt.zero_grad(); loss.backward(); opt.step()
        if step % 100 == 0: print(step, float(loss))
    • 如果在这个测试里 loss 依旧 ~0.25,先别动模型结构,先修"B/C/D"
  2. 检查"目标对齐/索引"

    • 自回归解码时,常见错位:把 t 的输出跟 t+1 的标签比;或训练时 teacher forcing/shift 处理不一致。
    • 快检:用同一个网络做**"恒等映射"**(encoder 直连 decoder / 或把输入直接喂给输出头)看损失是否瞬间接近 0;不接近 ⇒ 维度/顺序/mask/归一化错了。
  3. 看"训练集 vs 验证集 loss"

    • 都在 0.25 附近欠拟合/损失定义有问题/优化器设置不当
    • 训练低、验证高 ⇒ 过拟合(再谈正则/数据)。

B. 先把"损失/数据预处理"修正确

你的轨迹是 (x, y, yaw)(yaw 是角度)。直接用 MSE 处理角度会出错(π 与 -π 的误差会非常大),必须用圆形角度损失 ;同时 (x,y) 尺度若没标准化,也会让 loss 卡高位。

建议的损失:Huber(x,y) + 角度环形误差(并对分量做尺度平衡)

python 复制代码
import torch
import torch.nn.functional as F

def angle_diff(a, b):
    # 角度差规约到 (-pi, pi]
    return torch.atan2(torch.sin(a-b), torch.cos(a-b))

def traj_loss(y_hat, y_true, xy_w=1.0, yaw_w=0.5, delta=1.0):
    # y_*: (B,T,3) -> x,y,yaw
    xy_hat, yaw_hat = y_hat[..., :2], y_hat[..., 2]
    xy_true, yaw_true = y_true[..., :2], y_true[..., 2]
    # Huber 对 (x,y),更稳
    l_xy = F.smooth_l1_loss(xy_hat, xy_true, reduction='mean', beta=delta)
    # 环形角度误差
    d_yaw = angle_diff(yaw_hat, yaw_true)
    l_yaw = torch.mean(d_yaw ** 2)               # 或者 smooth_l1 也行
    return xy_w * l_xy + yaw_w * l_yaw

强烈建议做标准化/反标准化 (至少对 x,y):

  • 训练前:x_norm = (x - μ) / σ(μ, σ 按训练集统计;yaw 不做 z-score,保持弧度制)
  • 模型预测后:反标准化再评估 ADE/FDE。
  • 如果你之前没做标准化,loss 卡在 0.2~0.4 非常常见。

可选:把 yaw 用 (sin, cos) 表示,预测两维再归一化到单位圆,误差用欧氏距离/余弦损失,很多轨迹任务更稳。

确保 mask 正确:如果有 padding,loss 一定要用 mask 只统计真实步长。


C. 优化器与学习率:先"找范围",再调度

别拍脑袋改 lr,用 LR Range Test(几百步就能看出合适区间):

python 复制代码
# 线性把 lr 从 1e-6 提到 1e-1,记录 loss vs lr
opt = torch.optim.Adam(model.parameters(), lr=1e-6)
gamma = (1e-1/1e-6) ** (1/1000)  # 1000 步内指数拉升
scheduler = torch.optim.lr_scheduler.ExponentialLR(opt, gamma)
lrs, losses = [], []
model.train()
it = iter(DataLoader(train_dataset, batch_size=64, shuffle=True))
for step in range(1000):
    try: batch = next(it)
    except StopIteration:
        it = iter(DataLoader(train_dataset, batch_size=64, shuffle=True))
        batch = next(it)
    x = batch.to(device)
    y_hat = model(x)
    loss = traj_loss(y_hat, x)
    opt.zero_grad(); loss.backward(); opt.step(); scheduler.step()
    lrs.append(opt.param_groups[0]['lr']); losses.append(float(loss))
# 观察在哪些 lr 区间 loss 快速下降且未爆炸,选一个中间值作为起始 lr

常见起点:Adam lr=1e-3,配 ReduceLROnPlateauCosineAnnealingLR

网络不收敛:可尝试 1e-2 → 1e-4 范围扫描。
记得 gradient clipping(RNN/GRU/LSTM 强烈建议):

python 复制代码
torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)

D. 自回归解码的"teacher forcing"与对齐

  • 训练时建议 teacher forcing 比例从 1.0 逐步退火(例如从 1.0 → 0.5 → 0.0),否则容易漂。
  • 检查你的 dec_in:是否用了上一步的真值 (teacher forcing)还是上一步的预测(free running)。两者在训练-推理间要一致或做好 schedule。
  • 确保"时间维对齐":out_t 对应的 target 是否同一时间步?

E. 判断"欠拟合 vs 过拟合",再决定改模型还是正则

  • 欠拟合(训练/验证都 ~0.25):

    • 增大容量:hid_dim ↑num_layers ↑z_dim ↑(若是 VAE),适当加残差/LayerNorm;
    • 去掉/减小 dropout、weight_decay,先让网络学得动;
    • 检查是否强正则(过大 wd / 过强 dropout / 过小 hid)。
  • 过拟合(训练低、验证高):

    • 增加 dropout、weight decay、数据增强(噪声、抖动、旋转对齐等)、早停。

F. 更可解释的评估指标(仅看 loss 不直观)

同时输出这些指标能帮你判断瓶颈在哪:

  • ADE/FDE(Average/Final Displacement Error):(x,y) 的 L2 距离(注意反标准化)。
  • Angle ADE/FDE:角度环形误差的平均/最终步。
  • 把一条轨迹的输入 vs 重构画在同一图里(肉眼看偏差在拐弯还是直行段)。

G. 常见坑位 Checklist

  • 没有 model.train() / model.eval() 正确切换(BN/Dropout 会受影响)。
  • optimizer.zero_grad() 忘了;或多次 loss.backward()retain_graph=True
  • loss 归一化方式错误(同时对 B、T、C 除法导致过小或不稳定)。
  • 训练时用了归一化数据 ,计算 loss 却在反归一化后(或反之)------前后一致。
  • shuffle/seed 设置问题导致批间极不均匀。
  • 数据里的 yaw 单位混乱(度/弧度)。
  • 时间步错位(target 提前或滞后了一步)。
  • 使用 --filter=blob:none 拉数据而忘了把真实文件取回(与你之前的 git/LFS 问题类似,这里只是提醒数据加载是否正确)。

H. 如果你要具体建议(基于你常用设置的"保守配方")

  • 数据x,y 标准化到均值 0 方差 1;yaw 用弧度,损失用环形;
  • 模型 :GRU 2--3 层,hid_dim=128~256;解码自回归 + teacher forcing 退火;
  • 优化:Adam(lr=1e-3, betas=(0.9,0.999)),clip_grad_norm=1.0,CosineAnnealingLR 或 ReduceLROnPlateau;
  • 损失:Huber(x,y, beta=1.0)*1.0 + angle MSE *0.5;
  • 训练 :先把4条样本过拟合到很低,再扩大数据量、打开正则。

如果你把一小段你的损失计算代码 (前向输出到 loss 的那几行)贴出来,以及你的 输入张量形状 (B,T,C)和是否标准化的信息,我可以直接指出哪一两行先改、以及建议的权重/学习率起点。

相关推荐
搞科研的小刘选手2 小时前
【学术会议合集】2025-2026年地球科学/遥感方向会议征稿信息
大数据·前端·人工智能·自动化·制造·地球科学·遥感测绘
lingliang3 小时前
机器学习之三大学习范式:监督学习、无监督学习、强化学习
人工智能·学习·机器学习
没有口袋啦3 小时前
《决策树、随机森林与模型调优》
人工智能·算法·决策树·随机森林·机器学习
计育韬3 小时前
计育韬:基于AI的数据可视化设计入门工作流
人工智能·信息可视化·新媒体运营·微信公众平台
倔强青铜三3 小时前
苦练Python第58天:filecmp模块——文件和目录“找不同”的利器
人工智能·python·面试
倔强青铜三3 小时前
苦练Python第59天:tempfile模块,临时文件自动删!再也不用手动清理到怀疑人生
人工智能·python·面试
stjiejieto3 小时前
AI 重构实体经济:2025 传统产业的智能转型革命
人工智能·重构
NCU_wander3 小时前
显存和算力的关系
深度学习
镰刀韭菜3 小时前
【AI4S】通过单一基础模型双向生成分子的结构和特性
人工智能·分子生成·ai4s·多模态分子预训练模型·spmm·bpe算法