当前位置:   article > 正文

huggingface的bert简单实现_huggingface bert 输入 attentionmask

huggingface bert 输入 attentionmask

这是个简单的分类任务,我会写出我使用的代码,按照我的习惯,我会添加很多注释,这些注释是我认为的精髓所在,最后我还会顺着数据的转变过程进行一次梳理,毕竟数据的变换就是整个模型的核心任务。

数据是很多评论的句子,要求输出评价是正面还是负面,所以是个二分类任务。

  1. #! pip install transformers datasets
  2. #from google.colab import drive
  3. #drive.mount('/content/drive')
  4. import torch
  5. from datasets import load_dataset
  6. #定义数据集
  7. class Dataset(torch.utils.data.Dataset):
  8. def __init__(self, split):
  9. self.dataset = load_dataset(path='seamew/ChnSentiCorp', split=split)#self.dataset是Dataset类
  10. def __len__(self):
  11. return len(self.dataset)
  12. def __getitem__(self, i):
  13. text = self.dataset[i]['text']
  14. #print(self.dataset[2])后是{'text': '房间太小。其他的都一般。。。。。。。。。', 'label': 0}是字典
  15. label = self.dataset[i]['label']#dataset[i]是字典列表
  16. return text, label
  17. dataset = Dataset('train')#dataset是Dataset类,好像是我定义的那个
  18. print(len(dataset), dataset[0])
  19. from transformers import BertTokenizer
  20. #加载字典和分词工具
  21. token = BertTokenizer.from_pretrained('bert-base-chinese')
  22. token

  1. def collate_fn(data):
  2. sents = [i[0] for i in data]
  3. labels = [i[1] for i in data]
  4. #print(len(data))后是16=batch_size
  5. #print(data)后是[('环境还不错,在西街头上,又有相当的一段距离与吵闹的西街隔离,非常安静. 但是: 1.不能上网,与四星水准不符; 2.同去旅伴抱怨房内有霉味', 1), ('其实我也是曾经在官网上追文看的一员,心急如焚地等待过。当
  6. #编码
  7. data = token.batch_encode_plus(batch_text_or_text_pairs=sents,
  8. truncation=True,
  9. padding='max_length',
  10. max_length=500,
  11. return_tensors='pt',
  12. return_length=True)
  13. #print(data)后data是字典里面的键分别包括'input_ids','attention_mask','token_type_ids','length'值是tensor
  14. #input_ids:编码之后的数字
  15. #attention_mask:是补零的位置是0,其他位置是1
  16. input_ids = data['input_ids']
  17. attention_mask = data['attention_mask']
  18. token_type_ids = data['token_type_ids']
  19. labels = torch.LongTensor(labels)#转成长整形暂时不知道为何
  20. #print(input_ids.shape)是torch.Size([16, 500])
  21. #print(data['length'], data['length'].max())
  22. return input_ids, attention_mask, token_type_ids, labels
  23. #数据加载器
  24. loader = torch.utils.data.DataLoader(dataset=dataset,
  25. batch_size=16,
  26. collate_fn=collate_fn,
  27. shuffle=True,
  28. drop_last=True)
  29. for i, (input_ids, attention_mask, token_type_ids,
  30. labels) in enumerate(loader):
  31. break
  32. print(len(loader))
  33. input_ids.shape, attention_mask.shape, token_type_ids.shape, labels#前三个都是16*500的tensor,labels是1*16的tensor

  1. from transformers import BertModel
  2. #加载预训练模型
  3. pretrained = BertModel.from_pretrained('bert-base-chinese')
  4. #不训练,不需要计算梯度
  5. for param in pretrained.parameters():
  6. param.requires_grad_(False)
  7. #模型试算
  8. out = pretrained(input_ids=input_ids,
  9. attention_mask=attention_mask,
  10. token_type_ids=token_type_ids)
  11. out.last_hidden_state.shape#是torch.Size([16, 500, 768])

  1. #定义下游任务模型
  2. class Model(torch.nn.Module):
  3. def __init__(self):
  4. super().__init__()
  5. self.fc = torch.nn.Linear(768, 2)
  6. def forward(self, input_ids, attention_mask, token_type_ids):
  7. with torch.no_grad():
  8. out = pretrained(input_ids=input_ids,
  9. attention_mask=attention_mask,
  10. token_type_ids=token_type_ids)
  11. #print(out.last_hidden_state[:, 0].shape)是torch.Size([16, 768])
  12. out = self.fc(out.last_hidden_state[:, 0])
  13. #print(out.shape)是torch.Size([16, 2])
  14. out = out.softmax(dim=1)
  15. return out
  16. model = Model()
  17. model(input_ids=input_ids,
  18. attention_mask=attention_mask,
  19. token_type_ids=token_type_ids).shape#是torch.Size([16, 2])

  1. from transformers import AdamW
  2. #训练
  3. optimizer = AdamW(model.parameters(), lr=5e-4)
  4. criterion = torch.nn.CrossEntropyLoss()
  5. model.train()
  6. for i, (input_ids, attention_mask, token_type_ids,
  7. labels) in enumerate(loader):
  8. out = model(input_ids=input_ids,
  9. attention_mask=attention_mask,
  10. token_type_ids=token_type_ids)
  11. #print(out.shape,labels.shape)是torch.Size([16, 2]) torch.Size([16])
  12. loss = criterion(out, labels)
  13. loss.backward()
  14. optimizer.step()
  15. optimizer.zero_grad()
  16. if i % 5 == 0:
  17. out = out.argmax(dim=1)
  18. accuracy = (out == labels).sum().item() / len(labels)
  19. print(i, loss.item(), accuracy)
  20. if i == 25:
  21. break

  1. #测试
  2. def test():
  3. model.eval()
  4. correct = 0
  5. total = 0
  6. loader_test = torch.utils.data.DataLoader(dataset=Dataset('validation'),
  7. batch_size=32,
  8. collate_fn=collate_fn,
  9. shuffle=True,
  10. drop_last=True)
  11. for i, (input_ids, attention_mask, token_type_ids,
  12. labels) in enumerate(loader_test):
  13. if i == 5:
  14. break
  15. print(i)
  16. with torch.no_grad():
  17. out = model(input_ids=input_ids,
  18. attention_mask=attention_mask,
  19. token_type_ids=token_type_ids)
  20. out = out.argmax(dim=1)
  21. correct += (out == labels).sum().item()
  22. total += len(labels)
  23. print(correct / total)
  24. test()

下面开始总结使用bert需要哪些步骤,以及数据的具体变化

最开始就是将数据从数据集中读出

self.dataset = load_dataset(path='seamew/ChnSentiCorp', split=split)#self.dataset是Dataset类

这个dataset是一个列表,里面是一个个字典,包含了所有数据

然后把这个dataset放入数据加载器中,分成批次,比如batch_szie=16,就是16个数据为一组

然后使用tokenizer分词编码形成一个字典

字典里面的键分别包括'input_ids','attention_mask','token_type_ids','length'值是tensor

print(input_ids.shape)是torch.Size([16, 500])

然后将三个torch.Size([16, 500])放入model中得到一个torch.Size([16, 500, 768])

16代表16句话,500是代表每句话分成500个词,不够的就padding补充,768就是一个词的向量

print(out.last_hidden_state[:, 0].shape)是torch.Size([16, 768])

print(out.shape)是torch.Size([16, 2])

在经过softmax后得到两种评价的概率,最后取最大就行了。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/空白诗007/article/detail/938859
推荐阅读
相关标签
  

闽ICP备14008679号