Я намагаюся обчислити декілька (5-500) власних векторів, що відповідають найменшим власним значенням великих симетричних квадратних розріджених матриць (до 30000x30000), причому менше 0,1% значень є ненульовими.
В даний час я використовую scipy.sparse.linalg.eigsh у режимі зсуву-інвертування (сигма = 0,0), що я з'ясував, використовуючи різні пости в темі, є кращим рішенням. Однак для вирішення проблеми в більшості випадків потрібно до 1 год. З іншого боку, функція дуже швидка, якщо я запитую найбільші власні значення (підсекунди в моїй системі), що очікувалося з документації.
Оскільки я більше знайомий з Матлабом з роботи, я спробував вирішити проблему в Octave, що дало мені той же результат, використовуючи eigs (sigma = 0) протягом декількох секунд (суб 10с). Оскільки я хочу зробити розгортку параметрів алгоритму, включаючи обчислення власного вектора, такий виграш часу буде чудово мати і в python.
Я спершу змінив параметри (особливо толерантність), але це не сильно змінилося на шкалі часу.
Я використовую Anaconda в Windows, але спробував переключити LAPACK / BLAS, використовуваний scipy (що був величезним болем) з mkl (анаконда за замовчуванням) на OpenBlas (використовується Octave згідно з документацією), але не зміг змінити виконання.
Я не зміг зрозуміти, чи щось змінити вживаний ARPACK (і як)?
Я завантажив тестовий зразок коду нижче до такої папки-папки: https://www.dropbox.com/sh/l6aa6izufzyzqr3/AABqij95hZOvRpnnjRaETQmka?dl=0
У Python
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, яких я поки не можу з’ясувати.