следующий вопрос возникает из предыдущего, который я сделал ранее: Python - Как ускорить сходство косинусов с подсчетом массивов
Я сталкиваюсь с большой сложностью при использовании предложенного решения, в основном, моя реализация занимает много времени для построения матрицы косинусного сходства. Ниже код, который я использую:
import numpy as np
import pandas as pd
import networkx as nx
from scipy import spatial
def compute_other(user_1, user_2):
uniq = list(set(user_1[0] + user_2[0]))
duniq = {k:0 for k in uniq}
u1 = create_vector(duniq, list(user_1[0]))
u2 = create_vector(duniq, list(user_2[0]))
return 1 - spatial.distance.cosine(u1, u2)
# START
distances = spatial.distance.cdist(df[['ARTIST']], df[['ARTIST']], metric=compute_other)
idx_to_remove = np.triu_indices(len(distances))
distances[idx_to_remove] = 0
df_dist = pd.DataFrame(distances, index = df.index, columns = df.index)
edges = df_dist.stack().to_dict()
edges = {k: v for k, v in edges.items() if v > 0}
print('NET inference')
net = nx.Graph()
net.add_nodes_from(df.index)
net.add_edges_from(edges)
Первое, что я замечаю, это то, что я вычисляю полную матрицу и удаляю половину ее, поэтому было бы здорово вычислить только половину
Мне нужно (это будет х2).
Это структура df:
ARTIST
"(75751, 75751, 75751, 75751, 75751, 75751, 75751, 75751, 75751, 75751, 75751, 75751, 75751, 75751, 15053)"
"(55852, 55852, 17727, 17727, 2182)"
"(11446, 11446, 11446, 11446, 11446, 11446, 11446, 11446)"
"(54795,)"
"(22873, 22873, 22873, 22873)"
"(5634, 5634)"
"(311, 18672)"
"(1740, 1740, 1740, 1740, 1746, 15048, 15048, 1740)"
"(1788, 1983, 1788, 1748, 723, 100744, 723, 226, 1583, 12188, 51325, 1748, 75401, 1171)"
"(59173, 59173)"
"(2673, 2673, 2673, 2673, 2673, 2673, 2673, 5634, 5634, 5634)"
"(2251, 4229, 14207, 1744, 16366, 1218)"
"(19703, 1171, 1171)"
"(12877,)"
"(1243, 8249, 2061, 1243, 13343, 9868, 574509, 892, 1080, 1243, 3868, 2061, 4655)"
"(1229,)"
"(3868, 60112, 11084)"
"(15869, 15869, 15869, 15869)"
"(4067, 4067, 4067, 4067, 4067, 4067)"
"(1171, 1171, 1171, 1171)"
"(1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1245, 1195, 1193, 1193, 1193, 1193, 1193, 1193)"
"(723, 723)"
Этот набор данных завершен и может использоваться с кодом, который я разместил. Просто прочитайте его как обычный csv с пандами и примените эту функцию:
import ast
import pandas as pd
df = pd.read_csv('Stack.csv')
df['ARTIST'] = df['ARTIST'].apply(lambda x : ast.literal_eval(x))
Этот код выполняется почти 166
. Я выполняю 8 процессов параллельно на моем 8-ядерном процессоре, каждый процесс вычисляет одну и ту же функцию в своем наборе данных. Честно говоря, я не знаю, является ли это уже самой оптимизированной версией, однако, удаление половины вычислений, как я объяснял ранее, было бы действительно полезным (переход от 166
к 83
).
РЕДАКТИРОВАТЬ: ниже функции create_vector:
def create_vector(duniq, l):
dx = duniq.copy()
dx.update(Counter(l)) # Count the values
return list(dx.values()) # Return a list