我想知道是否有一种方法可以在postgres中获得两个向量的余弦距离。对于存储向量,我使用CUBE数据类型。
下面是我的表格定义:
test=# \d vectors
Table "public.vectors"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+-------------------------------------
id | integer | | not null | nextval('vectors_id_seq'::regclass)
vector | cube | | |
字符串
此外,样本数据如下所示:
test=# select * from vectors order by id desc limit 2;
id | vector
---------+------------------------------------------
2000000 | (109, 568, 787, 938, 948, 126, 271, 499)
1999999 | (139, 365, 222, 653, 313, 103, 215, 796)
型
实际上,我可以为此编写自己的PLPGSql函数,但希望避免这种情况,因为它可能效率不高。
3条答案
按热度按时间8cdiaqws1#
关于你的餐桌
首先,我认为你应该把你的数据类型改为普通数组。
字符串
所以呢
型
将产生以下数据
型
也许不是你期望的答案,但考虑一下
正如你可能已经知道的,计算向量之间的余弦涉及到计算幅值。我认为问题不在于算法,而在于实现;它需要计算平方和平方根,这对于RDBMS来说是昂贵的。
现在,我们来谈谈效率服务器进程在调用数学函数时不承担负载。在PostgreSQL中,数学函数(look here)从C库运行,因此它们非常高效。然而,最终,主机必须分配一些资源来进行这些计算。
在服务器内部实现这些相当昂贵的操作之前,我确实会仔细考虑。但没有一个正确的答案;这取决于你如何使用数据库。例如,如果它是一个有数千个并发用户的生产数据库,我会把这种计算转移到其他地方(中间层或用户应用程序)。但是,如果用户很少,数据库是用于小型研究操作的,那么最好将其实现为存储过程或运行在服务器内的进程,但请记住,这会影响可伸缩性或可移植性。当然,还有更多的考虑因素,比如要处理多少行,或者是否打算触发触发器等。
考虑其他选择
你可以用VB或你选择的语言做一个快速而体面的程序。让客户端应用程序进行繁重的计算,并使用数据库来存储和检索数据。
对于这个特殊的例子,你可以存储单位向量加上幅值。通过这种方式,求任意两个向量之间的余弦值简单地简化为单位向量的点积(只有乘法和除法,没有平方和平方根)。
型
导致
型
即使你必须在服务器内部计算向量的大小,你也会为每个向量计算一次,而不是每次都需要得到两个向量之间的距离。随着行数的增加,这变得更加重要。例如,对于1000个矢量,如果要使用原始矢量分量获得任意两个矢量之间的余弦差,则必须计算999000次幅度。
结论
当我们追求效率时,大多数时候都没有一个规范的答案。相反,我们必须考虑和评估权衡。它总是取决于我们需要实现的最终目标。数据库非常适合存储和检索数据;他们当然可以做其他的东西,但这会增加成本。如果我们能忍受额外的开销,那就好了;否则我们就得考虑其他办法了。
lokaqttq2#
你可以参考我的代码。
字符串
col17t5w3#
在PostgreSQL中,可以使用内置的pg_trgm扩展来计算两个向量之间的余弦相似度,该扩展提供了相似度操作的函数,包括余弦相似度。pg_trgm扩展通常用于涉及文本和向量的相似性计算。
以下是如何使用PostgreSQL和pg_trgm扩展计算两个向量之间的余弦相似度的分步指南:
启用pg_trgm扩展(如果尚未启用):
字符串
准备数据并创建一个表来存储向量。对于本例,我们假设有一个名为vectors_table的表,其中包含vector_id和vector_values列,其中vector_values包含存储为数组的向量值。
型
将矢量数据插入表中。用实际的向量值替换vector_values数组。
型
使用自定义函数计算两个向量之间的余弦相似度。下面是计算余弦相似度的函数:
型
现在你可以使用cosine_similarity函数来计算vectors_table中任意两个向量之间的相似度:
型
此查询将给予一个结果,显示表中所有向量之间的成对余弦相似性,不包括自相似性。
请记住,余弦相似性度量两个向量之间Angular 的余弦,范围从-1到1。值为1表示矢量相同,0表示矢量正交,-1表示它们完全相反。
注意:请相应修改代码。