为何传入标签后BART模型输出长度与标签一致?技术问询
问题描述
使用微调后的BART模型生成摘要时发现:传入标签时,模型输出的logits长度始终与标签一致;不传入标签时,输出长度为BART默认的最大序列长度1024。可复现代码如下:
from transformers import AutoModelForSeq2SeqLM, AutoTokenizer model=AutoModelForSeq2SeqLM.from_pretrained('facebook/bart-large-cnn') tokenizer=AutoTokenizer.from_pretrained('facebook/bart-large-cnn') sentence_to_summarize = ['This is a text to summarise. I just went for a walk in the park and saw very large crowds gathering to watch an impromptu football match'] encoded_dict = tokenizer.batch_encode_plus(sentence_to_summarize, return_tensors='pt', max_length=1024, padding='max_length') input_ids = encoded_dict['input_ids'] attention_mask = encoded_dict['attention_mask'] label = tokenizer.encode('I went to the park', return_tensors='pt')
两种测试情况:
- Case 1(不传标签):
output = model(input_ids=input_ids, attention_mask=attention_mask) print(output['logits'].shape)
输出形状为 torch.Size([1, 1024, 50264])
- Case 2(传入标签):
output = model(input_ids=input_ids, attention_mask=attention_mask, labels=label) print(output['logits'].shape)
输出形状为 torch.Size([1, 7, 50264])(7为包含起止token的标签'I went to the park'的长度)
疑问:认为传入标签时模型应仅额外输出loss值,不应影响logits形状,想了解标签长度影响模型输出的原因。
原因分析
这是BART这类Seq2Seq模型的固有设计逻辑,核心差异来自训练模式与推理模式下的decoder输入机制不同:
传入labels时(训练模式):
模型会启用**Teacher Forcing(教师强制)**机制——decoder的输入是标签序列的移位版本(去掉最后一个token,在开头添加<s>起始token)。此时decoder只需要处理与标签长度一致的序列,每一步的输入都是真实标签的前一个token,因此输出的logits长度与标签长度完全匹配,同时模型会计算loss用于参数更新。不传入labels时(推理/生成模式):
模型默认进入自回归生成模式,decoder从<s>token开始,每一步生成的token作为下一步的输入,直到生成<\s>结束token或者达到max_length(BART默认值为1024)。因此此时输出的logits长度会是设置的最大序列长度。
简言之,传入标签是让模型在训练阶段学习预测给定标签的每个位置,不传标签是让模型在生成阶段自主完成完整序列输出,两者的decoder输入逻辑完全不同,导致logits形状出现差异,属于正常现象而非异常。
内容的提问来源于stack exchange,提问作者andrea

