Python - Как ускорить сходство косинусов с подсчетом массивов - PullRequest
1 голос
/ 06 марта 2019

Мне нужно вычислить функцию подобия косинуса для очень большого набора. Этот набор представляет пользователей и каждого пользователя в виде массива идентификатора объекта. Пример ниже:

user_1 = [1,4,6,100,3,1]
user_2 = [4,7,8,3,3,2,200,9,100]

Если мое понимание верно, чтобы вычислить косинусное сходство, мне сначала нужно создать счетные массивы, чтобы иметь общее представление для каждого из них. Затем мне нужно вычислить функцию подобия косинуса. Для подсчета массивов я имею в виду следующее:

#user_1 array
#                        1,2,3,4,5,6,[7-99],100,[101-200]
user_1_counting_array = [2,0,1,1,0,1,.......,1,.........]
user_2_counting_array = [0,1,2,1,0,0,1,1,1,.,1,.......,1]

(в данном случае точки представляют собой нули)

после того, как я получу это общее представление, я использую функцию подобия косинуса из sklearn.

from scipy import spatial
s = 1 - spatial.distance.cosine(user_1_counting_array, user_2_counting_array)

Проблема в том, что когда я запускаю код, все происходит очень медленно, и у меня более 1 млн пользователей. Я понимаю, что комбинации будет много, но я думаю, что то, как я создаю общее представление, создает очень большое узкое место.

Для полноты, следующее представляет мою реализацию:

from collections import Counter
from scipy import spatial

def fill_array(array, counter):
    for c in counter:
        array[c] = counter[c]
    return array

user_1 = [1,4,6,100,3,1]
user_2 = [4,7,8,3,3,2,200,9,100]

user_1_c = Counter(user_1)
user_2_c = Counter(user_2)

if max(user_1_c) > max(user_2_c):
    max_a = max(user_1_c)+1
else:
    max_a = max(user_2_c)+1

user_1_c_array = [0]*max_a
user_2_c_array = [0]*max_a

fill_array(user_1_c_array, user_1_c)
fill_array(user_2_c_array, user_2_c)

result = 1 - spatial.distance.cosine(user_1_c_array, user_2_c_array)

1 Ответ

1 голос
/ 07 марта 2019

Вот как вы можете получить ваши краткие и краткие векторы косинусного сходства без зацикливания более миллиона записей:

user_1 = [1,4,6,100,3,1]
user_2 = [4,7,8,3,3,2,200,9,100]

# Create a list of unique elements
uniq = list(set(user_1 + user_2))

# Map all unique entrees in user_1 and user_2
duniq = {k:0 for k in uniq}

def create_vector(duniq, l):
    dx = duniq.copy()
    dx.update(Counter(l)) # Count the values
    return list(dx.values()) # Return a list

u1 = create_vector(duniq, user_1)
u2 = create_vector(duniq, user_2)

# u1, u2:

u1 = [2, 0, 1, 1, 1, 0, 0, 0, 0, 1]
u2 = [0, 1, 2, 1, 0, 1, 1, 1, 1, 1]

Затем вы можете подать эти 2 вектора в spatial.distance.cosine

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