我想申請將產生的這個在一般情況下結果的函數:點產品的循環應用
np.dot(np.dot(np.dot(D3, theta2), D2), theta1)
也就是說,而不是指定D3
,theta2
等,將在做一般情況下如
if n==1:
answer = np.dot(params['D'+str(n)], params['theta'+str(n - 1)])
else:
answer = ?
你有什麼想法,我怎麼能做到這一點?
我想申請將產生的這個在一般情況下結果的函數:點產品的循環應用
np.dot(np.dot(np.dot(D3, theta2), D2), theta1)
也就是說,而不是指定D3
,theta2
等,將在做一般情況下如
if n==1:
answer = np.dot(params['D'+str(n)], params['theta'+str(n - 1)])
else:
answer = ?
你有什麼想法,我怎麼能做到這一點?
你真正想要的是np.linalg.multi_dot
:
np.linalg.multi_dot([D3, theta2, D2, theta1])
這樣做的優化收縮順序的最大優點是效率最高,而不僅僅是ru通過列表。如果你的矩陣是正方形的,則沒有區別;然而,如果不是,這可能是非常有益的。
把你的東西在一個容器中,並使用functools.reduce
像已經被@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])
使用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])
這個主要的缺點是'np.einsum'會比'dot'慢得多。由於'einsum'只是循環遍歷索引,所以你的例子縮放爲'N^4'而不是'N^3'。這將在NumPy 1.12中改變,但需要注意的一點。 – Daniel
你真的想要使用'np.linalg.multi_dot'。 – Daniel