模型简介
模型特点
模型能力
使用案例
🚀 多语言文本语义搜索孪生BERT模型
本项目的模型基于 sentence-transformers
构建,能够将句子和段落映射到384维的密集向量空间,专为语义搜索设计。它在来自不同来源的2.15亿个(问题,答案)对上进行了训练,可有效为给定的段落找到相关文档。
🚀 快速开始
本模型可用于语义搜索,它能将查询/问题和文本段落编码到一个密集向量空间中,为给定的段落找到相关的文档。
✨ 主要特性
- 多语言支持:能够处理多种语言的文本,实现跨语言的语义搜索。
- 高效编码:将句子和段落快速编码为384维的密集向量。
- 精准匹配:在大规模数据集上训练,能准确找到相关文档。
📦 安装指南
如果你已经安装了 sentence-transformers
,使用这个模型会很方便:
pip install -U sentence-transformers
💻 使用示例
基础用法
使用 sentence-transformers
库调用模型:
from sentence_transformers import SentenceTransformer, util
query = "How many people live in London?"
docs = ["Around 9 Million people live in London", "London is known for its financial district"]
# 加载模型
model = SentenceTransformer('SeyedAli/Multilingual-Text-Semantic-Search-Siamese-BERT-V1')
# 编码查询和文档
query_emb = model.encode(query)
doc_emb = model.encode(docs)
# 计算查询和所有文档嵌入之间的点积分数
scores = util.dot_score(query_emb, doc_emb)[0].cpu().tolist()
# 组合文档和分数
doc_score_pairs = list(zip(docs, scores))
# 按分数降序排序
doc_score_pairs = sorted(doc_score_pairs, key=lambda x: x[1], reverse=True)
# 输出段落和分数
for doc, score in doc_score_pairs:
print(score, doc)
高级用法
PyTorch用法(HuggingFace Transformers)
不使用 sentence-transformers
时,你可以按以下方式使用模型:首先将输入传递给Transformer模型,然后对上下文词嵌入应用正确的池化操作。
from transformers import AutoTokenizer, AutoModel
import torch
import torch.nn.functional as F
# 平均池化 - 取所有标记的平均值
def mean_pooling(model_output, attention_mask):
token_embeddings = model_output.last_hidden_state
input_mask_expanded = attention_mask.unsqueeze(-1).expand(token_embeddings.size()).float()
return torch.sum(token_embeddings * input_mask_expanded, 1) / torch.clamp(input_mask_expanded.sum(1), min=1e-9)
# 编码文本
def encode(texts):
# 对句子进行分词
encoded_input = tokenizer(texts, padding=True, truncation=True, return_tensors='pt')
# 计算标记嵌入
with torch.no_grad():
model_output = model(**encoded_input, return_dict=True)
# 执行池化
embeddings = mean_pooling(model_output, encoded_input['attention_mask'])
# 归一化嵌入
embeddings = F.normalize(embeddings, p=2, dim=1)
return embeddings
# 我们想要获取句子嵌入的句子
query = "How many people live in London?"
docs = ["Around 9 Million people live in London", "London is known for its financial district"]
# 从HuggingFace Hub加载模型
tokenizer = AutoTokenizer.from_pretrained("SeyedAli/Multilingual-Text-Semantic-Search-Siamese-BERT-V1")
model = AutoModel.from_pretrained("SeyedAli/Multilingual-Text-Semantic-Search-Siamese-BERT-V1")
# 编码查询和文档
query_emb = encode(query)
doc_emb = encode(docs)
# 计算查询和所有文档嵌入之间的点积分数
scores = torch.mm(query_emb, doc_emb.transpose(0, 1))[0].cpu().tolist()
# 组合文档和分数
doc_score_pairs = list(zip(docs, scores))
# 按分数降序排序
doc_score_pairs = sorted(doc_score_pairs, key=lambda x: x[1], reverse=True)
# 输出段落和分数
for doc, score in doc_score_pairs:
print(score, doc)
TensorFlow用法(HuggingFace Transformers)
与上述PyTorch示例类似,要在TensorFlow中使用该模型,你需要将输入传递给Transformer模型,然后对上下文词嵌入应用正确的池化操作。
from transformers import AutoTokenizer, TFAutoModel
import tensorflow as tf
# 平均池化 - 考虑注意力掩码以进行正确的平均
def mean_pooling(model_output, attention_mask):
token_embeddings = model_output.last_hidden_state
input_mask_expanded = tf.cast(tf.tile(tf.expand_dims(attention_mask, -1), [1, 1, token_embeddings.shape[-1]]), tf.float32)
return tf.math.reduce_sum(token_embeddings * input_mask_expanded, 1) / tf.math.maximum(tf.math.reduce_sum(input_mask_expanded, 1), 1e-9)
# 编码文本
def encode(texts):
# 对句子进行分词
encoded_input = tokenizer(texts, padding=True, truncation=True, return_tensors='tf')
# 计算标记嵌入
model_output = model(**encoded_input, return_dict=True)
# 执行池化
embeddings = mean_pooling(model_output, encoded_input['attention_mask'])
# 归一化嵌入
embeddings = tf.math.l2_normalize(embeddings, axis=1)
return embeddings
# 我们想要获取句子嵌入的句子
query = "How many people live in London?"
docs = ["Around 9 Million people live in London", "London is known for its financial district"]
# 从HuggingFace Hub加载模型
tokenizer = AutoTokenizer.from_pretrained("SeyedAli/Multilingual-Text-Semantic-Search-Siamese-BERT-V1")
model = TFAutoModel.from_pretrained("SeyedAli/Multilingual-Text-Semantic-Search-Siamese-BERT-V1")
# 编码查询和文档
query_emb = encode(query)
doc_emb = encode(docs)
# 计算查询和所有文档嵌入之间的点积分数
scores = (query_emb @ tf.transpose(doc_emb))[0].numpy().tolist()
# 组合文档和分数
doc_score_pairs = list(zip(docs, scores))
# 按分数降序排序
doc_score_pairs = sorted(doc_score_pairs, key=lambda x: x[1], reverse=True)
# 输出段落和分数
for doc, score in doc_score_pairs:
print(score, doc)
🔧 技术细节
以下是该模型使用的一些技术细节:
属性 | 详情 |
---|---|
维度 | 384 |
是否生成归一化嵌入 | 是 |
池化方法 | 平均池化 |
适用的分数函数 | 点积 (util.dot_score )、余弦相似度 (util.cos_sim ) 或欧几里得距离 |
⚠️ 重要提示
使用
sentence-transformers
加载此模型时,会生成长度为1的归一化嵌入。在这种情况下,点积和余弦相似度是等价的,优先使用点积,因为它更快。欧几里得距离与点积成正比,也可以使用。
📚 详细文档
背景
本项目旨在使用自监督对比学习目标,在非常大的句子级数据集上训练句子嵌入模型。我们使用对比学习目标:给定来自一对句子中的一个句子,模型应该从一组随机采样的其他句子中预测出在数据集中实际与之配对的句子。
该模型是在Hugging Face组织的 使用JAX/Flax进行NLP和CV的社区周 期间开发的。它是 使用10亿个训练对训练有史以来最好的句子嵌入模型 项目的一部分。我们借助高效的硬件基础设施(7个TPU v3 - 8)以及谷歌Flax、JAX和云团队成员在高效深度学习框架方面的指导来运行该项目。
预期用途
本模型旨在用于语义搜索,它可以将查询/问题和文本段落编码到一个密集向量空间中,为给定的段落找到相关的文档。
⚠️ 重要提示
该模型的输入词块限制为512个,超过此长度的文本将被截断。此外,该模型仅在最多250个词块的输入文本上进行训练,对于较长的文本可能效果不佳。
训练过程
完整的训练脚本可在当前仓库中找到:train_script.py
。
预训练
我们使用预训练的 nreimers/MiniLM-L6-H384-uncased
模型。有关预训练过程的更多详细信息,请参考该模型的卡片。
训练
我们使用多个数据集的组合来微调模型。总共约有2.15亿个(问题,答案)对。我们根据加权概率对每个数据集进行采样,具体配置在 data_config.json
文件中详细说明。
模型使用 MultipleNegativesRankingLoss 进行训练,采用平均池化、余弦相似度作为相似度函数,缩放比例为20。
数据集 | 训练元组数量 |
---|---|
WikiAnswers WikiAnswers中的重复问题对 | 77,427,422 |
PAQ 维基百科中每个段落的自动生成(问题,段落)对 | 64,371,441 |
Stack Exchange 所有StackExchanges的(标题,正文)对 | 25,316,456 |
Stack Exchange 所有StackExchanges的(标题,答案)对 | 21,396,559 |
MS MARCO 来自Bing搜索引擎的50万个查询的三元组(查询,答案,硬负样本) | 17,579,773 |
GOOAQ: Open Question Answering with Diverse Answer Types 300万个谷歌查询和谷歌特色片段的(查询,答案)对 | 3,012,496 |
Amazon-QA 亚马逊产品页面的(问题,答案)对 | 2,448,839 |
Yahoo Answers Yahoo Answers的(标题,答案)对 | 1,198,260 |
Yahoo Answers Yahoo Answers的(问题,答案)对 | 681,164 |
Yahoo Answers Yahoo Answers的(标题,问题)对 | 659,896 |
SearchQA 14万个问题的(问题,答案)对,每个问题有前5个谷歌片段 | 582,261 |
ELI5 Reddit ELI5(像解释给五岁孩子一样解释)的(问题,答案)对 | 325,475 |
Stack Exchange 重复问题对(标题) | 304,525 |
Quora Question Triplets Quora问题对数据集的(问题,重复问题,硬负样本)三元组 | 103,663 |
Natural Questions (NQ) 10万个真实谷歌查询与相关维基百科段落的(问题,段落)对 | 100,231 |
SQuAD2.0 SQuAD2.0数据集的(问题,段落)对 | 87,599 |
TriviaQA (问题,证据)对 | 73,346 |
总计 | 214,988,242 |







