2016-12-15 25 views
3

我想申請將產生的這個在一般情況下結果的函數:點產品的循環應用

np.dot(np.dot(np.dot(D3, theta2), D2), theta1) 

也就是說,而不是指定D3theta2等,將在做一般情況下如

if n==1: 
    answer = np.dot(params['D'+str(n)], params['theta'+str(n - 1)]) 
else: 
    answer = ? 

你有什麼想法,我怎麼能做到這一點?

+0

你真的想要使用'np.linalg.multi_dot'。 – Daniel

回答

1

你真正想要的是np.linalg.multi_dot

np.linalg.multi_dot([D3, theta2, D2, theta1]) 

這樣做的優化收縮順序的最大優點是效率最高,而不僅僅是ru通過列表。如果你的矩陣是正方形的,則沒有區別;然而,如果不是,這可能是非常有益的。

2

像已經被@wwii可以使用functools.reduce代替遞歸提到:

import functools 

def dot(a, b): 
    return 'dot({}, {})'.format(a, b) 

>>> functools.reduce(dot, ['theta2', 'D2', 'theta1'], 'D3') 
'dot(dot(dot(D3, theta2), D2), theta1)' 

剛剛與實際功能和變量替換變量:

functools.reduce(np.dot, [D3, theta2, D2, theta1]) 
1

使用functools.reduce提出的優秀方案的替代解決方案將是我們e numpy's einsum

注意:這不是一個更好的解決方案,只是一種替代方法(和一個有趣的)。

例如,對於3個隨機陣列:

>>> a = np.random.randn(3,3) 
>>> b = np.random.randn(3,3) 
>>> c = np.random.randn(3,3) 

遞歸點積可以寫爲:

>>> result = np.einsum('ij,jk,kl->il', a, b, c) 
>>> np.allclose(result, a.dot(b).dot(c)) # True 

然後,通用函數可以被寫爲:

def recdot(*args): 
    # Generate the einstring equivalent to all the input matrices 
    s='abcdefghijklmnopqrstuvwxyz' 
    einstr = ','.join([s[i:i+2] for i in range(len(args))]) 
    einstr += '->{}{}'.format(s[0],s[len(args)]) 
    return np.einsum(einstr, *args) 

然後叫它:

>>> np.allclose(recdot(a, b, c), a.dot(b).dot(c)) # True 

注2:它有一個限制,只能在26個矩陣(上述字母表中的字母數)中操作。

或者,如果您有與輸入矩陣陣列,更改爲:

def recdot(*args): -> def recdot(args): 

而且

>>> recdot([a,b,c]) 
+0

這個主要的缺點是'np.einsum'會比'dot'慢得多。由於'einsum'只是循環遍歷索引,所以你的例子縮放爲'N^4'而不是'N^3'。這將在NumPy 1.12中改變,但需要注意的一點。 – Daniel

相關問題