如何基于无标签语料微调Sentence-BERT实现抽取式文本摘要?
解决方案:抽取式摘要与Sentence-BERT微调实践
一、用无标签全文-摘要配对微调Sentence-Transformers
无标签的全文-摘要配对数据可以用MultipleNegativesRankingLoss来微调,这个损失不需要额外标签,它会把配对的文本视为正例,同批次其他文本视为负例,让模型学习语义关联。直接上代码:
from sentence_transformers import SentenceTransformer, InputExample, losses from sentence_transformers.datasets import SentencesDataset from torch.utils.data import DataLoader # 加载轻量预训练模型,适合新手快速测试 model = SentenceTransformer('all-MiniLM-L6-v2') # 构造训练数据:每个样本是(全文片段/句子, 对应摘要句子) # 替换成你自己的数据集即可 train_data = [ InputExample(texts=["气候变化导致全球极端天气事件增多,冰川融化速度加快", "气候变化引发极端天气与冰川加速融化"]), InputExample(texts=["人工智能在医疗领域的应用包括疾病诊断、药物研发等多个方面", "AI涉足医疗的疾病诊断与药物研发等领域"]), # 更多样本... ] # 配置训练组件 train_dataset = SentencesDataset(train_data, model) train_dataloader = DataLoader(train_dataset, shuffle=True, batch_size=8) train_loss = losses.MultipleNegativesRankingLoss(model=model) # 启动微调,epochs和batch_size根据你的数据量调整 model.fit( train_objectives=[(train_dataloader, train_loss)], epochs=3, warmup_steps=100, output_path='./fine-tuned-sbert' )
二、微调后计算文本内句子间相似度
微调后的模型可以直接生成句子嵌入,用余弦相似度计算句间关联,代码示例:
from sentence_transformers import util # 加载微调好的模型 model = SentenceTransformer('./fine-tuned-sbert') # 把目标文档拆分成独立句子 document_sentences = [ "气候变化导致全球极端天气事件增多", "冰川融化速度加快,海平面持续上升", "各国正在制定减排政策应对气候危机", "极端高温和暴雨等灾害影响人类生产生活" ] # 生成所有句子的嵌入向量 embeddings = model.encode(document_sentences) # 计算所有句子对的余弦相似度矩阵 similarity_matrix = util.cos_sim(embeddings, embeddings) # 输出每个句子的Top3相似句(排除自身) for i in range(len(document_sentences)): top_scores, top_indices = similarity_matrix[i].topk(3) print(f"句子{i}: {document_sentences[i]}") for score, idx in zip(top_scores, top_indices): if idx != i: print(f" 相似句子{idx}: {document_sentences[idx]} | 相似度: {score:.4f}")
得到相似度后,你可以用TextRank思路排序,或者直接选取与全文最相似的句子作为摘要。
三、替代过时BERT教程的方案
如果之前的BERT教程过时,直接用Hugging Face Transformers最新API即可,不过原生BERT的句嵌入效果不如Sentence-BERT(没经过对比学习优化),这里给个最简示例:
from transformers import BertTokenizer, BertModel import torch from sklearn.metrics.pairwise import cosine_similarity # 加载最新版BERT基础模型和分词器 tokenizer = BertTokenizer.from_pretrained('bert-base-uncased') model = BertModel.from_pretrained('bert-base-uncased') # 获取BERT的<[BOS_never_used_51bce0c785ca2f68081bfa7d91973934]>嵌入作为句子表示 def get_bert_embedding(sentence): inputs = tokenizer(sentence, return_tensors='pt', padding=True, truncation=True) with torch.no_grad(): # 关闭梯度计算,节省资源 outputs = model(**inputs) # 取<[BOS_never_used_51bce0c785ca2f68081bfa7d91973934]>对应的隐藏层输出作为句子嵌入 return outputs.last_hidden_state[:, 0, :].numpy() # 计算两个句子的相似度 sent1_emb = get_bert_embedding("气候变化引发极端天气") sent2_emb = get_bert_embedding("全球极端天气事件增多") similarity = cosine_similarity(sent1_emb, sent2_emb)[0][0] print(f"相似度: {similarity:.4f}")
额外实用建议
- 数据量小的话,直接用预训练Sentence-BERT计算相似度就行,不一定需要微调;数据量大时微调能明显提升效果。
- 可以用公开摘要数据集(比如CNN/Daily Mail)来测试,用Hugging Face
datasets库一键加载即可。 - 抽取式摘要可以结合TF-IDF筛选关键词,再搭配句子相似度排序,效果会更稳定。
内容的提问来源于stack exchange,提问作者Python Beginner
相关产品推荐
相关产品推荐

