#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 для получения общего количества для каждого взаимодействия. Но у вас есть исходные данные, у меня их нет.