自定义 BERT 分类模型时,由于未使用 pooler 层导致的分布式训练梯度同步失败问题解决方法
·
- 报错:
RuntimeError: Expected to have finished reduction in the prior iteration before starting a new one. This error indicates that your module has parameters that were not used in producing loss. - 报错解析:反向传播【loss.backward()】过程中,模型的所有参数都应该收到梯度, DDP 会在各个 GPU 之间同步梯度。如果有些参数因为没有参与最终 loss 的计算,导致它们没有梯度,那么 DDP 就无法同步这部分参数的梯度,导致出错。
- 报错原因:直接取了倒数第 2 层的 [CLS],而不是 BERT 模型最后一层的、经过池化的 [CLS],导致最后一层没被使用到,不参与 loss 的计算,因此没有梯度。
def forward(self, input_ids, attention_mask, token_type_ids, labels=None):
output = self.bert(input_ids=input_ids, token_type_ids=token_type_ids,
attention_mask=attention_mask)
# 获取CLS的未池化前的表示,[0]表示隐藏层,[:, 0, :]表示 seq_len = 0 处
em_sentence = output[0][:, 0, :]
em_sentence = self.dropout_pair(em_sentence)
x = self.dense(em_sentence)
return x
- 解决办法:DDP 包装 model 的时候加上参数
find_unused_parameters=True,这会自动跳过没用到的参数
model = DistributedDataParallel(model, device_ids=[local_rank], output_device=local_rank, find_unused_parameters=True)
更多推荐
所有评论(0)