如何从Hugging Face pipeline获取损失以微调问答模型?
如何获取QA模型的损失并进行微调
我使用deepset/roberta-base-squad2模型做问答任务时,能通过pipeline得到预测结果,但不知道怎么计算损失来微调模型。比如测试案例中,真实答案是freedom to the user,但模型预测出了gives freedom to the user。
问答任务的损失计算和文本分类不同,QA模型需要的是答案在上下文文本中的起始和结束token位置作为标签,而非直接传入答案文本。以下是具体实现步骤:
1. 导入依赖并加载模型、分词器
import torch from transformers import AutoModelForQuestionAnswering, AutoTokenizer model_name = "deepset/roberta-base-squad2" model = AutoModelForQuestionAnswering.from_pretrained(model_name) tokenizer = AutoTokenizer.from_pretrained(model_name)
2. 定义输入数据与真实答案
question = "Why is model conversion important?" context = "The option to convert models between FARM and transformers gives freedom to the user and let people easily switch between frameworks." true_answer = "freedom to the user"
3. 编码输入并对齐真实答案的token位置
首先用分词器编码问题和上下文,同时获取offset_mapping来对齐原始文本和token的位置关系,再通过原始文本中真实答案的索引,找到对应的token位置:
# 编码输入,返回offset_mapping用于对齐原始文本与token encoding = tokenizer(question, context, return_tensors="pt", return_offsets_mapping=True) offset_mapping = encoding.pop("offset_mapping") # 模型不需要该参数,单独取出 # 找到真实答案在原始context中的起止索引 start_idx = context.find(true_answer) end_idx = start_idx + len(true_answer) # 遍历offset_mapping,找到对应token的起止位置 start_positions = None end_positions = None # 先找精确匹配 for idx, (token_start, token_end) in enumerate(offset_mapping[0]): if token_start == start_idx: start_positions = idx if token_end == end_idx: end_positions = idx # 若没有精确匹配,找包含答案的token位置 if start_positions is None: for idx, (token_start, token_end) in enumerate(offset_mapping[0]): if token_start <= start_idx < token_end: start_positions = idx break if end_positions is None: for idx, (token_start, token_end) in enumerate(offset_mapping[0]): if token_start < end_idx <= token_end: end_positions = idx break
4. 计算损失并执行反向传播
将找到的start_positions和end_positions传入模型,即可得到损失并进行微调:
# 加入标签参数 encoding["start_positions"] = torch.tensor([start_positions]) encoding["end_positions"] = torch.tensor([end_positions]) # 前向传播计算损失 outputs = model(**encoding) loss = outputs.loss # 初始化优化器并执行反向传播 optimizer = torch.optim.AdamW(model.parameters(), lr=5e-5) loss.backward() optimizer.step()
说明
QA模型的forward方法会基于预测的起止位置logits,与传入的真实start_positions、end_positions计算交叉熵损失。批量处理时,只需将每个样本的起止位置整理成批量tensor即可。
内容的提问来源于stack exchange,提问作者Penguin
相关产品推荐
相关产品推荐

