了解 OpenAI 的嵌入(Embeddings)

1. 什么是嵌入?

OpenAI的文本嵌入衡量文本字符串的相关性。嵌入通常用于:

  • 搜索(Search) 其中结果按与查询字符串的相关性排名
  • 聚类分析(Clustering) 其中文本字符串按相似性分组
  • 建议(Recommendations) 建议使用具有相关文本字符串的项目
  • 异常检测(Anomaly detection) 识别相关性不大的异常值
  • 多样性测量(Diversity measurement) 分析相似性分布
  • 分类(Classification) 其中文本字符串按其最相似的标签分类

嵌入是浮点数的向量(列表)。两个向量之间的距离衡量它们的相关性。小距离表示高相关性,大距离表示低相关性。

请访问OpenAI的定价页面,了解嵌入定价。请求根据输入中的令牌数量计费。

2. 如何获取嵌入

要获取嵌入,请将文本字符串与嵌入模型名称(例如 text-embedding-3-small )一起发送到嵌入 API 端点(例如 )。响应将包含一个嵌入(浮点数列表),您可以将其提取、保存在矢量数据库中,并用于许多不同的用例:

下面是输出结果,总结1536个数据:

如果要直接打印嵌入数据,可以使用

打印嵌入数据的长度

为啥 Openai 的嵌入返回的是1536个数据?

ChatGPT 的回答:

OpenAI的嵌入模型(如GPT-3或其它基于Transformer的模型)返回1536个数据点(或称为特征、维度)是由于模型设计和训练过程中的选择。这个数字,1536,指的是嵌入向量的维度,是模型内部表示信息的一个固定大小。

在深度学习和自然语言处理(NLP)中,嵌入是一种将文本(如单词、句子或整个文档)转换为一组数字的技术,使得这些数字能够代表原始文本的某种意义。这些数字通常组织成一个向量。向量的每个维度都是一个特征,可以捕捉一些关于文本的语义信息。

选择1536个维度(或任何特定的维度数)是基于多种因素的考虑:

  1. 性能和精度:更高的维度通常能够捕获更丰富的语义信息,这可能会提高模型在特定任务上的性能。然而,维度的增加也意味着模型的计算成本和存储需求会增加。1536是经过研发和测试后,平衡了性能、计算复杂度和资源需求的结果。
  2. 模型架构:OpenAI的模型是基于Transformer架构设计的,这种架构包括了多个自注意力层和前馈网络,它们的大小(维度)会影响模型能够处理的信息类型和量。1536维可以视为设计决策的一部分,以优化模型对于各种自然语言处理任务的通用性和效率。
  3. 实验和评估:在开发这些模型时,会进行大量的实验来评估不同配置下模型的表现。包括嵌入维度在内的各种参数都会被调整和优化,以找到最佳的设置,既能保持高质量的输出,又能在计算和存储上尽可能高效。

综上所述,1536个数据点的选择反映了在模型设计和开发过程中对于效能、资源和任务广泛性的综合考量。这样的嵌入向量大小旨在为多种应用和任务提供均衡且强大的语义表示能力。

3. 嵌入模型

默认情况下,text-embedding-3-small 嵌入向量的长度为 1536 for  或 text-embedding-3-large 为 3072。您可以通过传入 dimensions 参数来减小嵌入的维度,而不会使嵌入失去其概念表示属性。我们将在嵌入用例部分更详细地介绍嵌入维度。

OpenAI 提供了两个强大的第三代嵌入模型(在模型 ID 中用表示 v3 )。有关更多详细信息,可以阅读嵌入 v3 公告博客文章。

使用量按输入令牌定价,以下是每美元文本页的定价示例(假设每页~800个令牌):

模型每美元页数EVAL MTEB 评估性能最大输入长度
text-embedding-3-small62,50062.3%8191
text-embedding-3-large9,61564.6%8191
text-embedding-ada-00212,50061.0%8191

4. 使用案例

在这里,我们展示了一些具有代表性的用例。我们将使用亚马逊精品评论数据集进行以下示例。

4.1 获取嵌入

该数据集包含截至 2012 年 10 月亚马逊用户留下的 568,454 条食品评论。我们将使用 1,000 条最新评论的子集进行说明。评论是英文的,往往是正面或负面的。每条评论都有一个产品 ID、用户 ID、分数、评论标题(摘要)和评论正文(文本)。例如:

产品ID用户ID得分(SCORE)总结(SUMMARY)文本(TEXT)
B001E4KFG0A3SGXH7AUHU8GW5Good Quality Dog Food 
优质狗粮
I have bought several of the Vitality canned…
我买了几个活力罐头…
B00813GRG4A1D87F6ZCVE5NK1Not as Advertised 
不像广告上所说的那样
Product arrived labeled as Jumbo Salted Peanut…
产品到达时标有巨型盐渍花生…

我们将评论摘要和评论文本合并为一个组合文本。该模型将对此组合文本进行编码并输出单个向量嵌入。

下载后,截取 1000 条记录,文件中不要有空行,保存为 data/fine_food_reviews_1k.csv

4.1.1 加载数据集

您需要安装:pandas、openai、transformers、plotly、matplotlib、scikit-learn、torch (transformer dep)、torchvision 和 scipy。

代码如下:

输出结果:

运行结果:

获取嵌入并保存它们以备将来重用

要从保存的文件加载数据,可以运行以下命令:

5. 减小嵌入尺寸

与使用较小的嵌入相比,使用较大的嵌入(例如将它们存储在矢量存储中以供检索)通常成本更高,并且消耗更多的计算、内存和存储。

我们的两个新嵌入模型都使用一种技术进行训练,该技术允许开发人员权衡使用嵌入的性能和成本。具体来说,开发人员可以缩短嵌入(即从序列末尾删除一些数字),而不会通过传入 dimensions API 参数来使嵌入失去其概念表示属性。例如,在 MTEB 基准测试中, text-embedding-3-large 嵌入可以缩短到 256 的大小,同时仍然优于大小为 1536 的未缩短 text-embedding-ada-002 嵌入。您可以在我们的嵌入 v3 发布博客文章中详细了解更改维度如何影响性能。

通常,建议在创建嵌入时使用该 dimensions 参数。在某些情况下,您可能需要在生成嵌入维度后对其进行更改。手动更改尺寸时,需要确保规范化嵌入的尺寸,如下所示。

动态更改尺寸可实现非常灵活的使用。例如,当使用仅支持最多 1024 个维度的嵌入的向量数据存储时,开发人员现在仍然可以使用我们的最佳嵌入模型 text-embedding-3-large ,并为 dimensions API 参数指定值 1024,这将缩短从 3072 个维度向下的嵌入时间,从而牺牲一些准确性以换取较小的向量大小。

6. 使用嵌入的语义文本搜索

通过嵌入我们的搜索查询,然后找到最相似的评论,我们可以以非常有效的方式以非常低的成本在语义上搜索我们的所有评论。

在这里,我们比较了查询和文档嵌入的余弦相似度,并显示了top_n最佳匹配。

运行结果

运行结果:

我们可以轻松搜索这些评论。为了加快计算速度,我们可以使用一种特殊的算法,旨在通过嵌入更快地进行搜索。

运行结果:

正如我们所看到的,这可以立即带来很多价值。在此示例中,我们展示了能够快速找到交付失败的示例。

运行结果:

运行结果:

7. 带嵌入的零样本分类

在此笔记本中,我们将使用嵌入和零标记数据对评论的情绪进行分类!

我们将正面情绪定义为 4 星和 5 星评论,将负面情绪定义为 1 星和 2 星评论。3 星评价被视为中立,我们不会在此示例中使用它们。

我们将通过嵌入每个类的描述,然后将新样本与这些类嵌入进行比较来执行零样本分类。

7.1 零样本分类

为了执行零样本分类,我们希望在没有任何训练的情况下预测样品的标签。为此,我们可以简单地嵌入每个标签的简短描述,例如正和负,然后比较样本嵌入和标签描述之间的余弦距离。

与样本输入相似度最高的标签是预测标签。我们还可以将预测分数定义为到正标签和负标签的余弦距离之间的差值。该分数可用于绘制精确召回率曲线,该曲线可用于通过选择不同的阈值在精确率和召回率之间选择不同的权衡。

运行结果:

我们可以看到,这个分类器已经表现得非常好了。我们使用了相似性嵌入和最简单的标签名称。让我们尝试通过使用更具描述性的标签名称和搜索嵌入来改进这一点。

运行结果:

使用搜索嵌入和描述性名称可以进一步提高性能。

运行结果:

如上所示,带有嵌入的零样本分类可以产生很好的结果,尤其是当标签比简单的单词更具描述性时。

8. 用户和产品嵌入

我们根据训练集计算用户和产品嵌入,并在看不见的测试集上评估结果。我们将通过绘制用户和产品相似性与评论分数来评估结果。

8.1. 计算用户和产品嵌入

我们只需对训练集中关于同一产品或同一用户撰写的所有评论进行平均来计算这些嵌入。

运行结果:

运行结果:

我们可以看到,大多数用户和产品在 50k 示例中只出现过一次。

8.2. 评估嵌入

为了评估这些建议,我们查看了用户和产品嵌入在看不见的测试集中的评论中的相似性。我们计算用户和产品嵌入之间的余弦距离,这给了我们一个介于 0 和 1 之间的相似性分数。然后,我们通过计算所有预测分数中相似性分数的百分位数,将分数归一化为在 0 和 1 之间平均分配。

通8.2.1 过评分可视化余弦(cosine)相似度

我们将余弦相似度分数按评论分数分组,并绘制每个评论分数的余弦相似性分数分布图。

运行结果:

我们可以观察到一个疲软的趋势,表明用户和产品嵌入之间的相似度得分越高,评论得分就越高。因此,用户和产品嵌入可以弱预测评论分数 – 甚至在用户收到产品之前!

由于该信号的工作方式与更常用的协同滤波不同,因此它可以作为附加功能,略微提高现有问题的性能。

9. 聚类(Clustering)

我们使用一个简单的 k 均值算法来演示如何进行聚类。聚类分析可以帮助发现数据中有价值的隐藏分组

运行结果:

9.1 使用 K-means 查找聚类

我们展示了 K 均值的最简单用法。您可以选择最适合您的用例的集群数量。

运行结果:

运行结果:

二维投影中聚类的可视化。在这次运行中,绿色集群 (#1) 似乎与其他集群完全不同。让我们看看每个集群中的一些示例。

9.2 集群中的文本样本和集群命名

让我们展示每个聚类的随机样本。我们将使用 gpt-4 根据该集群的 5 条评论的随机样本来命名集群。

运行结果:

请务必注意,群集不一定与您打算使用它们的目的相匹配。较大的聚类将专注于更具体的模式,而少量聚类通常将专注于数据中最大的差异。

10. 使用嵌入进行分类

有很多方法可以对文本进行分类。此笔记本分享了一个使用嵌入进行文本分类的示例。对于许多文本分类任务,我们已经看到微调模型比嵌入模型做得更好。请参阅 Fine-tuned_classification.ipynb 中用于分类的微调模型示例。我们还建议使用比嵌入维度更多的示例,我们在这里没有完全实现。

在这个文本分类任务中,我们根据评论文本的嵌入来预测食品评论的分数(1 到 5)。我们将数据集拆分为以下所有任务的训练集和测试集,因此我们可以真实地评估看不见的数据的性能。数据集是在 Get_embeddings_from_dataset Notebook 中创建的。

运行结果:

我们可以看到,该模型已经学会了体面地区分类别。5 星评论总体上表现最佳,这并不奇怪,因为它们是数据集中最常见的。

运行结果:

不出所料,5 星和 1 星评论似乎更容易预测。也许有了更多的数据,可以更好地预测 2-4 颗星之间的细微差别,但人们如何使用中间分数也可能有更多的主观性。

11. 使用嵌入的回归

回归意味着预测一个数字,而不是其中一个类别。我们将根据评论文本的嵌入来预测分数。我们将数据集拆分为以下所有任务的训练集和测试集,因此我们可以真实地评估看不见的数据的性能。数据集是在 Get_embeddings_from_dataset Notebook 中创建的。

我们预测的是评论的分数,即 1 到 5 之间的数字(1 星为负面,5 星为正面)。

运行结果:

运行结果:

我们可以看到,嵌入能够预测分数,每个分数预测的平均误差为 0.53。这大致相当于完美地预测了一半的评论,并减少了一半的一星。

您还可以训练分类器来预测标签,或使用现有 ML 模型中的嵌入来对自由文本要素进行编码。

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部