如何用单句带标签数据微调Sentence Transformer模型?
问题
我正在尝试微调Sentence Transformer模型,现有数据集包含以下列:
- raw_text - 原始文本片段
- label - 文本对应的标签,取值为True/False(或1/0)
我的需求是:微调后让所有标签为True的句子在向量空间中的嵌入比标签为False的句子更接近。
我查阅了Sentence-Transformers的损失函数文档,但仍困惑于该选哪种损失函数。原本倾向于一类需要锚点、正样本、负样本对的损失(对应图示),但我的数据并没有这类样本对,所以不确定这个选择是否正确。
请问用Sentence Transformer库中的现有损失函数能不能实现我的需求?目前我有一段可运行的代码:
from sentence_transformers import SentenceTransformer, InputExample, SentencesDataset, LoggingHandler, losses from torch.utils.data import DataLoader import pandas as pd # Load a pre-trained Sentence Transformer model # model = SentenceTransformer('stsb-roberta-base') #Hugging face says this model produces embeddings of low quality model = SentenceTransformer('all-mpnet-base-v2') # Assume 'transportation_data' is your dataset containing 'page_raw_text' and 'is_practical' columns data = pd.DataFrame({'text': train_data['page_raw_text'], 'label': train_data['label']}) # Create InputExample objects examples = [InputExample(texts=[txt], label=label) for txt, label in zip(data['text'], data['label'])] # Create a DataLoader object and a Loss model train_dataset = SentencesDataset(examples=examples, model=model) train_dataloader = DataLoader(train_dataset, shuffle=True, batch_size=8) train_loss = losses.BatchAllTripletLoss(model=model) # Define your training arguments num_epochs = 10 evaluation_steps = 1 model.fit(train_objectives=[(train_dataloader, train_loss)], epochs=num_epochs,evaluation_steps=1)
解决方案
完全可以用Sentence Transformer库的现有损失函数实现你的需求,推荐两种方向的方案:
1. 适合的损失函数选择
(1)SoftmaxLoss
把任务当成二分类任务训练,让模型学习区分True/False类的嵌入分布,同类样本的嵌入会自然聚集。它不需要手动构造正负样本对,直接用单条文本的标签即可训练,逻辑直观且容易收敛。
(2)BatchHardTripletLoss/BatchAllTripletLoss
你当前使用的BatchAllTripletLoss其实可以适配你的数据:它会在每个batch内部自动挖掘锚点(任意样本)、正样本(同标签)和负样本(不同标签),只要batch中同时包含True和False样本,就能自动计算三元组损失,推动同标签样本嵌入靠近、异标签远离。其中BatchHardTripletLoss会选择每个batch里最难的正负样本,训练效果可能更稳定。
2. 优化后的代码示例
方案一:SoftmaxLoss实现
from sentence_transformers import SentenceTransformer, InputExample, SentencesDataset, losses from torch.utils.data import DataLoader import pandas as pd # 加载预训练模型 model = SentenceTransformer('all-mpnet-base-v2') # 构造数据集,将布尔标签转为整数(0/1) data = pd.DataFrame({'text': train_data['page_raw_text'], 'label': train_data['label'].astype(int)}) # 创建InputExample对象 examples = [InputExample(texts=[txt], label=label) for txt, label in zip(data['text'], data['label'])] train_dataset = SentencesDataset(examples=examples, model=model) # 适当增大batch size,提升模型学习效率 train_dataloader = DataLoader(train_dataset, shuffle=True, batch_size=16) # 初始化SoftmaxLoss,指定类别数为2 train_loss = losses.SoftmaxLoss( model=model, sentence_embedding_dimension=model.get_sentence_embedding_dimension(), num_labels=2 ) # 训练模型 num_epochs = 10 model.fit( train_objectives=[(train_dataloader, train_loss)], epochs=num_epochs, evaluation_steps=100 # 增大评估步长,减少冗余计算 )
方案二:优化TripletLoss使用
from sentence_transformers import SentenceTransformer, InputExample, SentencesDataset, losses from torch.utils.data import DataLoader import pandas as pd model = SentenceTransformer('all-mpnet-base-v2') data = pd.DataFrame({'text': train_data['page_raw_text'], 'label': train_data['label']}) examples = [InputExample(texts=[txt], label=label) for txt, label in zip(data['text'], data['label'])] train_dataset = SentencesDataset(examples=examples, model=model) # 增大batch size,确保每个batch内有足够的正负样本 train_dataloader = DataLoader(train_dataset, shuffle=True, batch_size=16) # 改用BatchHardTripletLoss,训练效果更稳定 train_loss = losses.BatchHardTripletLoss(model=model) num_epochs = 10 model.fit( train_objectives=[(train_dataloader, train_loss)], epochs=num_epochs, evaluation_steps=100 )
3. 关键注意事项
- 无论选择哪种损失,都建议增大batch size(16-32区间最佳),让损失函数更好地挖掘样本间的关系;
- 训练后可以通过计算同标签样本的平均余弦相似度、异标签样本的平均余弦相似度,来验证聚类效果是否符合预期;
- SoftmaxLoss更适合二分类场景,TripletLoss类更侧重嵌入空间的距离约束,可根据实际需求选择。
内容的提问来源于stack exchange,提问作者rushikesh maheshwari
相关产品推荐
相关产品推荐

