numpy之广播

广播的原则:

       如果两个数组的后缘维度(从末尾开始算起的维度)的轴长度相符或其中一方的长度为1,则认为他们是广播兼容的。广播会在缺失和(或)长度为1的维度长进行。

看几个例子理解一下:

In [223]: arr = np.arange(4)
In [224]: arr
Out[224]: array([0, 1, 2, 3])
In [225]: arr*3               #  比较简单的广播的例子
Out[225]: array([0, 3, 6, 9])

低维度的值可以被广播到数组的任意维度:

In [226]: arr = np.array([[1],[2],[3]])
In [227]: arr
Out[227]: 
array([[1],[2],[3]])
In [228]: arr.shape
Out[228]: (3, 1)
In [229]: other_arr = np.array([1,2,3])
In [230]: arr + other_arr
Out[230]: 
array([[2, 3, 4],
       [3, 4, 5],
       [4, 5, 6]])
In [231]: other_arr.shape
Out[231]: (3,)

arr的shape是(3,1)后缘维度长度为1,other_arr的shape是(3, ),other_arr低维度的值被广播到arr高维度的任意维度。

在看一个例子:

In [232]: arr = np.random.randn(4,3)
In [233]: m = arr.mean(0)
In [234]: m
Out[234]: array([ 0.10478714,  0.93317107, -0.01853336])
In [235]: arr - m
Out[235]: 
array([[ 0.53074894, -1.43334657,  1.11937261],
       [-0.09741141,  1.83929851,  0.91581349],
       [-0.51180403,  0.51003558,  0.1602767 ],
       [ 0.07846651, -0.91598753, -2.19546281]])
In [236]: (arr - m).mean(0)
Out[236]: array([2.08166817e-17, 1.38777878e-16, 0.00000000e+00])
上面这个例子的arr.shape是(4,3)后缘维度是3,而m的长度为3,所以可以在0轴上进行广播。

看图理解一下:


上面的那个例子如果在行上计算平均值就不一样:

In [240]: m = arr.mean(1)
In [241]: m
Out[241]: array([ 0.41206661,  1.22570848,  0.39264437, -0.6711
8633])
In [242]: arr - m
---------------------------------------------------------------
ValueError                    Traceback (most recent call last)
<ipython-input-242-33627b173828> in <module>()
----> 1 arr - m
ValueError: operands could not be broadcast together with shape
s (4,3) (4,)
In [243]: arr - m.reshape(4,1)
Out[243]: 
array([[ 0.22346946, -0.91224211,  0.68877264],
       [-1.21833276,  1.54676111, -0.32842835],
       [-0.79966126,  1.05056229, -0.25090103],
       [ 0.85443997,  0.68836987, -1.54280984]])

上面这个例子的arr.shape是(4,3)后缘维度是3,而m的长度为4,不符合广播原则,所以出错。要想正确在行上做减法,就必须改变其shape为(4,1)

看一下多维的情况:


第一个数组的后缘维度是(4,2) ,第二个数组的shape是(4,2),符合广播原则

对于多维的情况,任何一维上的广播就是将数据重塑为兼容的形状。

下图是三维数组各维度上广播形状的需求:


为了简化重塑形状的过程,numpy提供了一个通过索引机制插入轴来重塑形状 的特殊语法。

In [246]: arr = np.zeros((4,4))
In [247]: re_arr = arr[:,np.newaxis,:]
In [248]: re_arr.shape
Out[248]: (4, 1, 4)
In [250]: arr = np.array([1,2,3])
In [251]: arr.shape
Out[251]: (3,)
In [252]: arr_1 = arr[:,np.newaxis]
In [253]: arr_1.shape
Out[253]: (3, 1)
In [254]: arr_1 = arr[np.newaxis,:]
In [256]: arr_1.shape
Out[256]: (1, 3)

看一个栗子,对一个三维数组的轴2距平化:

In [257]: arr = np.random.randn(3,4,5)
In [258]: m2 = arr.mean(2)
In [259]: m2
Out[259]: 
array([[ 0.13649416,  0.10628038, -0.07967465,  0.77251529],
       [-0.02079456, -0.26046433, -0.03397547, -0.00820266],
       [-0.17323542,  0.23429955, -0.76819986, -0.18061328]])
In [260]: re = arr - m2[:,:,np.newaxis]
In [262]: re.mean(2)           #  结果大概就都是0
Out[262]: 
array([[ 2.22044605e-17, -2.22044605e-17,  2.22044605e-17,
         2.22044605e-17],
       [ 4.44089210e-17,  0.00000000e+00,  0.00000000e+00,
         1.11022302e-17],
       [ 0.00000000e+00,  3.88578059e-17, -8.88178420e-17,
         4.44089210e-17]])

### NumPy 广播机制概述 NumPy广播机制是一种强大的功能,允许具有不同形状的数组进行算术运算或其他操作。当两个数组的形状不完全相同时,NumPy 会尝试通过扩展较小的数组来匹配较大的数组形状[^3]。 #### 广播规则 NumPy 广播遵循以下规则: 1. 如果两个数组的维度数不同,则会在较小子数组前添加大小为 1 的轴,直到两者的维度相同。 2. 对于每一维,如果其中一个数组在此维度上的长度为 1 或两者长度相等,则可以继续广播;否则抛出错误。 以下是具体实现和验证的方法: ```python import numpy as np def can_broadcast(shape1, shape2): try: np.broadcast_shapes(shape1, shape2) return True except ValueError: return False ``` 此函数可用于测试两种形状是否能够成功广播[^1]。 --- ### 广播机制的实际应用 下面是一个简单的例子展示如何利用广播机制完成数组间的加法操作: ```python import numpy as np # 创建一个二维数组 A 和一维数组 B A = np.array([[1, 2], [3, 4]]) B = np.array([5]) # 利用广播机制将标量 5 加到数组 A 的每个元素上 C = np.add(A, B) print(C) ``` 运行以上代码的结果将是 `[[6, 7], [8, 9]]`,这表明标量被自动扩展成与数组 A 形状相同的结构并完成了逐元素加法操作[^2]。 更复杂的场景下,比如处理多个维度的数据时,也可以轻松运用广播特性来进行计算而无需显式地复制数据或调整其尺寸。 --- ### 更高级的应用实例 考虑如下情况:我们需要对三维矩阵中的每张图片加上不同的偏移值。 ```python images = np.random.rand(10, 32, 32) # 假设有 10 张灰度图像 (高度=32 宽度=32) offsets = np.arange(10).reshape(-1, 1, 1) # 不同的偏移量给定为 (10,) 向量 adjusted_images = images + offsets # 自动广播至适合的操作形式 ``` 在这里,尽管 `offsets` 是一个 `(10, 1, 1)` 大小的一维向量,但由于广播的存在,它会被视为 `(10, 32, 32)` 来执行逐像素级别的增加动作[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值