ранжирование сходства одного вектора с очень большим фреймом данных векторов в panda

#python #pandas #numpy #sklearn-pandas #cosine-similarity

#python #pandas #numpy #sklearn-pandas #косинусное сходство

Вопрос:

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

У меня есть 1 тестовый элемент с 10 атрибутами и 250 000 элементов с 10 атрибутами. Мне нужен список, в котором ранжируются 250 000 элементов. Например, если результирующий список вернулся [10,50,21,11,10000 ….], то элемент с индексом 10 будет ближе всего к моему тестовому элементу, индекс 50 является вторым ближайшим к моему тестовому элементу и т.д.

То, что я пробовал, работает для небольших фреймов данных, но не для больших фреймов данных:

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

similarity_matrix = pd.np.random.rand(4,4) 

#4 items with the first being the test
#0.727048   0.113704    0.886672    0.0345438
#0.496636   0.678949    0.0627973   0.547752
#0.641021   0.498811    0.628728    0.575058
#0.760778   0.955595    0.646792    0.126714 

#creates the cosine similarity matrix 
winner = cosine_similarity(similarity_matrix) 

#I just need the first row, how similar each item is to the test, I'm excluding how similar the test is to the test 
winner = np.argsort(winner[0:1,1:])

#I want to reverse the order and add one so the list matches the original index    
winner = np.flip(winner)  1
  

К сожалению, с 250 000 я получаю следующую ошибку «Ошибка памяти: невозможно выделить 339. GiB для массива с формой (250000, 250000) и типом данных float64 «

Вместо создания матрицы 250000X250000 мне действительно нужна только первая строка. Есть ли другой способ сделать это?

Ответ №1:

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

 x = np.random.rand(5,2)
  

С одним аргументом

 cosine_similarity(x)
array([[1.        , 0.95278802, 0.93496787, 0.45860786, 0.62841819],
       [0.95278802, 1.        , 0.99853581, 0.70677904, 0.8349406 ],
       [0.93496787, 0.99853581, 1.        , 0.74401257, 0.86348853],
       [0.45860786, 0.70677904, 0.74401257, 1.        , 0.979448  ],
       [0.62841819, 0.8349406 , 0.86348853, 0.979448  , 1.        ]])
  

С первым вектором в качестве второго аргумента

 cosine_similarity(x, [x[0]])
array([[1.        ],
       [0.95278802],
       [0.93496787],
       [0.45860786],
       [0.62841819]])
  

Если у вас все еще не хватает памяти, вы можете вычислить расстояние по частям

 chunks = 4
np.concatenate(
    [cosine_similarity(i, [x[0]]) for i in np.array_split(x, chunks)]
)
array([[1.        ],
       [0.95278802],
       [0.93496787],
       [0.45860786],
       [0.62841819]])
  

Комментарии:

1. Ваш ответ сработал, когда я установил df в np.array. Для полноты последующего экспорта списка требуются следующие изменения: winner = cosine_similarity(np_array,[np_array[0]])[1:,:] #take all elements except the first winner = winner[:,0].argsort(axis=0) #sort the index of the array winner = np.flip(winner) 1 #flip the sort order and add one to match the index

Ответ №2:

Вычислите расстояние строка за строкой, например.

 test = np.array([[1, 2, 3]])
big_matrix = np.array([[1, 2, 3], [2, 3, 4]])

#calculate and concat all of them into one
result = np.array([cosine_similarity(test, row.reshape(1, -1)) for row in big_matrix]).reshape(-1, 1)
winner = np.argsort(result)
  

Комментарии:

1. Это кажется многообещающим, но возвращает ошибку «ValueError: ожидаемый 2D-массив, вместо этого получен 1D-массив: массив=[1. 2. 3.].»

2. Это не работает, результат равен 0 0, и в этом примере он должен быть равен 1 0. Я думаю, проблема в том, что тестовый массив должен быть добавлен к строке. Я не уверен, как это сделать в понимании списка, но по нескольким строкам это выглядело бы ближе к этому array1 = np.array([[1, 2, 3]]) array2 = np.array([[1, 2, 3]]) array3 = np.append(array1,array2, axis=0) cosine_similarity(array3)[0,1]