Embedding 模型微调:领域效果不够时的最后一招

王老师476 阅读

如果你的领域比较垂直(比如法律、医疗、代码),通用 embedding 模型可能不够用。此时有两种选择:换更大模型,或者微调。这篇文章记录我微调 bge-m3 的完整过程。

什么时候值得微调

  • 通用模型在你的领域测试集上 Recall@10 < 0.7
  • 你有一定量的领域数据(几百到几千条查询-文档对)
  • 领域术语多、语义特殊(比如"退货"在电商和物流语境里语义不同)

如果没有以上条件,先别微调,调分块和检索参数收益更大。

训练数据怎么造

最简单有效的方案是合成数据

Python
# 用 LLM 生成 查询-文档 对 pairs = [] for doc in domain_docs: q = llm(f"基于以下文档生成 3 个相关问题:\n{doc}") pairs.append((q, doc)) # 正样本 # 负样本:随机取其他文档,或让 LLM 生成难负例

正样本是"问题-对应文档",负样本是"问题-不相关文档"。难负例(表面相似但实际无关)对训练效果最关键。

微调

用 sentence-transformers 的 MultipleNegativesRankingLoss:

Python
from sentence_transformers import SentenceTransformer, losses, InputExample from torch.utils.data import DataLoader model = SentenceTransformer("BAAI/bge-m3") loss = losses.MultipleNegativesRankingLoss(model) # 训练 3-5 个 epoch,学习率 2e-5

  1. epoch 别太多。embedding 微调很容易过拟合,3 个 epoch 和 10 个 epoch 效果差别很大,我试过 10 个 epoch 反而比通用模型还差。

  2. 混合训练。用领域数据微调时,最好混入一部分通用数据,防止领域偏移太狠。

  3. 评估要分开。微调前后用同一套测试集对比,别用训练集里的数据评估,那肯定虚高。

实测效果:在内部代码文档场景,微调 1000 对数据后,Recall@10 从 0.72 提到 0.88。但说实话,这个提升主要来自"术语对齐"——如果领域术语不多,微调收益有限。

微调是最后的手段,先把其他环节调好再考虑它。

评论0

还没有评论,来抢沙发~