Использование csr_matrix схожести элементов для получения наиболее похожих элементов для элемента X без необходимости преобразования csr_matrix в плотную матрицу - PullRequest
0 голосов
/ 13 сентября 2018

У меня есть данные о покупке ( df_temp ).Мне удалось заменить использование Pandas Dataframe на использование разреженного csr_matrix, потому что у меня есть много продуктов (89000), которые я должен получить из информации о пользовательских элементах (купленных или не купленных), а затем вычислить сходства между продуктами.

Во-первых, я преобразовал Pandas DataFrame в массив Numpy:

 df_user_product = df_temp[['user_id','product_id']].copy()
 ar1 = np.array(df_user_product.to_records(index=False))

Во-вторых, создал coo_matrix , потому что он известен быстрым созданием разреженной матрицы.

 rows, r_pos = np.unique(ar1['product_id'], return_inverse=True)
 cols, c_pos = np.unique(ar1['user_id'], return_inverse=True)
 s = sparse.coo_matrix((np.ones(r_pos.shape,int), (r_pos, c_pos)))

В-третьих, для матричных вычислений лучше использовать csr_matrix или csc_matrix , поэтому я использовал csr_matrix , поскольку у меня есть product_id (s) в строках => более эффективное нарезание строк, чем csc_matrix.

    sparse_csr_mat = s.tocsr()
    sparse_csr_mat[sparse_csr_mat > 1] = 1

Затем я вычислил косинусное сходство между продуктами и поместил результат в сходства :

import sklearn.preprocessing as pp
col_normed_mat = pp.normalize(sparse_csr_mat, axis=1)
similarities = col_normed_mat * col_normed_mat.T

Что такое:

<89447x89447 sparse matrix of type '<type 'numpy.float64'>'
    with 1332945 stored elements in Compressed Sparse Row format>

Теперь я хочу иметь в конце словарь, в котором для каждого товара есть 5 самых похожих товаров.Как это сделать?Я не хочу преобразовывать разреженную матрицу в плотный массив из-за ограничений использования памяти.Но я также не знал, есть ли способ получить доступ к csr_matrix, как мы делаем для массива, где мы проверяем, например, index = product_id и получаем все строки, где index = product_id, таким образом я получу все аналогичные продукты дляproduct_id и сортируйте по значению сходства по косинусу, чтобы получить 5 наиболее похожих.

Например, строка в матрице сходств:

(product_id1, product_id2) 0.45

как фильтровать только поX (= 5 в моем случае) большинство продуктов, похожих на product_id1, без необходимости преобразования матрицы в массив?

Глядя в Stackoverflow , я думаю, что lil_matrix можно использовать для этого случая?как?

Спасибо за помощь!

1 Ответ

0 голосов
/ 17 сентября 2018

Я, наконец, понял, как получить 5 наиболее похожих элементов для каждого продукта, и это с помощью матрицы .tolil(), а затем преобразовать каждую строку в массив с пустым фрагментом и использовать argsort, чтобы получить 5 наиболее похожих элементов.Я использовал решение @hpaulj, предложенное в этой ссылке .

def max_n(row_data, row_indices, n):
        i = row_data.argsort()[-n:]
        # i = row_data.argpartition(-n)[-n:]
        top_values = row_data[i]
        top_indices = row_indices[i]  # do the sparse indices matter?

        return top_values, top_indices, i

, а затем применил его к одному ряду для тестирования:

top_v, top_ind, ind = max_n(np.array(arr_ll.data[0]),np.array(arr_ll.rows[0]),5)

Что мне нужно, так этоtop_indices, которые являются индексами 5 наиболее похожих продуктов, но эти индексы не являются действительными product_id.Я нанёс на карту их, когда построил coo_matrix

rows, r_pos = np.unique(ar1['product_id'], return_inverse=True)

Но как вернуть реальное product_id из индексов?

Теперь, например, у меня есть:

top_ind = [2 1 34 9 123]

Как узнать, 2 соответствуют тому, что product_id, 1 чему и т. Д.?

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