ऑक्टेव की तुलना में SciPy में 100x से अधिक धीमे, बड़े विरल मैट्रिक्स के सबसे छोटे eigenvectors का पता लगाना


12

मैं शून्य (शून्य से 30000x30000 तक) बड़े सममित वर्ग विरल-मैट्रिस (30000x30000 तक) के सबसे छोटे eigenvalues ​​के अनुरूप कुछ (5-500) eigenvectors को गैर-शून्य होने की कोशिश कर रहा हूं।

मैं वर्तमान में scipy.sparse.linalg.eigsh इन शिफ्ट-इनवर्ट मोड (सिग्मा = 0.0) का उपयोग कर रहा हूं, जिसे मैंने इस विषय पर विभिन्न पदों के माध्यम से समझा है। हालांकि, ज्यादातर मामलों में समस्या को हल करने में 1h तक का समय लगता है। दूसरी ओर, फ़ंक्शन बहुत तेज़ है, अगर मैं सबसे बड़ा ईगेंवल्यूज़ (अपने सिस्टम पर सब सेकंड) मांगता हूं, जो प्रलेखन से अपेक्षित था।

चूंकि मैं काम से मैटलैब से अधिक परिचित हूं, इसलिए मैंने ऑक्टेव में समस्या को हल करने की कोशिश की, जिसने मुझे कुछ ही सेकंड (10 के दशक) में ईग्स (सिग्मा = 0) का उपयोग करके एक ही परिणाम दिया। चूँकि मैं eigenvector संगणना सहित एल्गोरिथ्म के एक पैरामीटर स्वीप करना चाहता हूं, उस तरह का समय लाभ अजगर में भी होना बहुत अच्छा होगा।

मैंने पहले पैरामीटर (विशेष रूप से सहिष्णुता) को बदल दिया, लेकिन वह टाइमस्केल्स पर बहुत अधिक नहीं बदला।

मैं विंडोज पर एनाकोंडा का उपयोग कर रहा हूं, लेकिन mkl (डिफ़ॉल्ट एनाकोंडा) से OpenBlas (प्रलेखन के अनुसार ऑक्टेव द्वारा उपयोग किया गया) से स्केपी द्वारा इस्तेमाल किया गया LAPACK / BLAS (जो एक बहुत बड़ा दर्द था) को स्विच करने की कोशिश की, लेकिन इसमें कोई बदलाव नहीं देखा जा सकता है प्रदर्शन।

मैं यह पता लगाने में सक्षम नहीं था कि क्या इस्तेमाल किए गए ARPACK (और कैसे) के बारे में कुछ बदलना है?

मैंने निम्न ड्रॉपबॉक्स-फ़ोल्डर के नीचे दिए गए कोड के लिए एक टेस्टकेस अपलोड किया: https://www.dropbox.com/sh/l6aa6izufzyzqr3/AABqij95hZOvRpnjRaETQmka.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);

किसी भी मदद के लिए appriciated है!

कुछ अतिरिक्त विकल्प जो मैंने टिप्पणियों और सुझावों के आधार पर आजमाए:

सप्तक: 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 से ऊपर है, अन्यथा यह बिल्कुल भी नहीं जुटता है और मान दृढ़ता से भिन्न होते हैं।

पायथन: 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]

फिर से एक अलग संख्या में छोटे eigenvalues ​​के साथ। गणना का समय अभी भी लगभग 30min है। जबकि विभिन्न बहुत छोटे मूल्य समझ में आ सकते हैं, क्योंकि वे 0 के गुणकों का प्रतिनिधित्व कर सकते हैं, अलग-अलग गुणन मुझे चकरा देते हैं।

इसके अतिरिक्त, SciPy और Octave में कुछ मूलभूत अंतर हैं, जिन्हें मैं अभी तक समझ नहीं पाया हूं।


2
1 - मुझे लगता है कि आप कोष्ठक कोड में [evals, evecs] के आसपास कोष्ठक लगाने का मतलब है? 2 - क्या आप M के लिए एक छोटा सा उदाहरण शामिल कर सकते हैं? या हो सकता है एक जनरेटर स्क्रिप्ट के लिए एक अगर यह संभव है?
निक जे

1 - हां बिल्कुल, मैंने अपनी पोस्ट को एडिट किया। 2 - मैंने अपने डेटा के कुछ उप-मेट्रिक्स के लिए प्रदर्शन की कोशिश की और ऐसा लगता है कि ऑक्टेव हमेशा तेज होता है, लेकिन 5000x5000 से नीचे के छोटे मेट्रिक्स के लिए इसका 2-5 गुना का बस एक कारक है, ऊपर से यह वास्तव में बदसूरत हो जाता है। और इसके "वास्तविक डेटा" के बाद से मैं एक जनरेटर स्क्रिप्ट नहीं दे सकता। क्या किसी भी तरह एक उदाहरण अपलोड करने का एक मानक तरीका है? स्पार्सिटी के कारण, एक npz- फाइल यथोचित रूप से छोटी है।
स्पेसकिलर

मुझे लगता है कि आप किसी भी क्लाउड स्टोरेज सुविधा के लिए लिंक साझा कर सकते हैं।
पटोल 19५

धन्यवाद। मैंने मूल पोस्ट में एक ड्रॉपबॉक्स लिंक शामिल किया और कोड को काम करने के उदाहरण में अपडेट किया।
स्पेसकिलर

1
अपनी बात को पुष्ट करने के लिए, मैंने माटलब आर २०१ ९ बी पर परीक्षण किया और पायथन ३.y, स्किप १.२.१ (२६ गुना तेजी से) में 36४ सेकंड बनाम ३६.५ मिनट का समय मिला।
बिल

जवाबों:


1

एक अनुमान और कुछ टिप्पणियाँ, क्योंकि मेरे पास मतलूब / सप्तक नहीं है:

Eigenvalues> = 0 के साथ सममित मैट्रिसेस के छोटे eigenvalues ​​को खोजने के लिए, आपकी तरह, निम्नलिखित बदलाव-इनवर्ट की तुलना में तेज़ है:

# flip eigenvalues e.g.
# A:     0 0 0 ... 200 463
# Aflip: 0 163 ... 463 463 463
maxeval = eigsh( A, k=1 )[0]  # biggest, fast
Aflip = maxeval * sparse.eye(n) - A
bigevals, evecs = eigsh( Aflip, which="LM", sigma=None ... )  # biggest, near 463
evals = maxeval - bigevals  # flip back, near 463 -> near 0
# evecs are the same

eigsh( Aflip )बड़े के लिए eigenpairs, शिफ्ट-इनवर्ट से छोटे के लिए A * xतेज़ है , क्योंकि solve()उस शिफ्ट- इनवर्ट की तुलना में तेज़ होना चाहिए। Aflipचोल्स्की के साथ सकारात्मक-निश्चितता के लिए एक त्वरित परीक्षण के बाद मतलब / ऑक्टेव गर्भधारण कर सकता है।
क्या आप eigsh( Aflip )मतलाब / ऑक्टेव में दौड़ सकते हैं ?

अन्य कारक जो सटीकता / गति को प्रभावित कर सकते हैं:

प्रारंभ वेक्टर के लिए Arpack का डिफ़ॉल्ट v0एक यादृच्छिक वेक्टर है। मैं उपयोग करता हूं v0 = np.ones(n), जो कुछ के लिए भयानक हो सकता है Aलेकिन प्रतिलिपि प्रस्तुत करने योग्य है :)

यह Aमैट्रिक्स लगभग सिगुलर है, A * ones~ 0।

मल्टीकोर: ओपनब्लस / लैपैक के साथ स्काइप-अरपैक मेरे आईमैक पर 4 कोर के ~ 3.9 का उपयोग करता है; मतलाब / ऑक्टेव सभी कोर का उपयोग करते हैं?


यहाँ कई के लिए scipy-Arpack eigenvalues ​​हैं kऔर tol, gist.gith.com के तहत लॉगफ़ाइल्स से निकाला गया है :

k 10  tol 1e-05:    8 sec  eigvals [0 8.5e-05 0.00043 0.0014 0.0026 0.0047 0.0071 0.0097 0.013 0.018] 
k 10  tol 1e-06:   44 sec  eigvals [0 3.4e-06 2.8e-05 8.1e-05 0.00015 0.00025 0.00044 0.00058 0.00079 0.0011] 
k 10  tol 1e-07:  348 sec  eigvals [0 3e-10 7.5e-07 7.6e-06 1.2e-05 1.9e-05 2.1e-05 4.2e-05 5.7e-05 6.4e-05] 

k 20  tol 1e-05:   18 sec  eigvals [0 5.1e-06 4.5e-05 0.00014 0.00023 0.00042 0.00056 0.00079 0.0011 0.0015 0.0017 0.0021 0.0026 0.003 0.0037 0.0042 0.0047 0.0054 0.006
k 20  tol 1e-06:   73 sec  eigvals [0 5.5e-07 7.4e-06 2e-05 3.5e-05 5.1e-05 6.8e-05 0.00011 0.00014 0.00016 0.0002 0.00025 0.00027 0.0004 0.00045 0.00051 0.00057 0.00066
k 20  tol 1e-07:  267 sec  eigvals [-4.8e-11 0 7.5e-07 7.6e-06 1e-05 1.9e-05 2e-05 2.2e-05 4.2e-05 5.1e-05 5.8e-05 6.4e-05 6.9e-05 8.3e-05 0.00011 0.00012 0.00013 0.00015

k 50  tol 1e-05:   82 sec  eigvals [-4e-13 9.7e-07 1e-05 2.8e-05 5.9e-05 0.00011 0.00015 0.00019 0.00026 0.00039 ... 0.0079 0.0083 0.0087 0.0092 0.0096 0.01 0.011 0.011 0.012
k 50  tol 1e-06:  432 sec  eigvals [-1.4e-11 -4e-13 7.5e-07 7.6e-06 1e-05 1.9e-05 2e-05 2.2e-05 4.2e-05 5.1e-05 ... 0.00081 0.00087 0.00089 0.00096 0.001 0.001 0.0011 0.0011
k 50  tol 1e-07: 3711 sec  eigvals [-5.2e-10 -4e-13 7.5e-07 7.6e-06 1e-05 1.9e-05 2e-05 2.2e-05 4.2e-05 5.1e-05 ... 0.00058 0.0006 0.00063 0.00066 0.00069 0.00071 0.00075

versions: numpy 1.18.1  scipy 1.4.1  umfpack 0.3.2  python 3.7.6  mac 10.10.5 

क्या Matlab / Octave एक ही हैं? यदि नहीं, तो सभी दांव बंद हैं - पहले शुद्धता की जांच करें, फिर गति।

क्यों eigenvalues ​​इतना लड़खड़ाते हैं? माना जाता है कि गैर-नकारात्मक-निश्चित मैट्रिक्स के लिए टिनी <0 राउंडऑफ़ त्रुटि का संकेत है , लेकिन एक छोटी सी पारी की सामान्य चाल, A += n * eps * sparse.eye(n)मदद नहीं करती है।


यह कहां Aसे आता है, क्या समस्या क्षेत्र है? क्या आप समान A, छोटे या विरल उत्पन्न कर सकते हैं ?

उम्मीद है की यह मदद करेगा।


आपके इनपुट के लिए धन्यवाद और (बहुत) देर से उत्तर के लिए क्षमा करें। मैंने जिस प्रोजेक्ट के लिए यह प्रयोग किया है वह पहले से ही पूरा है, लेकिन मैं अभी भी उत्सुक हूं, इसलिए मैंने जांच की। अफसोस की बात यह है कि ओकैटवे में प्रतिजन अलग-अलग होते हैं, k = 10 के लिए मैं [-2.5673e-16 -1.2239e-18 7.5420e-07 7.5622e-06 1.0189e-05 / 1.2525e-05 2.0265e-05 2.1568e- खोजें 05 4.2458e-05 5.1030e-05] जो 1e-5 से 1e-7 की सीमा में सहिष्णुता मूल्य से भी स्वतंत्र है। इसलिए यहां एक और अंतर है। क्या आपको नहीं लगता कि यह विचित्र है (आपके सुझाव सहित) अलग-अलग छोटे मानों की संख्या पर निर्भर मूल्यों की संख्या पर निर्भर करता है?
Spacekiller23

@ स्पेसकिलर 23, यह एक बग था, जो अब स्कैपी 1.4.1 में तय किया गया है ( स्काइप / मुद्दे / 11198 देखें ); क्या आप अपना संस्करण देख सकते हैं? इसके अलावा tolछोटे eigenvalues ​​के लिए गन्दा है - उस पर एक नया प्रश्न पूछें यदि आप चाहें, तो मुझे बताएं।
Denis

1

मुझे पता है कि यह पुराना है, लेकिन मुझे भी यही समस्या थी। क्या आपने यहाँ समीक्षा की ( https://docs.scipy.org/doc/scipy/reference/tutorial/arpack.html )?

ऐसा लगता है कि जब आप एक कम संख्या (0) पर सिग्मा सेट करते हैं, तो आपको सेट करना चाहिए जो कि = 'एलएम' है, भले ही आप कम मूल्यों के लिए चाहते हैं। इसका कारण यह है कि सिग्मा सेट करने से उन मानों को बदल दिया जाता है जो आप चाहते हैं (इस मामले में कम) उच्च प्रतीत होता है और इसलिए आप अभी भी 'एलएम' विधियों का लाभ उठाने में सक्षम हैं, जो कि आप जो चाहते हैं उसे प्राप्त करने के लिए बहुत तेज़ हैं (कम eigenvalues) )।


क्या इससे वास्तव में आपके लिए प्रदर्शन बदल गया? यह मेरे लिए एक आश्चर्य होगा। मुझे पता था कि आपके द्वारा पोस्ट किया गया लिंक और मैंने भी स्पष्ट रूप से निर्दिष्ट किया है जो मेरे उदाहरण में = 'LM' है। क्योंकि एक अनसेट के लिए डिफ़ॉल्ट मान जो 'LM' है। मैंने अभी भी जाँच की है, और प्रदर्शन मेरे उदाहरण के लिए अपरिवर्तित है।
Spacekiller23

वास्तव में, आपके लिए पाइथन से अष्टक के समान अंतर प्रतीत होता है। मेरे पास एक बड़ा मैट्रिक्स भी था जिसे मैं विघटित करने की कोशिश कर रहा था और ईगिश (मैट्रिक्स, के = 7, जो = 'एलएम', सिग्मा = 1e-10) का उपयोग करके समाप्त हो गया। मूल रूप से मैं गलत तरीके से निर्दिष्ट कर रहा था जो कि = 'एसएम' सोच के लिए मुझे यह करने की आवश्यकता थी कि सबसे छोटे eigenvalues ​​प्राप्त करने के लिए और मुझे जवाब देने के लिए हमेशा के लिए ले जा रहा था। फिर, मैंने उस लेख को पाया और महसूस किया कि आपको इसे तेजी से 'एलएम' पर निर्दिष्ट करने की आवश्यकता है, और जो कुछ भी आप चाहते हैं, उसे सेट करने के लिए और यह चीजों को गति देगा। क्या आपका मैट्रिक्स वास्तव में हेर्मिटियन है?
एंथोनी गत्ती

0

मैं पहले कहना चाहता हूं कि मुझे नहीं पता कि आपके और @Bill के परिणामों के बारे में रिपोर्ट क्यों की गई। मुझे आश्चर्य है कि अगर eigs(M,6,0)ऑक्टेव से मेल खाती है k=6 & sigma=0, या शायद यह कुछ और है?

डरपोक के साथ, अगर मैं सिग्मा प्रदान नहीं करता हूं, तो मुझे इस तरह से एक सभ्य समय में परिणाम मिल सकता है।

import numpy as np
from scipy.sparse import csr_matrix
from scipy.sparse.linalg import eigsh
from time import perf_counter
M = np.load('M.npz')
a = csr_matrix((M['data'], M['indices'], M['indptr']), shape=M['shape'])
t = perf_counter()
b, c = eigsh(a, k=50, which='SA', tol=1e1)
print(perf_counter() - t)
print(b)

मुझे पूरी तरह से यकीन नहीं है कि यह समझ में आता है।

0.4332823531003669
[4.99011753e-03 3.32467891e-02 8.81752215e-02 1.70463893e-01
 2.80811313e-01 4.14752072e-01 5.71103821e-01 7.53593653e-01
 9.79938915e-01 1.14003837e+00 1.40442848e+00 1.66899183e+00
 1.96461415e+00 2.29252666e+00 2.63050114e+00 2.98443218e+00
 3.38439528e+00 3.81181747e+00 4.26309942e+00 4.69832271e+00
 5.22864462e+00 5.74498014e+00 6.22743988e+00 6.83904055e+00
 7.42379697e+00 7.97206446e+00 8.62281827e+00 9.26615266e+00
 9.85483434e+00 1.05915030e+01 1.11986296e+01 1.18934953e+01
 1.26811461e+01 1.33727614e+01 1.41794599e+01 1.47585155e+01
 1.55702295e+01 1.63066947e+01 1.71564622e+01 1.78260727e+01
 1.85693454e+01 1.95125277e+01 2.01847294e+01 2.09302671e+01
 2.18860389e+01 2.25424795e+01 2.32907153e+01 2.37425085e+01
 2.50784800e+01 2.55119112e+01]

एकमात्र तरीका जो मैंने सिग्मा का उपयोग करने के लिए पाया और एक सभ्य समय में परिणाम प्राप्त करने के लिए एम को एक रैखिकओपरेटर के रूप में प्रदान करना है। मैं इस चीज से बहुत परिचित नहीं हूं, लेकिन मैंने जो कुछ भी समझा था, उसके कार्यान्वयन से एक पहचान मैट्रिक्स का प्रतिनिधित्व होता है, जो कि एम को कॉल में निर्दिष्ट नहीं होने पर क्या होना चाहिए। इसका कारण यह है कि प्रत्यक्ष समाधान (LU अपघटन) करने के बजाय, scipy एक पुनरावृत्त सॉल्वर का उपयोग करेगा, जो संभवतः बेहतर अनुकूल है। एक तुलना के रूप में, यदि आप प्रदान करते हैं M = np.identity(a.shape[0]), जो सटीक होना चाहिए, तो परिणाम प्राप्त करने के लिए eigsh हमेशा के लिए लेता है। ध्यान दें कि यह दृष्टिकोण काम नहीं करता है यदि sigma=0प्रदान किया जाता है। लेकिन मुझे यकीन नहीं है कि क्या sigma=0वास्तव में यह उपयोगी है?

import numpy as np
from scipy.sparse import csr_matrix
from scipy.sparse.linalg import eigs, eigsh, LinearOperator
from time import perf_counter


def mv(v):
    return v


M = np.load('M.npz')
a = csr_matrix((M['data'], M['indices'], M['indptr']), shape=M['shape'])
t = perf_counter()
b, c = eigsh(a, M=LinearOperator(shape=a.shape, matvec=mv, dtype=np.float64),
             sigma=5, k=50, which='SA', tol=1e1, mode='cayley')
print(perf_counter() - t)
print(np.sort(-5 * (1 + b) / (1 - b)))

फिर से, अगर यह सही है, लेकिन निश्चित रूप से पहले से अलग नहीं है तो कोई विचार नहीं है। यह बहुत अच्छा होगा कि किसी से भी बात की जाए।

1.4079377939924598
[3.34420263 3.47938816 3.53019328 3.57981026 3.60457277 3.63996294
 3.66791416 3.68391585 3.69223712 3.7082205  3.7496456  3.76170023
 3.76923989 3.80811939 3.81337342 3.82848729 3.84137264 3.85648208
 3.88110869 3.91286153 3.9271108  3.94444577 3.97580798 3.98868207
 4.01677424 4.04341426 4.05915855 4.08910692 4.12238969 4.15283192
 4.16871081 4.1990492  4.21792125 4.24509036 4.26892806 4.29603036
 4.32282475 4.35839271 4.37934257 4.40343219 4.42782208 4.4477206
 4.47635849 4.51594603 4.54294049 4.56689989 4.58804775 4.59919363
 4.63700551 4.66638214]

आपके इनपुट और प्रतिक्रिया के लिए धन्यवाद। मैंने आपकी बातों का माकूल जवाब देने के लिए कुछ चीजों की कोशिश की। 1. हाथ में मेरा काम के लिए सबसे छोटे eigenvalues ​​/ वैक्टर खोजने की आवश्यकता होती है। Sigma = 0 का उपयोग करने का तरीका SciPy डॉक्स में भी दिया गया है: docs.scipy.org/doc/scipy/reference/tutorial/arpack.html 2. मैंने कुछ और विकल्पों की कोशिश की, जिन्हें मैंने मूल प्रश्न में संपादित किया। 3. जैसा कि मैं ऑक्टेव और साइपीपी के वृत्तचित्रों को समझता हूं, ईग्स (एम, 6,0) और के = 6, सिमगा = 0 समान होना चाहिए।
स्पेसकिलर

4. चूंकि मेरा मैट्रिक्स वास्तविक और चौकोर है, मैंने सोचा कि एसए और एसएम के बीच एक विकल्प के रूप में कोई अंतर नहीं होना चाहिए, लेकिन जाहिर है, कम से कम कम्प्यूटेशन में है। क्या मैं यहाँ गलत रास्ते पर हूँ? कुल मिलाकर इसका मतलब है कि अधिक प्रश्न और मुझसे कोई वास्तविक उत्तर या समाधान नहीं।
स्पेसकिलर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.