我想在一般情况下应用一个能产生结果的函数:
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 = ?
您对我如何做到这一点有什么想法吗?
答案 0 :(得分: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 :(得分:1)
将您的东西放在容器中并使用functools.reduce
答案 2 :(得分:1)
使用functools.reduce
提议的优秀解决方案的另一种解决方案是使用numpy' 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])
答案 3 :(得分:1)
你真正想要的是np.linalg.multi_dot
:
np.linalg.multi_dot([D3, theta2, D2, theta1])
这具有非常大的优势,即优化收缩顺序是最有效的,而不是简单地在列表中运行。如果你的矩阵是正方形,则没有区别;但是,如果不是这样,这可能是非常有益的。