NLP语义相似度尝试

发布时间 2023-08-15 16:59:22作者: HaruSuzumiya

要实现这么一个需求,预设一个评分标准,然后根据用户的行为或者一段描述进行打分,很自然的想到了这几年很火的NLP,调研了一番做个记录。

1.方案选择

python上有很多很成熟的库来实现,本次选用SentenceTransformers。

2.环境搭建

安装python:太新的版本可能造成各种库不兼容,固使用了python  3.10版本。

安装pip:pip 是一个 Python 包安装与管理工具。

安装pytorch:

打开https://pytorch.org/,会发现有很多版本可以选择,cuda版支持显卡加速

 没有n卡的可以选择cpu版本

 安装SentenceTransformers:

SentenceTransformers是一个可以用于句子、文本和图像嵌入的Python库。它基于PyTorch和Transformers,提供了大量针对各种任务的预训练模型,例如中文BERT、英文RoBERTa等。其中,sentence-transformers (SBert) 预训练模型可以用于计算文本的嵌入并且可以轻松地将它们用于语义文本相似性、语义搜索和同义词挖掘等常见任务 。

pip install -U sentence-transformers
pip install -U transformers

 

3.模型训练

from sentence_transformers import SentenceTransformer, SentencesDataset 
from sentence_transformers import InputExample , evaluation, losses
from torch.utils.data import DataLoader
import os
import pandas as pd
import math
import torch

current_dir=current_dir = os.path.dirname(os.path.abspath(__file__))
model_save_path=os.path.join(current_dir, '', 'chinese_model')
model = SentenceTransformer('distiluse-base-multilingual-cased-v2')
device=torch.device('cuda')
model=model.to(device)

 

初次训练的时候模型会自动下载,大约500m。

准备训练数据:

训练数据可以从日常的使用数据导出为一定格式的excel文件,下面是几个常用的数据类型和损失函数:

CosineSimilarityLoss
输入样本:(sentence1, sentence2, 相似度),这个相似度范围是-1~1(因为求的是余弦相似度)
Contrastiveloss
输入样本:(sentence1, sentence2, label),这里label只能为0或者1
MultipleNegativesRankingLoss
输入样本:(anchor, positive)

加载训练数据:

def load(path):
  df = pd.read_csv(path,encoding='gb18030')
  samples = []
  for idx,item in df.iterrows():
    samples.append((item['sentence1'], item['sentence2'], item['label']))
  return samples
train_path = os.path.join(current_dir, '', 'train.csv')  
valid_path = os.path.join(current_dir, '', 'valid.csv')  
train_data = load(train_path)
valid_data = load(dev_path)

train_datas = []
for i in train_data:
    train_datas.append(InputExample(texts=[i[0], i[1]], label=1))

sentences1,sentences2,scores = [],[],[]
for i in valid_data:
    print(i[2])
    sentences1.append(i[0])
    sentences2.append(i[1])
    scores.append(float(i[2]))
evaluator = evaluation.EmbeddingSimilarityEvaluator(sentences1, sentences2, scores)
evaluator相当于当前模型对于验证数据的一个评估。
训练模型并导出:
train_dataset = SentencesDataset(train_datas, model)
train_dataloader = DataLoader(train_dataset, shuffle=True, batch_size=128)
train_loss = losses.MultipleNegativesRankingLoss(model)
num_epochs=5
warmup_steps = math.ceil(len(train_dataloader) * num_epochs * 0.1) #10% of train data for warm-up
model.fit(train_objectives=[(train_dataloader, train_loss)], epochs=num_epochs, warmup_steps=warmup_steps, 
          evaluator=evaluator, evaluation_steps=1000, output_path=model_save_path)
evaluation_steps:评估步数,是指在训练过程中,模型会在每个evaluation_steps迭代中进行一次评估。

batch_size:单次训练选取的样本量。

batch_size过大优点:

(1)提高了内存利用率,大矩阵乘法并行计算效率提高。

(2)计算的梯度方向比较准,引起的训练的震荡比较小。

(3)跑完一次epoch所需要的迭代次数变小,相同数据量的数据处理速度加快。

 batch_size过大缺点:

 容易内容溢出,想要达到相同精度,epoch会越来越大,容易陷入局部最优,泛化性能差。

 

epochs:训练迭代次数。
warmup_steps:预热步数。在训练神经网络时,预热步数可以帮助模型更好地收敛。预热步数是指在训练过程中,学习率会从0逐渐增加到预设的学习率,这个过程中的一部分步数就是预热步数。 通常的,在训练网络的前期过程中,会选取一个相对较大的学习率以加快网络的收敛速度。而随着迭代优化的次数增多,逐步减小学习率,以保证最终收敛至全局最优解,而不是在其附近震荡或爆炸

4.模型验证

使用新的验证数据集和微调后的新模型进行验证吧~
batch_size