Я пытаюсь вычислить несколько (5-500) собственных векторов, соответствующих наименьшим собственным значениям больших симметричных квадратных разреженных матриц (до 30000x30000) с ненулевыми значениями менее 0,1%.
В настоящее время я использую scipy.sparse.linalg.eigsh в режиме shift-invert (sigma = 0.0), который, как я выяснил, в различных сообщениях на эту тему является предпочтительным решением. Однако для решения проблемы в большинстве случаев требуется до 1 часа. С другой стороны, функция очень быстрая, если я запрашиваю самые большие собственные значения (в секундах в моей системе), что ожидалось из документации.
Поскольку я больше знаком с Matlab с работы, я попытался решить проблему в Octave, которая дала мне тот же результат, используя eigs (sigma = 0) всего за несколько секунд (sub 10s). Поскольку я хочу выполнить поиск параметров алгоритма, включая вычисление собственных векторов, такой выигрыш во времени был бы также полезен в python.
Сначала я изменил параметры (особенно допуск), но это не сильно изменилось в сроки.
Я использую Anaconda в Windows, но попытался переключить LAPACK / BLAS, используемый scipy (что было очень трудно), с mkl (по умолчанию Anaconda) на OpenBlas (используемый Octave в соответствии с документацией), но не увидел изменений в представление.
Я не смог выяснить, было ли что-то изменить в используемом ARPACK (и как)?
Я загрузил тестовый пример для кода ниже в следующую папку dropbox: https://www.dropbox.com/sh/l6aa6izufzyzqr3/AABqij95hZOvRpnnjRaETQmka?dl=0
В питоне
import numpy as np
from scipy.sparse import csr_matrix, csc_matrix, linalg, load_npz
M = load_npz('M.npz')
evals, evecs = linalg.eigsh(M,k=6,sigma=0.0)
В октаве:
M=dlmread('M.txt');
M=spconvert(M);
[evecs,evals] = eigs(M,6,0);
Любая помощь ценится!
Некоторые дополнительные опции, которые я опробовал на основе комментариев и предложений:
Октава:
eigs(M,6,0)
и eigs(M,6,'sm')
дай мне тот же результат:
[1.8725e-05 1.0189e-05 7.5622e-06 7.5420e-07 -1.2239e-18 -2.5674e-16]
пока eigs(M,6,'sa',struct('tol',2))
сходится к
[1.0423 2.7604 6.1548 11.1310 18.0207 25.3933]
намного быстрее, но только если значения допуска выше 2, иначе оно не сходится вообще и значения сильно отличаются.
Python:
eigsh(M,k=6,which='SA')
и eigsh(M,k=6,which='SM')
оба не сходятся (ошибка ARPACK при отсутствии достигнутой конвергенции). Только eigsh(M,k=6,sigma=0.0)
дает некоторые собственные значения (после почти часа), которые отличаются от октавы для самых маленьких (найдено даже 1 дополнительное небольшое значение):
[3.82923317e-17 3.32269886e-16 2.78039665e-10 7.54202273e-07 7.56251500e-06 1.01893934e-05]
Если допуск достаточно высок, я также получаю результаты eigsh(M,k=6,which='SA',tol='1')
, которые приближаются к другим полученным значениям
[4.28732218e-14 7.54194948e-07 7.56220703e-06 1.01889544e-05, 1.87247350e-05 2.02652719e-05]
снова с другим количеством маленьких собственных значений. Время вычислений все еще почти 30 минут. В то время как различные очень маленькие значения могут быть понятны, так как они могут представлять кратные 0, различная множественность сбивает с толку меня.
Кроме того, в SciPy и Octave, похоже, есть некоторые принципиальные различия, которые я пока не могу понять.