开始使用嵌入
'使用嵌入'
查看具有Notebook Companion的教程:
理解嵌入
嵌入是信息的数值表示,例如文本、文档、图像、音频等。该表示捕捉了被嵌入的内容的语义意义,使其在许多行业应用中具有鲁棒性。
给定文本”What is the main benefit of voting?”,句子的嵌入可以用向量空间表示,例如,使用一个包含384个数字的列表(例如[0.84, 0.42, …, 0.02])。由于这个列表捕捉了意义,我们可以进行一些有趣的事情,比如计算不同嵌入之间的距离,以确定两个句子的含义匹配程度。
嵌入不仅限于文本!您还可以创建图像的嵌入(例如,一个包含384个数字的列表),并将其与文本嵌入进行比较,以确定一个句子是否描述了该图像。这个概念在图像搜索、分类、描述等强大系统中得到了应用!
嵌入是如何生成的?名为Sentence Transformers的开源库允许您免费创建最先进的图像和文本嵌入。本博客展示了使用该库的一个示例。
嵌入有什么用?
“[…] 一旦您理解了这个机器学习多功能工具(嵌入),您将能够构建从搜索引擎到推荐系统再到聊天机器人等各种应用。您不需要成为一个具有机器学习专业知识的数据科学家来使用它们,也不需要一个大型标记数据集。” – Dale Markowitz, Google Cloud。
一旦嵌入了一条信息(句子、文档、图像),创造力就开始发挥作用;几个有趣的工业应用使用嵌入。例如,Google搜索使用嵌入将文本与文本和文本与图像进行匹配;Snapchat使用它们在“恰当的时间为恰当的用户提供正确的广告”;Meta(Facebook)将其用于社交搜索。
在从嵌入中获取智能之前,这些公司必须对其信息进行嵌入。嵌入的数据集允许算法快速搜索、排序、分组等。然而,这可能是昂贵且技术复杂的。在本文中,我们使用简单的开源工具展示了嵌入和分析数据集可以有多么容易。
开始使用嵌入
我们将创建一个小型的常见问题解答(FAQ)引擎:接收用户的查询并确定最相似的FAQ是哪个。我们将使用美国社会保障医疗保险FAQ。
但首先,我们需要对我们的数据集进行嵌入(其他文本中使用编码和嵌入这些术语可以互换使用)。Hugging Face Inference API允许我们使用快速的POST调用来嵌入数据集。
由于嵌入捕捉了问题的语义意义,可以比较不同的嵌入并查看它们有多么不同或相似。借助此功能,您可以获得与查询最相似的嵌入,这相当于找到最相似的FAQ。请查看我们的语义搜索教程以获取有关此机制如何工作的更详细解释。
简而言之,我们将:
- 使用推理API嵌入医疗保险FAQ。
- 将嵌入的问题上传到Hub以进行免费托管。
- 将客户的查询与嵌入的数据集进行比较,确定最相似的FAQ。
1. 嵌入数据集
第一步是选择一个现有的预训练模型来创建嵌入。我们可以从Sentence Transformers库中选择一个模型。在这种情况下,让我们使用”sentence-transformers/all-MiniLM-L6-v2″,因为它是一个小而强大的模型。在未来的文章中,我们将研究其他模型及其权衡。
登录到Hub。您必须在您的帐户设置中创建一个写令牌。我们将把写令牌存储在hf_token
中。
model_id = "sentence-transformers/all-MiniLM-L6-v2"
hf_token = "在http://hf.co/settings/tokens中获取您的令牌"
您可以使用https://api-inference.huggingface.co/pipeline/feature-extraction/{model_id}
端点生成嵌入,头部使用{"Authorization": f"Bearer {hf_token}"}
。下面是一个接收包含文本的字典并返回嵌入列表的函数。
import requests
api_url = f"https://api-inference.huggingface.co/pipeline/feature-extraction/{model_id}"
headers = {"Authorization": f"Bearer {hf_token}"}
第一次生成嵌入向量可能需要一些时间(大约20秒)才能从API返回结果。我们使用retry
装饰器(通过pip install retry
安装)来实现这样的功能:如果第一次尝试output = query(dict(inputs = texts))
不成功,则等待10秒并再次尝试三次。这是因为在第一次请求时,模型需要在服务器上进行下载和安装,但随后的调用速度会更快。
def query(texts):
response = requests.post(api_url, headers=headers, json={"inputs": texts, "options":{"wait_for_model":True}})
return response.json()
当前的API没有强制执行严格的速率限制。相反,Hugging Face会将负载均衡地分配到所有可用的资源上,并优先处理请求的稳定流量。如果你需要嵌入多个文本或图像,Hugging Face加速推理API可以加快推理速度,并让你选择使用CPU还是GPU。
texts = ["如何获取替换的医疗保险卡?",
"医疗保险B部分的月费是多少?",
"如何终止我的医疗保险B(医疗保险)?",
"如何注册医疗保险?",
"如果我正在工作并通过雇主获得健康保险,我可以注册医疗保险B吗?",
"如果我已经拥有A部分,如何注册医疗保险B?",
"医疗保险迟报名惩罚是什么?",
"什么是医疗保险,谁可以获得?",
"如何获得医疗保险A和B的保费帮助?",
"医疗保险有哪些不同的部分?",
"我的医疗保险费用会因为我更高的收入而增加吗?",
"什么是TRICARE?",
"如果我有退伍军人福利,我应该注册医疗保险B吗?"]
output = query(texts)
作为响应,你会得到一个嵌套列表。每个列表包含一个FAQ的嵌入向量。模型 “sentence-transformers/all-MiniLM-L6-v2” 将输入问题编码为大小为384的13个嵌入向量。让我们将这个列表转换成一个形状为(13×384)的Pandas DataFrame
。
import pandas as pd
embeddings = pd.DataFrame(output)
它的样子类似于这个矩阵:
[[-0.02388945 0.05525852 -0.01165488 ... 0.00577787 0.03409787 -0.0068891 ]
[-0.0126876 0.04687412 -0.01050217 ... -0.02310316 -0.00278466 0.01047371]
[ 0.00049438 0.11941205 0.00522949 ... 0.01687654 -0.02386115 0.00526433]
...
[-0.03900796 -0.01060951 -0.00738271 ... -0.08390449 0.03768405 0.00231361]
[-0.09598278 -0.06301168 -0.11690582 ... 0.00549841 0.1528919 0.02472013]
[-0.01162949 0.05961934 0.01650903 ... -0.02821241 -0.00116556 0.0010672 ]]
2. 在Hugging Face Hub上免费托管嵌入向量
🤗 Datasets是一个快速访问和共享数据集的库。让我们使用用户界面(UI)将嵌入向量数据集托管到Hub上。然后,任何人都可以使用一行代码加载它。你也可以使用终端来共享数据集;请参考文档中的步骤。在本文档的配套笔记本中,你将能够使用终端来共享数据集。如果你想跳过这一部分,请查看ITESM/embedded_faqs_medicare
仓库中的嵌入FAQs。
首先,我们将从Pandas DataFrame
导出我们的嵌入向量到CSV文件中。你可以以任何你喜欢的方式保存数据集,例如zip或pickle;你不需要使用Pandas或CSV。由于我们的嵌入向量文件不大,我们可以将其存储在CSV文件中,而datasets.load_dataset()
函数可以轻松地推断出它,我们将在下一节中使用这个函数(请参阅Datasets文档),也就是说,我们不需要创建一个加载脚本。我们将以embeddings.csv
作为文件名保存这些嵌入向量。
embeddings.to_csv("embeddings.csv", index=False)
按照以下步骤将embeddings.csv
托管到Hub中。
- 点击Hub UI右上角的用户。
- 使用”新数据集”创建一个数据集。
- 选择数据集的所有者(组织或个人),名称和许可证。选择数据集是否私有或公开。创建数据集。
- 转到”文件”选项卡(如下图所示),然后点击”添加文件”和”上传文件”。
- 最后,拖动或上传数据集,并提交更改。
现在数据集免费托管在Hub上。您(或您想共享嵌入结果的人)可以快速加载它们。让我们看看如何操作。
3. 找到与查询最相似的常见问题
假设一个 Medicare 客户问:“Medicare 如何帮助我?”我们将找出哪个常见问题最适合回答我们的用户查询。我们将创建一个能够表示语义含义的查询嵌入。然后,我们将它与我们的常见问题数据集中的每个嵌入进行比较,以确定在向量空间中与查询最接近的常见问题。
使用pip install datasets
安装🤗 Datasets库。然后,从Hub中加载嵌入数据集并将其转换为PyTorch的FloatTensor
。请注意,这不是操作Dataset
的唯一方式;例如,您还可以使用NumPy、Tensorflow或SciPy(请参阅文档)。如果您想使用真实数据集进行练习,ITESM/embedded_faqs_medicare
存储库包含嵌入的常见问题,或者您可以使用与本博客配套的笔记本。
import torch
from datasets import load_dataset
faqs_embeddings = load_dataset('namespace/repo_name')
dataset_embeddings = torch.from_numpy(faqs_embeddings["train"].to_pandas().to_numpy()).to(torch.float)
我们使用之前定义的查询函数对客户的问题进行嵌入并将其转换为PyTorch的FloatTensor
,以便高效地操作它。请注意,在加载嵌入的数据集之后,我们可以使用Dataset
的add_faiss_index
和search
方法来使用faiss库识别最接近嵌入查询的常见问题。这是一个很好的替代方案的教程。
question = ["Medicare 如何帮助我?"]
output = query(question)
query_embeddings = torch.FloatTensor(output)
您可以使用Sentence Transformers库中的util.semantic_search
函数来确定哪些常见问题与用户的查询最接近(最相似)。此函数使用余弦相似度作为默认函数来确定嵌入之间的接近程度。但是,您也可以使用其他度量两个点在向量空间中的距离的函数,例如点积。
使用pip install -U sentence-transformers
安装sentence-transformers
,并搜索与查询最相似的五个常见问题。
from sentence_transformers.util import semantic_search
hits = semantic_search(query_embeddings, dataset_embeddings, top_k=5)
util.semantic_search
确定了13个常见问题与客户查询的接近程度,并返回一个包含前top_k
个常见问题的字典列表。hits
的样式如下:
[{'corpus_id': 8, 'score': 0.75653076171875},
{'corpus_id': 7, 'score': 0.7418993711471558},
{'corpus_id': 3, 'score': 0.7252674102783203},
{'corpus_id': 9, 'score': 0.6735571622848511},
{'corpus_id': 10, 'score': 0.6505177617073059}]
在corpus_id
中的值允许我们对在第一节中定义的texts
列表进行索引,并获取与之最相似的五个常见问题解答:
print([texts[hits[0][i]['corpus_id']] for i in range(len(hits[0]))])
这里是与客户查询最接近的5个常见问题解答:
['如何获得关于我的Medicare A和B保费的帮助?',
'什么是Medicare,谁可以获得?',
'如何注册Medicare?',
'Medicare的不同部分是什么?',
'由于我的收入较高,我的Medicare保费会更高吗?']
此列表表示与客户查询最接近的5个常见问题解答。太棒了!我们在这里使用了PyTorch和Sentence Transformers作为我们的主要数值工具。然而,我们也可以使用NumPy和SciPy等工具自定义余弦相似度和排名函数。
继续学习的其他资源
如果您想了解更多关于Sentence Transformers库的信息:
- 有关所有新模型和如何下载模型的Hub组织。
- Nils Reimers在推特上比较Sentence Transformer模型与GPT-3 Embeddings的推文。剧透:Sentence Transformers非常棒!
- Sentence Transformers文档,
- Nima的最新研究线程。
感谢阅读!