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

DPO训练过程中预训练模型权重未更新问题求助

问题分析与解决思路

核心问题在于计算图断裂,导致梯度无法传递到模型参数:
你的loss是通过独立脚本run_mpnn计算的得分得到的,这部分得分是脱离当前训练模型计算图的纯数值,没有和内存中的model建立反向传播依赖,因此loss.backward()不会产生任何梯度,optimizer.step()自然也不会更新权重。

具体解决办法

1. 整合得分计算到训练流程(最优方案)

放弃独立脚本计算得分,直接在训练函数内调用模型的前向传播生成logps,让得分计算成为计算图的一部分:

def train(model, optimizer, pref_set, dispref_set, epochs, beta, bs):
    model.train()
    for epoch in range(epochs):
        cur_pref=[]
        cur_dispref=[]
        for i in range(len(pref_set)):
            cur_pref.append(pref_set[i])
            cur_dispref.append(dispref_set[i])
            if (i+1) % bs == 0:
                # 直接用当前model计算偏好/非偏好样本的logps
                # 替换原有的make_fastas、run_mpnn、collect_logps流程
                b_dpo = []
                nb_dpo = []
                for pref, dispref in zip(cur_pref, cur_dispref):
                    # 假设model接受样本输入,返回log概率
                    pref_logp = model(pref)
                    dispref_logp = model(dispref)
                    b_dpo.append(pref_logp)
                    nb_dpo.append(dispref_logp)
                # 参考模型的logps如果是固定的,可以提前预计算好
                b_ref, nb_ref = get_precomputed_ref_logps(cur_pref)
                # 计算loss
                loss = calc_loss(b_dpo, nb_dpo, b_ref, nb_ref, beta)
                print(loss)
                # 反向传播与更新
                optimizer.zero_grad()
                loss.backward()
                optimizer.step()
                # 验证参数是否更新:打印某参数的数值
                print(list(model.parameters())[0].data[0])
                # 保存模型
                torch.save({
                        'epoch': epoch+1,
                        'step': i,
                        'num_edges' : 48,
                        'noise_level': 0.2,
                        'model_state_dict': model.state_dict(),
                        'optimizer_state_dict': optimizer.state_dict(),
                        }, "../ProteinMPNN/vanilla_model_weights/model-DPO.pt")
                cur_pref=[]
                cur_dispref=[]

2. 若必须使用独立脚本的折中方案

如果无法避免用独立脚本打分,需要确保每轮离线打分使用的是最新更新后的模型,并且接受这种模式下梯度是近似的(因为得分是基于上一轮模型的,不是当前计算图的一部分):

  • 先完成一轮梯度更新,保存模型
  • 调用独立脚本加载最新模型,计算所有样本的得分并保存
  • 下一轮训练时加载这些预计算的得分,计算loss并更新模型
  • 注意:这种方式相当于用离线得分做监督,不是严格的DPO在线训练,效果会受影响

额外排查点

  • 检查calc_loss函数中是否存在detach()、.numpy()或.item()操作,这些会破坏张量的可导性
  • 确认optimizer初始化时传入了model.parameters(),确保优化器关联了正确的参数
  • 在optimizer.step()前后打印模型参数的具体数值(如list(model.parameters())[0].data),直接验证内存中的模型是否更新,而不是仅依赖保存的文件

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 23:15:55