用广播代替循环轴,第2页

时间:2017-07-19 22:02:16

标签: python python-3.x numpy numpy-broadcasting

早些时候,我问了一个类似的question,答案使用np.dot,利用了点积涉及一系列产品的事实。 (据我所知。)

现在我有一个类似的问题,我不认为dot会适用,因为我想采用一个元素方式对角线代替一个总和。如果是这样,我就无法正确应用它。

给定矩阵x和数组err

x = np.matrix([[ 0.02984406, -0.00257266],
               [-0.00257266,  0.00320312]])

err = np.array([  7.6363226 ,  13.16548267])

我目前使用循环的实现是:

res = np.array([np.sqrt(np.diagonal(x * err[i])) for i in range(err.shape[0])])

print(res)
[[ 0.47738755  0.15639712]
 [ 0.62682649  0.20535487]]

x.dot(i)中的每个i的对角线为err。这可以被矢量化吗?换句话说,x * err的输出可以是3维的,np.diagonal然后产生2d数组,每个对角线有一个元素吗?

2 个答案:

答案 0 :(得分:2)

程序:

import numpy as np
x = np.matrix([[ 0.02984406, -0.00257266],
               [-0.00257266,  0.00320312]])

err = np.array([  7.6363226 ,  13.16548267])
diag = np.diagonal(x)
ans = np.sqrt(diag*err[:,np.newaxis])  # sqrt of outer product
print(ans)

# use out keyword to avoid making new numpy array for many times.
ans = np.empty(x.shape, dtype=x.dtype)
for i in range(100):
    ans = np.multiply(diag, err, out=ans)
    ans = np.sqrt(ans, out=ans)

结果:

[[ 0.47738755  0.15639712]
 [ 0.62682649  0.20535487]]

答案 1 :(得分:2)

这是一种方法,将diagonal-viewndarray.flat一起用于x,然后使用broadcasting进行逐元素乘法,就像这样 -

np.sqrt(x.flat[::x.shape[1]+1].A1 * err[:,None])

示例运行 -

In [108]: x = np.matrix([[ 0.02984406, -0.00257266],
     ...:                [-0.00257266,  0.00320312]])
     ...: 
     ...: err = np.array([  7.6363226 ,  13.16548267])
     ...: 

In [109]: np.sqrt(x.flat[::x.shape[1]+1].A1 * err[:,None])
Out[109]: 
array([[ 0.47738755,  0.15639712],
       [ 0.62682649,  0.20535487]])

运行时测试,了解view如何帮助创建副本的np.diagonal -

In [104]: x = np.matrix(np.random.rand(5000,5000))

In [105]: err = np.random.rand(5000)

In [106]: %timeit np.diagonal(x)*err[:,np.newaxis]
10 loops, best of 3: 66.8 ms per loop

In [107]: %timeit x.flat[::x.shape[1]+1].A1 * err[:,None]
10 loops, best of 3: 37.7 ms per loop