使用Numpy广播将不同形状的矩阵或数组加减乘除
首先先强调一点很容易混淆的点:
- 一个shape为(4,)的np.array其实是一行!!一行4列!!而不是4行每行1个元素!!
- 上面说的这个👆array假设叫x,那么想把x加到一个shape为(9,4)的matrix上是可以直接加的,如果想要把x加到一个shape为(4,9)的matrix上要先转置!而且不能直接转置,因为一个array的转置的形状是不会变的。。正确做法是:先把x变成一个数组,之后再对这个数组转置,这时候x的形状就已经变成了(4,1),成了真正的4行每行1列,也就可以把它加到shape为(4,9)的matrix上去喽~
在我们所以Numpy的过程中,常常会有大量的矩阵数组需要运算,但是不同类型的Numpy怎样进行加减乘除呢?这就要用到我们Numpy的广播。
快速入门Numpy广播
Numpy的广播既是在2个不同的矩阵运算过程中,Numpy将较小的数组拉伸成较大数组的形状(shape),然后Numpy加减乘除不同矩阵的加减乘除运算,好的没我们来看一下一个例子:
1 | a = np.array([3.0, 4.0, 5.0, 6.0]) |
将会出现这样的错误ValueError: operands could not be broadcast together with shapes (3,), (2,)
, 在这里,我们只需要将a转换成一个2维数组,即可进行广播,如:
1 | a = np.array([3.0, 4.0, 5.0, 6.0]) |
好的到这里其实主要我们已经将完了所有的内容,如果你想要了解更多,可以查看下面的内容,其实都是一些描述性的,我觉得不是那么有必要看
什么是Numpy广播
广播术语描述了在算术运算过程中numpy如何处理具有不同形状的数组。受到某些约束,较小的数组是跨越较大阵列的“广播”,以便它们具有兼容的形状。广播提供了一种向量化数组操作的方法,以便循环发生在C而不是Python中。它不会造成不必要的数据副本,通常会导致高效的算法实现。然而,广播是一个坏主意,因为它导致低效的内存使用减慢了计算的情况。
NumPy操作通常是在逐个元素的基础上完成的。在最简单的情况下,两个阵列必须具有完全相同的形状,如下例所示:
1 | a = np.array([3.0, 4.0, 5.0]) |
当数组的形状满足某些限制时,NumPy的广播规则放宽了这个约束。当操作中组合数组和标量值时,会发生最简单的广播示例:
1 | a = np.array([3.0, 4.0, 5.0]) |
上面2个例子的结果相同,在计算期间,我们可以看作b被拉伸成与a相同的形状,新元素 b只是原始标量的副本。拉伸类比只是概念性的。NumPy足够聪明才能使用原始的标量值,而无需实际复制,因此广播操作尽可能地作为记忆和计算效率。
第二个示例中的代码比第一个示例中的代码更有效,因为广播在乘法期间移动较少的内存(b是标量而不是数组)。
一般广播规则
在两个数组上运行时,NumPy将元素的形状进行比较。它从尾随的维度开始,并向前推进。两个尺寸兼容
- 他们是平等的
- 其中一个是1
如果不满足这些条件, 则抛出异常,表示阵列具有不兼容的形状。结果数组的大小是输入数组的每个维度的最大大小。ValueError: frames are not aligned
接下来我们看一下一些具体的例子:
1 | >>> x = np.arange(4) |
广播提供了一种方便的方式来拍摄两个阵列的外部产品(或任何其他外部操作)。以下示例显示了两个1-d数组的外部加法运算:
1 | >>> a = np.array([0.0, 10.0, 20.0, 30.0]) |
这里,newaxis
索引操作符插入一个新轴a
,使其成为一个二维4x1
数组。将4x1
阵列与b
形状组合(3,)
,产生一个4x3
数组。