Deep learning 序列间丢失

Deep learning 序列间丢失,deep-learning,pytorch,huggingface-transformers,Deep Learning,Pytorch,Huggingface Transformers,我想弄清楚如何计算顺序间的损失。在本例中,我使用的是huggingface transformers库,但这实际上可能与其他DL库相关 因此,为了获得所需的数据,我们可以: 从transformers导入EncoderCodermodel,BertTokenizer 进口火炬 导入torch.nn.功能为F 手电筒。手动种子(42) 标记器=BertTokenizer.from_pretrained('bert-base-uncased')) 最大长度=128 tokenize=lambda x

我想弄清楚如何计算顺序间的损失。在本例中,我使用的是huggingface transformers库,但这实际上可能与其他DL库相关

因此,为了获得所需的数据,我们可以:

从transformers导入EncoderCodermodel,BertTokenizer
进口火炬
导入torch.nn.功能为F
手电筒。手动种子(42)
标记器=BertTokenizer.from_pretrained('bert-base-uncased'))
最大长度=128
tokenize=lambda x:tokenizer(x,max_length=max_LEN,truncation=True,padding=True,return_tensors=“pt”)
model=encoderCodermodel。从“编码器”到“解码器”预训练(“bert-base-uncased”,“bert-base-uncased”)#从预先训练的检查点初始化Bert2Bert
input_seq=[“你好,我的狗很可爱”,“我的猫很可爱”]
输出顺序=[“是的”,“确定”]
输入标记=标记化(输入顺序)
输出标记=标记化(输出顺序)
输出=模型(
输入标识=输入标识[“输入标识”],
注意屏蔽=输入令牌[“注意屏蔽”],
解码器输入标识=输出标识[“输入标识”],
解码器\u注意\u掩码=输出\u令牌[“注意\u掩码”],
标签=输出令牌[“输入标识”],
返回(dict=True)
idx=输出令牌[“输入令牌”]
logits=F.log\u softmax(输出[“logits”],dim=-1)
掩码=输出令牌[“注意掩码”]
编辑1 多亏了@cronoik,我才能够将huggingface计算的损失复制为:

output_logits=logits[:,:-1,:]
输出_掩码=掩码[:,:-1]
label_-tokens=输出_-tokens[“输入_-id”][:,1:]。取消查询(-1)
选择\u logits=torch.gather(输出\u logits,-1,标记\u令牌)。挤压()
huggingface\u loss=-select\u logits.mean()
但是,由于第二个输入的最后两个标记只是填充,我们不应该将损失计算为:

seq_loss=(选择_logits*output_mask).sum(dim=-1,keepdims=True)/output_mask.sum(dim=-1,keepdims=True)
seq_损失=-seq_损失平均值()

^这将考虑到每行输出序列的长度,以及通过掩蔽它而进行的填充。当我们有成批不同长度的输出时,我认为这特别有用。

好的,我找到了我犯错误的地方。这一切都要感谢你

  • 对于屏蔽版本,输出标签需要有
    -100
    。transoformers图书馆不为您提供这项服务
  • 我犯的一个愚蠢的错误是戴面具。它应该是
    output\u mask=mask[:,1://code>而不是
    :-1
  • 1.使用模型 我们需要将输出的掩码设置为-100。使用克隆非常重要,如下所示:

    labels=output_令牌[“input_id”].clone()
    标签[output_tokens[“attention_mask”]==0]=-100
    输出=模型(
    输入标识=输入标识[“输入标识”],
    注意屏蔽=输入令牌[“注意屏蔽”],
    解码器输入标识=输出标识[“输入标识”],
    解码器\u注意\u掩码=输出\u令牌[“注意\u掩码”],
    标签=标签,
    返回(dict=True)
    
    2.计算损失 因此,复制它的最终方法如下:

    idx=output\u令牌[“input\u id”]
    logits=F.log\u softmax(输出[“logits”],dim=-1)
    掩码=输出令牌[“注意掩码”]
    #转移东西
    output_logits=logits[:,:-1,:]
    label_tokens=idx[:,1::]。取消查询(-1)
    输出屏蔽=屏蔽[:,1:]
    #收集日志和掩码
    选择\u logits=torch.gather(输出\u logits,-1,标记\u令牌)。挤压()
    -选择\u logits[output\u mask==1].mean(),output[“loss”]
    
    然而,上面忽略了一个事实,即这来自两条不同的线路。因此,计算损失的另一种方法可以是:

    seq_loss=(选择_logits*output_mask).sum(dim=-1,keepdims=True)/output_mask.sum(dim=-1,keepdims=True)
    seq_损失平均值()