Я работаю над рекомендациями продукта.
Мой набор данных выглядит следующим образом (Пример, полный набор содержит более 110 000 строк и более 80000 уникальных product_id ):
user_id product_id
0 0E3D17EA-BEEF-493 12909837
1 0FD6955D-484C-4FC8-8C3F 12732936
2 CC2877D0-A15C-4C0A Gklb38
3 b5ad805c-f295-4852 12909841
4 0E3D17EA-BEEF-493 12645715
Я хочу рассчитать косинусное сходство между продуктами на основе приобретенных продуктов на пользователя.
Почему? Мне нужен конечный результат:
список 5 самых похожих товаров для каждого product_id .
Итак, я подумал, что первое, что мне нужно сделать, - это преобразовать фрейм данных в этот формат:
где у меня одна строка на user_id, а столбцы - product_ids. Если пользователь купил product_id X, то соответствующая строка столбца будет содержать значение 1, иначе 0.
Я сделал это с помощью функции кросс-таблицы панд данных.
crosstab_df = pd.crosstab(df.user_id, df.product_id).astype('bool').astype('int')
После этого я рассчитал сходство между продуктами.
def calculate_similarity(data_items):
"""Calculate the column-wise cosine similarity for a sparse
matrix. Return a new dataframe matrix with similarities.
"""
# create a scipy sparse matrix
data_sparse = sparse.csr_matrix(data_items)
#pairwise similarities between all samples in data_sparse.transpose()
similarities = cosine_similarity(data_sparse.transpose())
#put the similarities between products in a dataframe
sim = pd.DataFrame(data=similarities, index= data_items.columns, columns= data_items.columns)
return sim
similarity_matrix = calculate_similarity(crosstab_df)
Я знаю, что это неэффективно, потому что кросс-таблица не работает хорошо, когда есть много строк и много столбцов, что я должен обработать. Итак, я подумал о том, чтобы вместо использования Crosstab DataFrame, я должен использовать scipy разреженную матрицу , поскольку это ускоряет вычисления (вычисления подобия, нормализацию векторов), потому что входные данные будут массивом, а не кадром данных.
Однако я не знал, как это сделать. Мне также нужно отслеживать каждый столбец, которому соответствует product_id, чтобы я мог получить наиболее похожие product_ids для каждого product_id.
Я нашел в других вопросах ответы, которые:
scipy.sparse.csr_matrix(df.values)
можно использовать, но в моем случае, я думаю, я могу использовать его только после применения кросс-таблицы .. пока я хочу избавиться от шага кросс-таблицы.
Кроме того, люди предложили использовать scipy coo_matrix , но я не понял, как я могу применить его в моем случае для достижения желаемых результатов.
Я ищу эффективное для памяти решение , поскольку начальный набор данных может увеличиваться на тысячи строк и сотни тысяч product_id ..