Я пытаюсь реализовать поиск сходства по косинусу в предварительно векторизованной таблице базы данных (например, сходство триграмм), имеющей объекты в этой структуре:
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
будет содержать 512 измеренийсозданный вектор из original_data
.
Например, пользователь вводит строку «Что такое яблоко?»:
- Ввод преобразуется в 512-мерныйvector
A
. A
повторяется по всем объектам x
в базе данных (или нет). - На каждой итерации нормализованное скалярное произведение (косинусное сходство) вычисляется между
A
и x.vectorized
(см. определение косинусного сходства ). 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?
Спасибо!