广播NumPy阵列时实际发生了什么

时间:2014-11-18 22:00:15

标签: python numpy

我正在和NumPy一起玩,我写了简单的功能

>   def euclid_dist(x, y):
...    return sqrt((x-y).transpose().dot(x-y))

但现在我尝试

> x = arange(1,4).reshape(3,1)
> y = array([[1,2,3],[4,5,6],[7,8,9],[10,11,12]]).transpose()
> z = euclid_dist(x, y)
> z

array([[  0.        ,   0.        ,   0.        ,   0.        ],
       [  0.        ,   5.19615242,   7.34846923,   9.        ],
       [  0.        ,   7.34846923,  10.39230485,  12.72792206],
       [  0.        ,   9.        ,  12.72792206,  15.58845727]])

好的......所以,对角线上的数字是我想要的东西,但其余的呢?刚刚发生了什么?

据我所知,x被广播,因此它变成'

array([[1, 1, 1, 1],
       [2, 2, 2, 2],
       [3, 3, 3, 3]])

但之后会发生什么?这显然不是元素操作。但是,如果它将函数应用于x和y的每对列,那么z的所有行(或列)都不应该相等(因为'广播x'的所有列都相等)?

显然有一些我不理解的东西,我将不胜感激任何澄清。

1 个答案:

答案 0 :(得分:2)

正如我理解你的问题,你正试图做一个列式并行点产品。换句话说,对于向量abcd的矩阵,您想要这样做:

[[a1, b1, c1, d1],
 [a2, b2, c2, d2],
 [a3, b3, c3, d3]]

对此:

[a1 * a1 + a2 * a2 + a3 * a3,
 b1 * b1 + b2 * b2 + b3 * b3,
 c1 * c1 + c2 * c2 + c3 * c3,
 d1 * d1 + d2 * d2 + d3 * d3]

事实上,你对广播的理解看起来很好。它dot不能按预期的方式工作 - 它会进行矩阵乘法运算。所以你得到以下结果(取决于你的转置方式):

>>> sqrt((x - y).T.dot(x - y))
array([[ 11.22497216,  11.22497216,  11.22497216],
       [ 11.22497216,  11.22497216,  11.22497216],
       [ 11.22497216,  11.22497216,  11.22497216]])
>>> sqrt((x - y).dot((x - y).T))
array([[  0.        ,   0.        ,   0.        ,   0.        ],
       [  0.        ,   5.19615242,   7.34846923,   9.        ],
       [  0.        ,   7.34846923,  10.39230485,  12.72792206],
       [  0.        ,   9.        ,  12.72792206,  15.58845727]])

第二个结果的对角线是你正在寻找的,但是全矩阵乘法会做太多额外的工作。以下是我通常只对角线的说法,粗略地说:

>>> sqrt(((x - y) * (x - y)).sum(axis=1))
array([  0.        ,   5.19615242,  10.39230485,  15.58845727])

简而言之,在这种特殊情况下,您实际上希望进行广播。