Косинусное сходство для очень большого набора данных - PullRequest
0 голосов
/ 20 декабря 2018

У меня проблемы с вычислением косинусного сходства между большим списком 100-мерных векторов.Когда я использую from sklearn.metrics.pairwise import cosine_similarity, я получаю MemoryError на моем компьютере с 16 ГБ.Каждый массив отлично вписывается в мою память, но я получаю MemoryError во время np.dot() внутреннего вызова

Вот мой пример использования и как я в настоящее время решаю его.

Вот мой родительский вектор 100-мерение, которое мне нужно сравнить с другими 500 000 различных векторов того же измерения (т.е. 100)

parent_vector = [1, 2, 3, 4 ..., 100]

Вот мои дочерние векторы (с некоторыми выдуманными случайными числами для этого примера)

child_vector_1 = [2, 3, 4, ....., 101]
child_vector_2 = [3, 4, 5, ....., 102]
child_vector_3 = [4, 5, 6, ....., 103]
.......
.......
child_vector_500000 = [3, 4, 5, ....., 103]

Моя конечная цель состоит в том, чтобы получить топ-N дочерних векторов (с их именами, такими как child_vector_1 и их соответствующий показатель косинуса), которые имеют очень высокое сходство косинусов с родительским вектором.

Мой текущий подход(который, как я знаю, неэффективен и занимает много памяти):

Шаг 1: Создание супердатафрейма следующей формы

parent_vector         1,    2,    3, .....,    100   
child_vector_1        2,    3,    4, .....,    101   
child_vector_2        3,    4,    5, .....,    102   
child_vector_3        4,    5,    6, .....,    103   
......................................   
child_vector_500000   3,    4,    5, .....,    103

Шаг 2: Используйте

from sklearn.metrics.pairwise import cosine_similarity
cosine_similarity(df)

, чтобы получить парное косинусное сходство между всеми векторами (показано на приведенном выше кадре данных)

Шаг 3: Составьте список кортежей для храненияkey, например child_vector_1, и значение, такое какчисло сходства косинусов для всех таких комбинаций.

Шаг 4: Получите верхний N, используя sort() списка - так что я получу имя дочернего вектора, а также его сходство косинусовоценка с родительским вектором.

PS: я знаю, что это крайне неэффективно, но я не мог придумать лучшего способа быстрее вычислить косинусное сходство между каждым из дочернего вектора и родительского вектора и получить верхнюю-N значения.

Любая помощь будет принята с благодарностью.

Ответы [ 2 ]

0 голосов
/ 11 августа 2019

Это решение безумно быстрое

child_vectors = np.array(child_vector_1, child_vector_2, ....., child_vector_500000)
input_norm = parent_vector / np.linalg.norm(parent_vector, axis=-1)[:, np.newaxis]
embed_norm =  child_vectors/ np.linalg.norm(child_vectors, axis=-1)[:, np.newaxis]
cosine_similarities = np.sort(np.round(np.dot(input_norm, embed_norm.T), 3)[0])[::-1]
paiswise_distances = 1 - cosine_similarities
0 голосов
/ 21 декабря 2018

, даже если ваш (500000, 100) массив (родитель и его дочерние элементы) помещается в память, любая попарная метрика на нем не будет.Причиной этого является то, что попарно метрика, как следует из названия, вычисляет расстояние для любых двух детей.Чтобы сохранить эти расстояния, вам понадобится массив с плавающей точкой (500 000 500 000), который, если мои вычисления верны, займет около 100 ГБ памяти.

К счастью, есть простое решение вашей проблемы.Если я вас правильно понимаю, вы хотите иметь только расстояние между ребенком и родителями, в результате чего вектор длиной 500000 будет легко сохраняться в памяти.

Чтобы сделать это, вам просто нужно предоставить второй аргументto cosine_s Similarity, содержащее только parent_vector

import pandas as pd
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity

df = pd.DataFrame(np.random.rand(500000,100)) 
df['distances'] = cosine_similarity(df, df.iloc[0:1]) # Here I assume that the parent vector is stored as the first row in the dataframe, but you could also store it separately

n = 10 # or however many you want
n_largest = df['distances'].nlargest(n + 1) # this contains the parent itself as the most similar entry, hence n+1 to get n children

Надеюсь, что решит ваш вопрос.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...