第九天
Numpy聚合和广播
一、Numpy聚合函数
当你面对大量的数据时,第一个步骤通常是计算相关数据的概括统计值。最常用的概括统计值可能是均值和标准差,这两个值能让你分别概括出数据集中的“经典”值,但是其他一些形式的聚合也是非常有用的(如求和、乘积、中位数、最小值和最大值、分位数等等)。
1.数组值求和
import numpy as np
L = np.random.random(100)
sum(L) # Python的内置求和函数
np.sum(L) # numpy的求和函数
---------------
# 用的anaconda3发现这两者的sum结果不一样???精度差了一点
但是Numpy的sum函数在编码过程中执行操作的,所以Numpy的操作计算更快一些。
2.最大值和最小值
同样,Python也有内置的min函数和max函数,分别被用于获取给定数组的最小值和最大值:
min(L)
max(L)
--------
np.max(L)
np.min(L)
对于min、max、sum和其他的一些Numpy聚合函数,一种更简洁的语法形式是数组对象直接调用这些方法:
L.min()
L.max()
L.sum()
3.多维度聚合
一种常用的聚合操作是沿着一行或一列聚合。例如,假设你有一些数据存储在二维数组中:
M = np.random.random((3, 4))
M.sum()
默认情况下,每一个Numpy聚合函数将会返回对整个数组的聚合结果。
聚合函数还有一个参数,用于指定沿着哪个轴进行聚合。例如,可以指定axis=0找到每一列的最小值:
M.min(axis=0)
------------
结果会返回四个值,分别对应四列数字的计算值。
同样,可以指定axis=1,找到每一行的最小值。
M.min(axis=1)
下表示Numpy中可用的聚合函数:
函数名称 | 描述 |
---|---|
np.sum | 计算元素的和 |
np.prod | 计算元素的积 |
np.mean | 计算元素的平均值 |
np.std | 计算元素的标准差 |
np.var | 计算元素的方差 |
np.min | 找出最小值 |
np.max | 找出最大值 |
np.argmin | 找出最小值索引 |
np.argmax | 找出最大值索引 |
np.median | 计算元素的中位数 |
np.percentile | 计算基于元素排序的统计值 |
np.any | 验证任何一个元素是否为真 |
np.all | 验证所有元素是否为真 |
二、数组的计算:广播
前面有介绍Numpy如果通过通用函数的向量化操作来减少缓慢的Python循环,另外一种向量化的操作是利用Numpy的广播功能。广播可以简单理解为用于不同于大小数组的二进制通用函数的一组规则。
1.广播的介绍
对于同样大小的数组,二进制操作是对相应元素逐个计算:
import numpy as np
a = np.array([0, 1, 2])
b = np.array([5, 5, 5])
a + b # [5, 6, 7]
广播允许这些二进制操作可以用于不同大小的数组。比如:
a + 5 # 将一个标量和数组相加
我们可以认为这个操作是将数字5扩展或重复至数组[5, 5, 5],然后执行加法。但是广播的好处是,这种对值的重复操作实际上并没有发生。
同样,我们可以将这个原理扩展到更高维的数组。观察以下,将一个数组和一个二维数组相加的结果:
M = np.ones((3, 3))
M + a
2.广播的规则
Numpy的广播遵循一组严格的规则,设定这组规则是为了决定两个数组间的操作。
规则1:如果两个数组的维度数不相同,那么小维度数组的形状会将在最左边补1。
规则2:如果两个数组的形状在任何一个维度上都不匹配,那么数组的形状会沿着维度为1的维度扩展以匹配另外一个数组的形状。
规则3:如果两个数组的形状在任何一个维度上都不匹配并且没有任何一个维度等于去,俺么会引发异常。
示例1:
M = ones((2, 3)) # [[1., 1., 1.], [1., 1., 1.]]
a = np.arange(3) # [0, 1, 2]
----------------
M.shape = (2, 3)
a.shape = (3,)
--------------执行加法操作
根据规则1,数组a的维度小,所以在其左边补1:
M.shape ->(2, 3)
a.shape ->(1, 3)
根据规则2,第一维度不匹配,因此扩展这个维度:
M.shape ->(2, 3)
a.shape ->(2, 3)
M + a
----------
[[1., 2., 3.],
[1., 2., 3.]]
示例2:
两个数组都需要广播
a = np.arange(3).reshape((3, 1)) #[[0], [1], [2]]
b = np.arange(3) # [0, 1, 2]
-------------
a.shape = (3, 1)
b.shape = (3,)
--------------
根据规则1,需要用1将b的形状补全
a.shape -> (3, 1)
b.shape -> (1, 3)
根据规则2,需要更新着两个数组的维度来相互匹配
a.shape -> (3, 3)
b.shape -> (3, 3)
a + b
----------------
[[0, 1, 2],
[1, 2, 3],
[2, 3, 4]]
3.广播的实际应用:数据归一化
通用函数可以让Numpy免于写很慢的Python循环。广播进一步扩展了这个功能,一个常见的例子就是数组数据的归一化。假设你有一个有10个观察值的数组,每个观察值包含3个数值。
x = np.random.random((10, 3))
计算每个特征的均值,计算方法是利用mean函数沿着第一个维度(列维度)聚合
xmean = x.mean(0)
现在通过从x数组中的元素减去这个均值实现归一化(这就是一个广播操作)
x_centered = x - xmean