【问题标题】:PostgreSQL: perform cosine similarity search over pre-vectorized databasePostgreSQL:对预矢量化数据库执行余弦相似度搜索
【发布时间】:2019-02-25 01:09:50
【问题描述】:

我正在尝试在预矢量化的数据库表上实现余弦相似度搜索(如三元相似度),具有此结构中的对象:

from django.contrib.postgres.fields import ArrayField
from django.db import models

class Information(object):
    vectorized = ArrayField(models.FloatField(default=0.0))  # will contain 512-dimensional vector of floats
    original_data = models.TextField(blank=True)
    original_data_length = models.IntegerField(default=0)

其中属性vectorized 将包含从original_data 生成的512 维向量。


例如,用户输入一个字符串“什么是苹果?”:

  1. 输入转换为512维向量A
  2. A 遍历数据库上的所有对象x(或不遍历)。
  3. 在每次迭代中,在Ax.vectorized 之间计算归一化点积(余弦相似度)(请参阅cosine similarity definition)。
  4. 选择相似度最高的x对象(与A的最高归一化内积),并打印出x.original_data

我为此目的实现了简单的代码,它效率低下,因为它是在框架级别而不是数据库级别执行的,并且为数据库表中的所有对象分配了内存:

from core.models import Information
from numpy import dot  # dot product = inner product limited for real numbers
from numpy.linalg import norm

user_input = user_input  # let this be 512 dimensional vector converted from user input
most_similar = ("", 0)
for item in Information.objects.all():
    similarity = dot(item, user_input)/norm(item, user_input)
    if similarity > most_similar[1]: 
        most_similar = (item.original_data, similarity)
print(most_similar[0])

有什么方法可以实现上面代码的更有效的方法吗?

有没有办法使用 PostgreSQL 做到这一点?

谢谢!

【问题讨论】:

  • 您找到解决方案了吗?我也有同样的问题。

标签: sql django postgresql search cosine-similarity


【解决方案1】:

不可能在 PostgreSQL 中对向量执行余弦相似度。为此,您需要使用像AquilaDBEuclidesDB 这样的矢量数据库。 AquilaDB 支持将 JSON 文档与向量一起存储,我发现这非常适合您的情况。因为,您可以将任何元数据添加到您的 PostgreSQL 数据库中,这些元数据将交叉引用 AquilaDB 中索引的任何向量。他们在wiki page 上有一些不错的教程。

【讨论】:

    【解决方案2】:

    这对我很有用——请注意,它需要预先规范化的向量,总体而言这是一个很好的默认值:

    CREATE OR REPLACE FUNCTION dot_product_norm_d(a double precision[], b double precision[])
    RETURNS double precision AS
    $$
    SELECT sum(result)
    FROM (SELECT (tuple.val1 * tuple.val2) AS result
          FROM (SELECT UNNEST($1) AS val1,
                       UNNEST($2) AS val2,
                       generate_subscripts($1, 1) AS ix) tuple
          ORDER BY ix) inn;
    $$ LANGUAGE SQL IMMUTABLE STRICT;
    

    这里有一个对相关问题有帮助的答案:Vector (array) addition in Postgres

    【讨论】:

      猜你喜欢
      • 2020-08-12
      • 2017-09-27
      • 1970-01-01
      • 2020-07-18
      • 2011-01-01
      • 2013-02-12
      • 2017-12-12
      • 2016-08-09
      相关资源
      最近更新 更多