NumPy ndarray广播-形状(X,)与(X,1)一起使用(X,Y) [英] NumPy ndarray broadcasting - shape (X,) vs (X, 1) to operate with (X,Y)
问题描述
我有一个NumPy ndarray
,其形状为(32,1024),并保存32个信号测量值,我希望将它们组合成一个1024个元素长的数组,每个32个元素的权重都不同. numpy.average
,但是我的权重很复杂,average
根据求和的结果对权重进行归一化.
I have a NumPy ndarray
which is shaped (32, 1024) and holds 32 signal measurements which I would like to combine into a single 1024 element long array, with a different weight for each of the 32. I was using numpy.average
but my weights are complex and average
performs a normalisation of the weights based on the sum which throws off my results.
看代码的平均值,我意识到我可以通过将权重乘以信号数组然后在第一轴上求和来完成相同的事情.但是,当我尝试将(32,)权重数组乘以(32,1024)信号数组时,由于(32,)无法广播到(32,1024)而导致尺寸不匹配.如果我将权重数组的形状重塑为(32,1),那么一切都会按预期工作,但是这会导致代码很丑陋:
Looking at the code for average I realised that I can accomplish the same thing by multiplying the weights by the signal array and then summing over the first axis. However when I try and multiply my (32,) weights array by the (32, 1024) signal array I get a dimension mismatch as the (32,) cannot be broadcast to (32, 1024). If I reshape the weights array to (32, 1) then everything works as expected, however this results in rather ugly code:
avg = (weights.reshape((32, 1)) * data).sum(axis=0)
有人能解释为什么NumPy不允许我的(32,)数组广播到(32,1024)和/或建议使用另一种更整洁的方法来执行加权平均值吗?
Can anybody explain why NumPy will not allow my (32,) array to broadcast to (32, 1024) and/or suggest an alternative, neater way of performing the weighted average?
推荐答案
用于在(X,)
和(X,Y)
形阵列之间对齐的通用设置
Generic setup for alignment between (X,)
and (X,Y)
shaped arrays
关于为什么(32,)
无法广播到(32, 1024)
的问题,这是因为形状未正确对齐.要将其放入示意图中,我们有:
On the question of why (32,)
can't broadcast to (32, 1024)
, it's because the shapes aren't aligned properly. To put it into a schematic, we have :
weights : 32
data : 32 x 1024
我们需要对齐唯一的轴,这是weights
的第一轴与data
的第一轴对齐.因此,您发现一种方法是将reshape
转换为2D
,这样我们最终将以单例尺寸作为第二轴.这可以通过使用
We need to align the only axis, which is the first axis of weights
aligned to the first axis of data
. So, as you discovered one way is to reshape
to 2D
, such that we would end up with a singleton dimension as the second axis. This could be achieved by introducing a new axis with None/np.newaxis
: weights[:,np.newaxis]
or weights[:,None]
or a simple reshape : weights.reshape(-1,1)
. Hence, going back to the schematic, with the modified version we would have :
weights[:,None] : 32 x 1
data : 32 x 1024
现在,形状已对齐,我们可以在这两个形状之间执行任何常规的按元素的操作,其结果示意图如下所示-
Now, that the shapes are aligned, we can perform any generic element-wise operation between these two with the result schematic looking like so -
weights[:,None] : 32 x 1
data : 32 x 1024
result : 32 x 1024
这将广播weights
,并且将对data
执行相应的逐元素操作,从而导致result
.
This would broadcast weights
and the relevant element-wise operation would be performed with data
resulting in result
.
解决我们的具体情况和替代方案
在上一节中的讨论之后,要解决我们的逐元素乘法的情况,将其为weights[:,None]*data
,然后沿axis=0
求和,即-
Following the discussion in previous section, to solve our case of element-wise multiplication, it would be weights[:,None]*data
and then sum along axis=0
, i.e. -
(weights[:,None]*data).sum(axis=0)
让我们寻找精巧的替代品!
Let's look for neat alternatives!
One neat and probably intuitive way would be with np.einsum
-
np.einsum('i,ij->j',weights,data)
另一种方法是使用 weights
的第一个轴与data
的第一个轴,就像这样-
Another way would be with matrix-multiplication using np.dot
, as we lose the first axis of weights
against the first axis of data
, like so -
weights.dot(data)
这篇关于NumPy ndarray广播-形状(X,)与(X,1)一起使用(X,Y)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!