2010-11-21 21 views
3

以下は多変量正規分布からの描画用の私のCythonコードです。私は異なる密度を持つたびにループを使用しています。 (conLSigmaはコレスキーファクターです)cythonで可能な最適化:numpy配列

これは、ループごとに逆およびコレスキー分解を行っているので、時間がかかります。純粋なPythonコードよりも速いですが、速度をさらに上げる方法があるかどうかは疑問でした。

from __future__ import division 

import numpy as np 

cimport numpy as np 

ctypedef np.float64_t dtype_t 

cimport cython 
@cython.boundscheck(False) 
@cython.wraparound(False) 

def drawMetro(np.ndarray[dtype_t, ndim = 2] beta, 
       np.ndarray[dtype_t, ndim = 3] H, 
       np.ndarray[dtype_t, ndim = 2] Sigma, 
       float s): 

    cdef int ncons = betas.shape[0] 
    cdef int nX = betas.shape[1] 
    cdef int con 

    cdef np.ndarray betas_cand = np.zeros([ncons, nX], dtype = np.float64) 
    cdef np.ndarray conLSigma = np.zeros([nX, nX], dtype = np.float64) 

    for con in xrange(ncons): 
     conLSigma = np.linalg.cholesky(np.linalg.inv(H[con] + Sigma)) 
     betas_cand[con] = betas[con] + s * np.dot(conLSigma, np.random.standard_normal(size = nX)) 

    return(betas_cand) 

答えて

5

コレスキー分解では、下三角行列が作成されます。これは、np.dotで行われる乗算の半分近くが実行される必要がないことを意味します。あなたはしかし、

tmp = np.random.standard_normal(size = nX) 
for i in xrange(nX): 
    for j in xrange(i+1): 
     betas_cand[con,i] += s * conLSigma[i,j] * tmp[j] 

にライン

betas_cand[con] = betas[con] + s * np.dot(conLSigma, np.random.standard_normal(size = nX)) 

を変更する場合は、あなたは可能性が

cdef np.ndarray betas_cand = np.array(betas) 

cdef np.ndarray betas_cand = np.zeros([ncons, nX], dtype = np.float64) 

を変更する必要がありますコースの利用スライスの乗算のために、私はそうではありませんそれが私が提案した方法より速いかどうか確かめてください。とにかく、うまくいけばあなたは考えを得る。私はこれをスピードアップするためにできることが他にもたくさんあるとは思わない。

+2

チップをありがとう。私は、BLASのようなCライブラリを直接呼び出すとnp.dotのものを使うのではなくて困っています。 – joon

0

最初にコレスキー分解を計算し、後ろの置換によって下の三角行列を反転させます。これはlinalg.cholesky(linalg.inv(S))よりも速くなければなりません。

関連する問題