2013-02-09 81 views
11

我試圖做到以下幾點,並重復直至收斂:numpy的矩陣掛羊頭賣狗肉 - 逆時代矩陣的總和

其中X n x p,並有他們的rr x n x p數組中被稱爲samplesUn x n,Vp x p。 (我得到了matrix normal distribution的MLE。) 這些尺寸都可能很大,我期待的事情至少在r = 200,n = 1000,p = 1000

我當前的代碼確實

V = np.einsum('aji,jk,akl->il', samples, np.linalg.inv(U)/(r*n), samples) 
U = np.einsum('aij,jk,alk->il', samples, np.linalg.inv(V)/(r*p), samples) 

這工作不錯,但你永遠應該當然地找到逆,並通過它繁殖的東西。如果我能以某種方式利用U和V是對稱和正定的事實,那也是很好的。 我希望能夠在迭代中計算U和V的Cholesky因子,但是我不知道如何去做,因爲總和。

我可以做這樣的事情

V = sum(np.dot(x.T, scipy.linalg.solve(A, x)) for x in samples) 

(或利用的PSD岬類似的東西)避免逆,但後來有一個Python的循環,這使得該numpy的仙女哭泣。

我也想象不出這樣一種方式,我能得到使用solve爲每xA^-1 x數組,而不必做一個Python循環重塑samples,但能造成很大的輔助陣列是浪費內存。

是否存在一些線性代數或無節制的技巧,我可以做到最好的三種:沒有明確的逆,沒有Python循環,沒有大的輔助數組?或者,我最好的辦法是用更快的語言來實現Python循環並向其發出呼籲? (直接將它直接移植到Cython可能會有所幫助,但仍然會涉及到很多Python方法調用;但是,直接製作相關的blas/lapack例程並不會太麻煩。)

(事實證明,實際上我並不需要矩陣UV - 只是它們的決定因素,或者實際上只是Kronecker產品的決定因素。所以如果有人對如何減少工作有一個聰明的想法,仍然得到了決定了,那將是非常讚賞。)

+2

寫得很好的問題。我的大腦今天運作不佳,但我只是建議您至少將數學部分從頭到尾發佈到math.stackexchange。com,以防你錯過了一條明顯的捷徑。你是對的,它*感覺*就像那裏*可能*是一種利用spd矩陣屬性的方式,但是我也看不到它。 – YXD 2013-02-09 00:50:29

+0

@MrE感謝您的建議; [我也在那裏發佈](http://math.stackexchange.com/q/298512/19147)。 – Dougal 2013-02-09 05:14:27

回答

7

直到有人想出了一個更加振奮的答案,如果我是你,我會讓仙女哭了...

r, n, p = 200, 400, 400 

X = np.random.rand(r, n, p) 
U = np.random.rand(n, n) 

In [2]: %timeit np.sum(np.dot(x.T, np.linalg.solve(U, x)) for x in X) 
1 loops, best of 3: 9.43 s per loop 

In [3]: %timeit np.dot(X[0].T, np.linalg.solve(U, X[0])) 
10 loops, best of 3: 45.2 ms per loop 

因此,擁有一個python循環,並且必須將所有結果彙總在一起,所花費的時間比解決每200個系統需要的200多倍多390倍。如果循環和求和是免費的,你會得到少於5%的改進。可能會有一些調用python函數的開銷,但對於實際解決方程的時間來說,它可能仍然可以忽略不計,無論您使用哪種語言編寫。

+0

嗯......好點。在非常大的'r'和非常小的'n'和'p'的情況下,我愚蠢地執行了'einsum'方法與'solve'方法的計時,當然這很有意義,Python循環開銷會是更重要的是。我會在明天試試我的真實數據,看看比較是什麼。 – Dougal 2013-02-09 04:51:12

+0

事實證明,使用'scipy.linalg.cho_solve'做一個python循環足以滿足我的需求。我仍然很好奇,如果有一個算法加速,所以我要離開這個數學。我打開問題。 – Dougal 2013-02-11 19:33:23