暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Kaggle知识点:使用BERT完成阅读理解

Coggle数据科学 2022-02-16
1680

文本问答是常见的NLP任务,文本介绍了如何使用Bert模型完成文本问答,并给出了各自的步骤。

任务介绍

机器阅读理解和问答任务(QA)指的是给定一个问题和一个或多个文本,训练QA模型可以根据文本找出答案,标准答案一般与文本中的答案完全匹配。

Finetune原理

模型的输入句子对由问题和包含答案的文本组成,并有特殊分隔符[SEP]
分隔。同其他下游任务一样,输入序列的第一个token为特殊分类嵌入[CLS]
,同时输入序列为token embeddings,segmentation embeddings,以及position embedding之和。

步骤1:数据处理

首先读取选中的模型,并利用tokenizer对输入的文本和问题进行处理。

from transformers import BertTokenizerFast, BertForQuestionAnswering

tokenizer = BertTokenizerFast.from_pretrained('hfl/chinese-bert-wwm-ext')
model = BertForQuestionAnswering.from_pretrained('hfl/chinese-bert-wwm-ext')

train_encodings = tokenizer(list(train_df['text'])[:], list(train_df['question_text'])[:], 
                            return_tensors='pt', truncation=True, padding=True,
                           max_length=512)

生成训练数据中答案的开始/结束位置:

train_encodings['start_positions'] = [train_encodings.char_to_token(idx, x) for idx, x in enumerate(train_df['index_start'].values[:])]
train_encodings['end_positions'] = [train_encodings.char_to_token(idx, x-1for idx, x in enumerate(train_df['index_end'].values[:])]

步骤2:定义数据集

根据Pytorch框架定义模型数据集,直接传入数据集,对文本和答案的开始/结束位置进行转换即可。

import torch
from torch.utils.data import Dataset, DataLoader, TensorDataset
    
import torch

class SquadDataset(torch.utils.data.Dataset):
    def __init__(self, encodings):
        self.encodings = encodings

    def __getitem__(self, idx):
        return {key: torch.tensor(val[idx]) for key, val in self.encodings.items()}

    def __len__(self):
        return len(self.encodings.input_ids)

train_dataset = SquadDataset(train_encodings)

步骤3:进行训练

根据定义好的数据集和模型直接进行训练即可,此时模型正向传播需要传入答案的开始/结束位置。

from torch.utils.data import DataLoader
from transformers import AdamW

device = torch.device('cuda'if torch.cuda.is_available() else torch.device('cpu')
model.to(device)
model.train()

train_loader = DataLoader(train_dataset, batch_size=8, shuffle=True)
optim = AdamW(model.parameters(), lr=5e-5)

for epoch in range(3):
    for idx, batch in enumerate(train_loader):
        optim.zero_grad()
        input_ids = batch['input_ids'].to(device)
        attention_mask = batch['attention_mask'].to(device)
        start_positions = batch['start_positions'].to(device)
        end_positions = batch['end_positions'].to(device)
        outputs = model(input_ids, attention_mask=attention_mask, start_positions=start_positions, end_positions=end_positions)
        loss = outputs[0]
        loss.backward()
        optim.step()

        start_pred = torch.argmax(outputs['start_logits'], dim=1)
        end_pred = torch.argmax(outputs['end_logits'], dim=1)
        acc1 = ( (start_pred == start_positions).sum() / len(start_pred) ).item()
        acc2 = ( (end_pred == end_positions).sum() / len(start_pred) ).item()

        if idx % 10 == 0:
            print(loss.item(), acc1, acc2)
            with codecs.open('log.log''a'as up:
                up.write('{3}\t{0}\t{1}\t{2}\n'.format(loss.item(), acc1, acc2, 
                                                       str(epoch) + '/' + str(idx) +'/'+ str(len(train_loader))))

model.eval()

学习交流群已成立
学习推荐系统,算法竞赛,组队参赛
添加👇微信拉你进群
加入了之前的社群不需要重复添加~

文章转载自Coggle数据科学,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论