大模型分不清 9.9 与 9.11 谁大,那 Embedding 模型呢?

这是我今天在维也纳举行的 ICML 会议上被问到的问题。

在茶歇期间,一位 Jina 用户向我提出了一个源自 LLM 社区最近讨论的问题。他问我们 Jina Embeddings 能不能判断 9.11 比 9.9 更小,很多大模型在这个小问题上翻了车。

我说:“老实说,我也不知道。” 他接着详细阐述了这个能力对于他应用的重要性,并暗示:Tokenizer 可能是问题的源头,我若有所思点点头,脑海里开始构思如何用实验来找到答案。

本文我将通过一系列实验来探索 Embeddings、Reranker 模型能否可以准确比较数字。为了验证模型在实际应用中的表现,我还设计了一些具有挑战性的测试用例,包括

  1. 小数比较(例如 0.001 和 0.0001)

  2. 货币金额(例如 和 2.00)

  3. 日期比较(例如 2023-12-31 和 2024-01-01)

  4. 时间比较(例如 23:59 和 00:00)

在这次实验中,我选择了 jina-embeddings-v2-base-en(2023 年 10 月发布)和 Reranker jina-reranker-v2-multilingual(2024 年 6 月发布)作为研究对象,来评估它们在数字理解和比较方面的优势与局限。

让我们拭目以待。

实验装置

完整的实现可以在下面的 Colab 中找到: https://colab.research.google.com/drive/11kUxYhHMLqYhw5HVKEYdHv0EfdZIyBBy?ref=jina-ai-gmbh.ghost.io#scrollTo=G7Cy9zSb2Ukg

本次实验设计非常直观。举个例子,要检查 Embeddings 模型是否理解 1 到 100 之间的数字,步骤如下:

  1. 构建文档:为每个数字生成“字符串文字”文档。

  2. 发送至 Embeddings API: 使用 Embeddings API 获取每个文档的 Embeddings。

  3. 计算余弦相似度:计算每两个文档的余弦相似度,创建一个相似度矩阵。

  4. 绘制散点图:使用散点图可视化结果。相似度矩阵中的每个元素(i, j)映射到一个点,X 轴为(i-j),Y 轴为(i, j)的相似度值。

实验原理是:如果(i-j)的差值为零,即 i 等于 j,那么语义相似度应该是最高的。随着(i-j)的差值增加,相似度应该降低。理想情况下,相似度应该与差值成线性关系。 如果我们观察不到这种线性关系,那么模型可能无法理解数字,并可能产生错误,比如认为 9.11 大于 9.9。

Reranker 模型遵循类似流程。主要区别在于,我们将每个文档逐一设为查询,通过加上 Prompt:“哪一项最接近...”,将所有其他文档作为 documents 进行排名。Reranker API 返回的相关性得分直接作为语义相似度度量。核心实现如下:

def rerank_documents(documents):
    reranker_url = "https://api.jina.ai/v1/rerank"
    headers = {
        "Content-Type": "application/json",
        "Authorization": f"Bearer {token}"
    }

    # 初始化相似度矩阵
    similarity_matrix = np.zeros((len(documents), len(documents)))

    for idx, d in enumerate(documents):
        payload = {
            "model": "jina-reranker-v2-base-multilingual",
            "query": f"what is the closest item to {d}?",
            "top_n": len(documents),
            "documents": documents
        }
    ...

模型能否比较 1 到 100 之间的数字?

左图是 jina-embeddings-v2-base-en 的结果,右图是 jina-reranker-v2-multilingual 的结果。

如何阅读这些图

在继续实验之前,我先解释一下如何正确解读这些图表。首先,我观察到 Embeddings 模型表现不错,而 Reranker 模型表现稍差。那么,这些图表到底展示了什么呢?

X 轴代表索引(i, j)的差值,即 i-j,当我们从文档集中均匀采样 di 和 dj 时。这个差值范围是[-100, 100]。由于文档集是按顺序排列的,即|i-j|越小,di 和 dj 在语义上越接近;i 和 j 越远,di 和 dj 之间的相似度越低。这就是为什么你会看到相似度(由 Y 轴表示)在 X=0 处达到峰值,然后随着 X 值的增大或减小而线性下降。

理想情况下,这应该形成一个尖峰或“^”形状。 然而,情况并非总是如此。如果你固定 X 轴某一点,例如 X = 25,并沿 Y 轴查看,你会发现相似度值在 0.80 到 0.95 之间。这意味着 sim(d_27,d_2)可能是 0.81,而 sim(d_42,d_17)可能是 0.91,尽管它们的差值都是 25。也就是说,即使差值相同,不同文档对的相似度也会不同。

青色趋势线显示了每个 X 值的平均相似度及其标准差。要注意,由于文档集是均匀分布的,确保了连续文档间的间隔相等,相似度应该线性下降。

Embedding 模型图总是对称的,X = 0 时,Y 值最大,为 1.0。这是因为对于 di 和 dj,余弦相似度是对称的,且 cos(0) = 1。

相反,Reranker 模型图总是呈现非对称性,这是因为在重排序模型中,查询与文档的角色存在差异。其最大值未必是 1.0,毕竟 X=0 表示的是我们利用 Reranker 模型去计算“与 4 最接近的一项是什么”和“4”的相关性。倘若深入思考,X = 0 并不一定会致使出现最大的 Y 值。

模型能否比较 -100 到 -1 之间的负数?

我们想测试模型在负数空间中是否能够判断语义相似性,测试数据集是从 -1 到 -100 的负整数字符串,即 documents = [str(-i) for i in range(1, 101)]。这是一个散点图,一同显示了平均值和标准差。

左侧是jina-embeddings-v2-base-en的结果,右侧是jina-reranker-v2-multilingual的结果。

模型能否比较更大间隔的数字 1000, 2000, 3000, ..., 100000?

在这里,我们想测试当比较间隔为 1000 的数字时,模型能否识别语义相似性。documents是由 1 到 100 的数字乘以 1000 构成的字符串列表。documents = [str(i*1000) for i in range(1, 101)]。同上,本散点图一并显示了平均值和标准差。

左侧是jina-embeddings-v2-base-en的结果,右侧是jina-reranker-v2-multilingual的结果。

模型能否比较任意范围内的数字,例如 376, 377, 378, ..., 476?

我们希望测试当比较任意范围内的数字时,模型能否识别语义相似性。我们将数字移动到一个随机范围,documents是由 0 到 100 的数字加上 375 构成的字符串列表。即 documents = [str(i+375) for i in range(1, 101)]

左侧是jina-embeddings-v2-base-en的结果,右侧是jina-reranker-v2-multilingual的结果。

模型能否比较非常大的数字 4294967296, 4294967297, 4294967298, ..., 4294967396?

我们想测试当比较大数字时,模型能否识别语义相似性。我们将范围进一步移动到一个大数字,documents是由 0 到 100 的数字加上 4294967296 构成的字符串列表。即 documents = [str(i+4294967296) for i in range(1, 101)]

左侧是jina-embeddings-v2-base-en的结果,右侧是jina-reranker-v2-multilingual的结果。

模型能否比较 0.0001, 0.0002, 0.0003, ..., 0.1 之间的浮点数?(不固定小数位数)

在这里,我们想测试当比较浮点数时,模型能否识别语义相似性。documents是由 1 到 100 的数字除以 1000 构成的字符串列表。即 documents = [str(i/1000) for i in range(1, 101)]

左侧是jina-embeddings-v2-base-en的结果,右侧是jina-reranker-v2-multilingual的结果。

模型能否比较货币数字 1,1 2, 3,...,3 ..., 100?

在这里,我们想测试当比较货币中的数字时,模型能否识别语义相似性。documents是由 1 到 100 的数字前面加上货币符号$ 构成的字符串列表。即 documents = ['$'+str(i) for i in range(1, 101)]

模型能否比较日期 2024-07-24, 2024-07-25, 2024-07-26, ..., 2024-10-31?

在这里,我们想测试当比较日期格式中的数字时,模型能否识别语义相似性。documents是由当前日期加上 0 到 100 天构成的日期字符串列表。today = datetime.today(); documents = [(today + timedelta(days=i)).strftime('%Y-%m-%d') for i in range(100)]

模型能否比较时间 19:00:07, 19:00:08, 19:00:09,..., 20:39:07?

在这里,我们想测试当比较时间格式中的数字时,模型能否识别语义相似性。documents是由当前时间加上 0 到 100 分钟构成的时间字符串列表。now = datetime.now() documents = [(now + timedelta(minutes=i)).strftime('%H:%M:%S') for i in range(100)]

观察结果

从上述图表中,我们得出了一些观察结果:

Reranker 模型

  • Reranker 模型在处理数字比较问题时,确实有些力不从心。 哪怕是在 1 到 100 这样简单的数字比较内,它的表现也不尽人意。

  • 不过我们在 Reranker 使用了为查询构造的特殊提示词,即最接近 x 的一项是什么,这也可能影响结果。

Embedding 模型

  • Embedding 模型在处理 1 到 100 的小数字或者 -100 到 1 的负数时,表现还算不错,但一旦数字范围扩大,或者涉及到更复杂的数值区间,如浮点数,它的效果就会大打折扣。

  • 我们还会注意到,在每隔 10 的倍数处,算法的表现会出现一些规律性的波动。这可能与分词器将字符串如"10"拆分成"1"和"0"的方式有关。

日期和时间理解

  • Embedding 模型对日期和时间有相当不错的理解,大多数情况下都能准确比较它们。 例如,在日期图表里,我们会发现每 30 或 31 天会出现一个高峰,对应一个月的天数。而在时间的图表中,每 60 分钟也会出现一个高峰,这与一小时的分钟数相匹配。

  • 重排器模型也在一定程度上捕捉到了这种理解。

可视化与“零”的相似性

我们还设计了另一个直观有趣的实验:可视化任意数字与零(原点)之间的语义相似性。将参考点固定为零的嵌入,我们想看看数字与零之间的语义相似性是否随数字增大而线性下降。

Google Colab:https://colab.research.google.com/drive/1S9qZQ0jjdKLNUT2GKqPbU4ogpDe6g9Qh#scrollTo=nvAX2GOpCiRt

我们将查询固定为"0"或"与数字零最接近的数字是什么",并对所有数字进行排序,看看它们的相关性得分是否随着数字的增加而下降。结果如下所示:

左侧是jina-embeddings-v2-base-en的结果,右侧是jina-reranker-v2-multilingual的结果。

关键发现

尽管本文实验设置相对简单,但它揭示了当前模型在数字处理方面的一些基本问题,为我们后续的模型开发提供了宝贵见解。

影响模型数字比较能力的两大关键因素有 分词策略 和 训练数据

首先是分词策略: 词汇表的设计直接影响数字的表示。例如,如果词汇表只包括 0-9 的数字,那么 11 可能被分为单独的 1 和 1,或作为整体的 11,不同的分词方式会导致模型对数值的理解差异。

来源:HuggingFace 上的 Tokenizer Playground。

其次是训练数据: 训练语料的选择对模型的数值推理能力影响重大。比如,如果训练数据主要是软件开发文档或 GitHub Repo,那么模型可能会解释 9.11 大于 9.9 (受语义化版本控制的影响)。

密集检索模型(例如 Embeddings 和 Reranker)的算术能力对于涉及 RAG 以及高级检索和推理的任务至关重要。强大的数字推理能力可以显著提高搜索质量,尤其是在处理 JSON 这样的结构化数据时。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值