Scipy coo_matrix.max() изменяет атрибут данных

#python #scipy #sparse-matrix

#python #scipy #разреженная матрица

Вопрос:

Я создаю систему рекомендаций, используя библиотеку с открытым исходным кодом LightFM. Эта библиотека требует, чтобы определенные фрагменты данных были в формате разреженной матрицы, в частности scipy coo_matrix. Именно здесь я сталкиваюсь со странным поведением. Это похоже на ошибку, но более вероятно, что я делаю что-то не так.

В принципе, я разрешил LightFM.Dataset построит мне разреженную матрицу, например:

 interactions, weights = dataset.build_interactions(data=_get_interactions_data())
 

Метод build_interactions возвращает «Две матрицы COO: матрицу взаимодействий и соответствующую матрицу весов» — официальный документ LightFM.

Когда я проверяю содержимое этой разреженной матрицы (на практике я использую отладчик), например:

 for i in interactions.data:
    print(i, end=', ')
 

1, 1, 1, 1, 1, ….

Он выводит длинный список из единиц, что указывает на то, что ненулевые элементы разреженной матрицы равны только единицам.

Однако, когда я сначала проверяю максимальное значение разреженной матрицы, это указывает на то, что максимальные значения в разреженной матрице не равны 1, а равны 3. Кроме того, при печати матрицы после этой проверки будет выведен длинный список из 1, 2 и 3. Это код для этого:

 print(interactions.max())
for i in interactions.data:
    print(i, end=', ')
 

3
1, 1, 3, 2, 1, 2, …

Есть идеи, что здесь происходит? Python — 3.6.8. Scipy — 1.5.4. CentOS7.

Спасибо.

Ответ №1:

«Необработанная» coo_matrix может содержать повторяющиеся элементы (повторения одной и той же строки и значений col), но при преобразовании в формат csr для вычислений эти дубликаты суммируются. Он должен делать то же самое, но на месте, чтобы найти это максимальное значение.

 In [9]: from scipy import sparse
In [10]: M = sparse.coo_matrix(([1,1,1,1,1,1],([0,0,0,0,0,0],[0,0,1,0,1,2])))
In [11]: M.data
Out[11]: array([1, 1, 1, 1, 1, 1])
In [12]: M.max()
Out[12]: 3
In [13]: M.data
Out[13]: array([3, 2, 1])
In [14]: M
Out[14]: 
<1x3 sparse matrix of type '<class 'numpy.int64'>'
    with 3 stored elements in COOrdinate format>
 

Трассировка по max коду, который я нахожу используемым sum_duplicates

 In [33]: M = sparse.coo_matrix(([1,1,1,1,1,1],([0,0,0,0,0,0],[0,0,1,0,1,2])))
In [34]: M.data
Out[34]: array([1, 1, 1, 1, 1, 1])
In [35]: M.sum_duplicates?
Signature: M.sum_duplicates()
Docstring:
Eliminate duplicate matrix entries by adding them together

This is an *in place* operation
File:      /usr/local/lib/python3.8/dist-packages/scipy/sparse/coo.py
Type:      method
In [36]: M.sum_duplicates()
In [37]: M.data
Out[37]: array([3, 2, 1])
 

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

1. Я не могу понять, почему это реализовано таким образом. Похоже, что max() на самом деле не находит максимальный элемент разреженной матрицы. В любом случае, спасибо за помощь!

2. Вы всегда можете max data напрямую использовать of . Но если вы не хотите или не ожидаете, что главный операционный директор будет суммировать дубликаты (в какой-то момент), значит, что-то не так с вашим определением матрицы. Если бы я это сделал M.toarray() , я бы увидел [[1,2,3]] , нет [1,1,1,1,1,1] .

3. Да, я считаю, что часть проблемы заключается в непонимании того, как работают эти разреженные матрицы. Все еще немного запутан, но для моих целей я могу позволить LightFM справиться со сложностями. Спасибо за вашу помощь.

4. Я предполагаю, что LightFM помещает один элемент со значением 1 в матрицу для каждого взаимодействия. Это зависит от этого суммирования coo для получения общего количества для каждого взаимодействия. Но у вас есть исходные данные, у меня их нет.