torch.zeros_like

Posted by:

|

On:

|

for epoch in range(epochs):
    model.train()
    total_loss = 0
    for x, y in train_loader:
        tgt = torch.zeros_like(y)
        optimizer.zero_grad()
        output = model(x, tgt)
        loss = criterion(output, y)
        loss.backward()
        optimizer.step()
        total_loss += loss.item()
    print(f"Epoch {epoch+1}, Loss: {total_loss / len(train_loader):.4f}")


# During training
for epoch in range(epochs):
    model.train()
    total_loss = 0
    for x, y in train_loader:
        tgt = y[:, :-1, :] 
        optimizer.zero_grad()
        output = model(x, tgt)
        loss = criterion(output, y[:, 1:, :])  
        loss.backward()
        optimizer.step()
        total_loss += loss.item()
    print(f"Epoch {epoch+1}, Loss: {total_loss / len(train_loader):.4f}") 这两个什么区别 

这两段代码的区别在于:训练时目标序列 tgt 的设置方式不同,影响模型学习目标和质量。


第一段代码:使用全零目标序列

pythonCopyEditfor x, y in train_loader:
    tgt = torch.zeros_like(y)  # tgt 是全为0的张量
    ...
    output = model(x, tgt)
    loss = criterion(output, y)
  • tgt 输入的是全为0的张量,不含任何真实信息。
  • 相当于你让模型“从一片空白中预测出未来走势”,这非常困难。
  • Transformer Decoder 在训练时如果不看到真实值序列,很难学习到如何逐步生成序列。
  • 会导致预测值 几乎一样或者无法收敛

🛑 这种做法在时间序列建模中通常效果很差,不推荐


第二段代码:使用 teacher forcing(教学强制)

pythonCopyEditfor x, y in train_loader:
    tgt = y[:, :-1, :]               # 使用真实目标序列的前 (n-1) 步
    ...
    output = model(x, tgt)
    loss = criterion(output, y[:, 1:, :])  # 与目标序列的后 (n-1) 步做对比
  • 使用了真实的目标序列作为 Decoder 的输入,也就是所谓的 teacher forcing
  • 意思是:我告诉你第一天的值,你来预测第二天;然后告诉你第二天的值,你预测第三天……
  • 然后比较模型预测的 [t+1, t+2, ..., t+n] 和真实的 [t+1, t+2, ..., t+n]
  • 这种方式训练更稳定,收敛更快,预测精度更高。

这是推荐的做法,尤其适合时间序列预测、机器翻译等任务。


🧠 简单类比帮助理解

模式类比说明
第一段(用0作为目标输入)让一个学生在不知道考试题目的前提下写完整份答案
第二段(用部分真实目标)老师给他看前几道题的答案,他再尝试写后面的题目

✅ 建议总结

项目第一段(全零 tgt)第二段(真实 tgt)
输入给 decoder 的序列全为 0真实序列的前一部分
模型训练难度
收敛速度慢或不收敛
模型预测能力弱,容易输出重复值强,能学到序列模式
推荐程度❌ 不推荐✅ 推荐

如需进一步提升效果,还可以在训练中逐渐减少 teacher forcing 的比例,转向模型自回归(scheduled sampling)。