任务原理

此次任务是基于RoFormer的微调阶段去做的和Bert模型结构类似,输入句子获取这个句子的向量,然后计算两个句子的余弦距离得到两个句子的相似度。
完成任务的前提希望能对Bert有了解。在此不做介绍。下图是Bert的embedding阶段。它会经过Bert的预训练的Masked LM 和Next Sentence Prediction (NSP)这个2个任务完成。
image.png
所以我们只需要将句子整理成Bret的输入格式,[CLS] 的向量就可以表示这个句子。

实战

  1. 首先加载模型,预训练模型可以自行到GitHub上下载RoFormer_pytorch

image.png

  1. import torch
  2. import torch.nn as nn
  3. from transformers import RoFormerModel
  4. class RoFormerModel(nn.Module):
  5. def __init__(self):
  6. super().__init__()
  7. self.bert = RoFormerModel.from_pretrained("../bert_pretrain")
  8. self.bert.training = False
  9. for param in self.bert.parameters():
  10. param.requires_grad = False
  11. def forward(self, x):
  12. pooled = self.bert(**x).last_hidden_state
  13. pooled = pooled[0][0].reshape(-1, 768)
  14. return pooled
  1. BertTokenizer对句子进行切分

    1. tokenizer = RoFormerTokenizer.from_pretrained("../bert_pretrain")
    2. token = tokenizer("你好, 世界")
    3. print(token)

    输出结果:

    1. {'input_ids': tensor([[ 101, 38183, 13598, 4209, 2229, 1101, 11667, 10120, 1401, 2110,
    2. 33354, 102]]), 'token_type_ids': tensor([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]), 'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]])}

    还可以通过以下方式获取这个句子的token_id

    1. pt_inputs_1 = tokenizer.tokenize(text1)
    2. print(tokenizer.convert_tokens_to_ids(pt_inputs_1))

    输出结果:

    1. [38183, 13598, 4209, 2229, 1101, 11667, 10120, 1401, 2110, 33354]

    这就是Bert微调模型的输入数据,后续输入到BretModel模型中就可以得到表示这个句子的向量了

  2. 项目的完整代码 ```python class SentenceSimilarity():

    def init(self):

    1. self.tokenizer = RoFormerTokenizer.from_pretrained("../bert_pretrain")
    2. self.model = RoFormerModel()
    3. # 预测模式
    4. self.model.eval()

    def sentence_similarity(self, text_1, text_2):

    1. sentence1_token = self.tokenizer(text_1, return_tensors="pt")
    2. sentence2_token = self.tokenizer(text_2, return_tensors="pt")
    3. sentence1_token_vector = self.model(sentence1_token)
    4. sentence2_token_vector = self.model(sentence2_token)
    5. cosine = torch.cosine_similarity(sentence1_token_vector, sentence2_token_vector)
    6. data = {
    7. "txt_1": text_1,
    8. "txt_2": text_2,
    9. "cosine": cosine
    10. }
    11. return data

    def run(self):

    1. text1 = input()
    2. text2 = input()
    3. print(self.sentence_similarity(text1, text2))

if name == ‘main‘: SentenceSimilarity().run()

  1. <a name="cmXTU"></a>
  2. ### 测试效果
  3. 例1:

{‘txt_1’: ‘赵立坚回应英方在华为安插情报人员’, ‘txt_2’: ‘外交部回应英方在华为内部安插间谍’, ‘cosine’: tensor([0.9383])}

例2:

{‘txt_1’: ‘汤加火山喷发首例死者身份确认’, ‘txt_2’: ‘在汤加失联山东教授夫妇确认平安’, ‘cosine’: tensor([0.8254])}

例3:

{‘txt_1’: ‘31省份昨日新增127例本土确诊’, ‘txt_2’: ‘31省份新增本土确诊127例 天津18例’, ‘cosine’: tensor([0.9420])}

例子4:

{‘txt_1’: ‘汤加火山喷发首例死者身份确认’, ‘txt_2’: ‘31省份新增本土确诊127例 天津18例’, ‘cosine’: tensor([0.7073])} ```