Numpy'de matris inversiyonunun karmaşıklığı


11

Yoğun kare matrisleri ters çevirmeyi gerektiren diferansiyel denklemleri çözüyorum. Bu matris inversiyonu hesaplama süremin çoğunu tüketiyor, bu yüzden mevcut en hızlı algoritmayı kullanıp kullanmadığımı merak ediyordum.

Şu anki seçimim numpy.linalg.inv . Nümeriklerimden , n'nin satır sayısı olduğu olarak ölçeklendiğini görüyorum, bu yüzden yöntem Gauss eliminasyonu gibi görünüyor.Ö(n3)

Wikipedia'ya göre , daha hızlı algoritmalar mevcuttur. Bunları uygulayan bir kütüphane olup olmadığını bilen var mı?

Acaba, neden bu hızlı algoritmaları kullanmıyor?


Matrislerinizi daha önce yapmanız gerekir. Scipy'ye bak. Yardımınız için seyrek. İhtiyacınız olan birçok araç içerir.
Tobal

@Toplam izlediğimden emin değilim ... bir matrisi nasıl "gerçekleştirirsiniz?" ve tam olarak nasıl scipy.sparseyardımcı olabilirsiniz?
16:24, GoHokies

@ GoHokies scipy numpy'nin bir tamamlayıcısıdır. Bazı hesaplamalar yapmadan önce yoğun / seyrek matrisler iyi uygulanmalıdır, hesaplamalarınızı geliştirir. Lütfen kötü ingilizcemle benden en iyi açıklayan bu docs.scipy.org/doc/scipy/reference/sparse.html adresini okuyun .
Tobal

@Tobal Soru özellikle yoğun matrisleri ifade ediyor , bu yüzden scipy.sparseburada nasıl alakalı olduğunu görmüyorum ?
Christian Clason

2
@Tobal - Sanırım hala anlamıyorum. "Matrislerinizi önceden oluşturun" ve "bazı hesaplamalar yapmadan önce matrislerin iyi uygulanması gerekir" ile tam olarak ne demek istiyorsunuz? Son yorumunuzla ilgili olarak, seyrek ve yoğun matrisler için kullanılabilecek tekniklerin çok farklı olduğunu kesinlikle kabul edeceksiniz.
Wolfgang Bangerth

Yanıtlar:


21

(Bu yorumlar için çok uzun sürüyor ...)

Aslında algoritmanızda tersini hesaplamanız gerektiğini varsayacağım. 1 İlk olarak, bu alternatif algoritmaların aslında daha hızlı olduğu iddia edilmediğini , sadece daha iyi asimptotik karmaşıklığa sahip olduklarını belirtmek önemlidir (yani, gerekli sayıda temel işlem daha yavaş büyür). Aslında, pratikte bunlar , aşağıdaki nedenlerden dolayı (verilen için ) aslında standart yaklaşımdan ( çok) daha yavaştır :n

  1. -notation deri gücü önünde sürekli bir astronomik büyük olabilir, - çok büyük olduğunu den çok daha küçük olabilir herhangi olduğu öngörülebilir gelecekte herhangi bir bilgisayar tarafından ele alınabilir. (Bu, örneğin Coppersmith – Winograd algoritması için geçerlidir.)ÖnC1n3C2n2.xn

  2. Karmaşıklık, her (aritmetik) işlemin aynı zamanı aldığını varsayar - ancak bu gerçek uygulamada gerçek olmaktan çok uzaktır: Aynı sayı ile bir grup sayıyı çarpmak, aynı sayıda farklı sayıyı çarpmaktan çok daha hızlıdır . Bunun nedeni, mevcut hesaplamadaki büyük şişe boynunun, verileri o verilerdeki gerçek aritmetik işlemleri değil, önbelleğe almasıdır. Dolayısıyla, ilk duruma ( önbellek uyumlu olarak adlandırılır ) sahip olacak şekilde yeniden düzenlenebilen bir algoritma , bunun mümkün olmadığı bir yerden çok daha hızlı olacaktır. (Örneğin Strassen algoritması için durum budur.)

Ayrıca, sayısal kararlılık en az performans kadar önemlidir; ve burada, yine, standart yaklaşım genellikle kazanır.

Bu nedenle, standart yüksek performanslı kütüphaneler (Numpy'nin tersi hesaplamasını istediğinde çağırdığı BLAS / LAPACK) genellikle sadece bu yaklaşımı uygular. Elbette, örneğin Strassen'in algoritmasının orada Numpy uygulamaları vardır, ancak montaj seviyesinde elle ayarlanan bir algoritması bir herhangi bir makul matris boyutu için üst düzey bir dilde yazılmış algoritma.Ö(n3)Ö(n2.x)


1 Ama bunun çok nadiren gerçekten gerekli olduğuna işaret etmediysem yanlış olurum: ürününü hesaplamanız gerektiğinde, bunun yerine doğrusal sistemini çözmelisiniz (örn. kullanarak ) kullanın ve kullanın - bu çok daha kararlıdır ve ( matrisinin yapısına bağlı olarak ) çok daha hızlı yapılabilir. Kullanmak gerekiyorsa birden çok kez, sen faktorize precompute edebilirsiniz daha sonra ve yeniden (genellikle en pahalı çözmek parçasıdır).bir-1bbirx=bnumpy.linalg.solvexbirbir-1bir


Harika cevap, teşekkürler efendim, özellikle teorik hız ile pratik hız arasında büyük bir fark yaratan ayrıntılardaki (büyük O gösterimindeki sabitler) şeytanı işaret ettiğiniz için teşekkür ederim.
gaborous

"Tersine nadiren gerekli" kısmının daha fazla vurgulanması gerektiğini düşünüyorum. Amaç bir diferansiyel denklemler sistemini çözmekse, tam tersin gerekli olması muhtemel görünmemektedir.
Jared Goguen

@o_o Bu benim ilk orijinal yorumumdu (hepsini tek bir cevapta birleştirdikten sonra sildim). Ancak, sitenin (ve daha sonra okurların) yararına, arkasında bir XY sorunu olsa bile, bir sorunun sorudaki gerçek soruya (hem makul hem de konuyla ilgili) cevap vermesi gerektiğini düşündüm. Ayrıca, çok
sinir bozucu gelmek

1
n

1
bir

4

Muhtemelen numpy kaynak kodu içine derin gömülü, dikkat edilmelidir (bkz https://github.com/numpy/numpy/blob/master/numpy/linalg/umath_linalg.c.src dgetrf işlevi çağırmak için inv rutin girişimleri) daha sonra orijinal matrisinizin LU ayrışmasını gerçekleştiren sistem LAPACK paketinizden. Bu ahlaki olarak Gauss eliminasyonuna eşdeğerdir, ancak yüksek performanslı bir BLAS'ta daha hızlı matris çarpma algoritmaları kullanılarak biraz daha düşük bir karmaşıklığa ayarlanabilir.

Bu rotayı izlerseniz, dağıtımınızla birlikte gelen sistem yerine kitaplık zincirinin tamamını yeni kitaplığı kullanmaya zorlamanın oldukça karmaşık olduğu konusunda uyarılmalıdır. Modern bilgisayar sistemlerindeki alternatiflerden biri scaLAPACK veya (python dünyasında) petsc4py gibi paketleri kullanarak paralel yöntemlere bakmaktır. Bununla birlikte, bunlar doğrudan metotlara uygulandığından daha çok lineer cebir sistemleri için tekrarlamalı çözücüler olarak kullanılmaktadır ve PETSc özellikle seyrek sistemleri yoğun olanlardan daha fazla hedeflemektedir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.