彻底剖析numpy的数值运算

来源:互联网 发布:pdf.js 打开 word文档 编辑:程序博客网 时间:2024/05/25 18:09

彻底剖析numpy的数值运算

1.矢量与标量的运算

>>> a = np.array([1, 2, 3, 4])>>> a + 1array([2, 3, 4, 5])>>> 2**aarray([ 2,  4,  8, 16])

2.矢量之间进行点运算

>>> b = np.ones(4) + 1>>> a - barray([-1.,  0.,  1.,  2.])>>> a * barray([ 2.,  4.,  6.,  8.])>>> j = np.arange(5)>>> 2**(j + 1) - jarray([ 2,  3,  6, 13, 28])

当然,numpy对于这些操作都做了十分细致的优化。

>>> a = np.arange(10000)>>> %timeit a + 1  10000 loops, best of 3: 24.3 us per loop>>> l = range(10000)>>> %timeit [i+1 for i in l] 1000 loops, best of 3: 861 us per loop

值得注意的是,两个array之间进行*运算,并不是进行矩阵相乘(如果想进行矩阵间相乘,应该调用dot()方法)。

>>> c = np.ones((3, 3))>>> c * c                   # NOT matrix multiplication!array([[ 1.,  1.,  1.],       [ 1.,  1.,  1.],       [ 1.,  1.,  1.]])>>> c.dot(c)array([[ 3.,  3.,  3.],       [ 3.,  3.,  3.],       [ 3.,  3.,  3.]])

3.比较运算

>>> a = np.array([1, 2, 3, 4])>>> b = np.array([4, 2, 2, 4])>>> a == barray([False,  True, False,  True], dtype=bool)>>> a > barray([False, False,  True, False], dtype=bool)
>>> a = np.array([1, 2, 3, 4])>>> b = np.array([4, 2, 2, 4])>>> c = np.array([1, 2, 3, 4])>>> np.array_equal(a, b)False>>> np.array_equal(a, c)True

4.逻辑运算

>>> a = np.array([1, 1, 0, 0], dtype=bool)>>> b = np.array([1, 0, 1, 0], dtype=bool)>>> np.logical_or(a, b)array([ True,  True,  True, False], dtype=bool)>>> np.logical_and(a, b)array([ True, False, False, False], dtype=bool)

5.超越函数

>>> a = np.arange(5)>>> np.sin(a)array([ 0.        ,  0.84147098,  0.90929743,  0.14112001, -0.7568025 ])>>> np.log(a)array([       -inf,  0.        ,  0.69314718,  1.09861229,  1.38629436])>>> np.exp(a)array([  1.        ,   2.71828183,   7.3890561 ,  20.08553692,  54.59815003])

6.转置操作

>>> a = np.triu(np.ones((3, 3)), 1)   # see help(np.triu)>>> aarray([[ 0.,  1.,  1.],       [ 0.,  0.,  1.],       [ 0.,  0.,  0.]])>>> a.Tarray([[ 0.,  0.,  0.],       [ 1.,  0.,  0.],       [ 1.,  1.,  0.]])

请注意!!转置操作返回的是原array的视图,即两者共享内存。

7.求和聚合

>>> x = np.array([1, 2, 3, 4])>>> np.sum(x)10>>> x.sum()10

或者,分别对每一行/列进行求和聚合:

>>> x = np.array([[1, 1], [2, 2]])>>> xarray([[1, 1],       [2, 2]])>>> x.sum(axis=0)   # 列聚合array([3, 3])>>> [x[:, 0].sum(), x[:, 1].sum()]  # ←相当于[3, 3]>>> x.sum(axis=1)   # 行聚合array([2, 4])>>> [x[0, :].sum(), x[1, :].sum()]  # ←相当于[2, 4]

求和聚合

相同地,求和聚合也适用于更高维度的情况:

>>> x = np.array([[[1, 2], [3, 4]],[[5, 6], [7, 8]]])>>> x.sum(axis=2)[[ 3  7] [11 15]]>>> [[x[0, 0, :].sum(), x[0, 1, :].sum()], [x[1, 0, :].sum(), x[1, 1, :].sum()]]    # ←相当于[[3, 7], [11, 15]]

8.其他聚合操作

其他聚合操作的用法与上面介绍的求和聚合大同小异:

8.1.求极值

>>> x = np.array([1, 3, 2])>>> x.min()1>>> x.max()3>>> x.argmin()  # 最小值的索引下标0>>> x.argmax()  # 最大值的索引下标1

8.2.逻辑聚合

>>> np.all([True, True, False])     # 相当于所有元素进行and的reduce操作False>>> np.any([True, True, False])     # 相当于所有元素进行or的reduce操作True

逻辑聚合常常与比较运算一起使用:

>>> a = np.zeros((100, 100))>>> np.any(a != 0)False>>> np.all(a == a)True>>> a = np.array([1, 2, 3, 2])>>> b = np.array([2, 2, 3, 2])>>> c = np.array([6, 4, 4, 5])>>> ((a <= b) & (b <= c)).all()True

8.3.其他统计值

>>> x = np.array([1, 2, 3, 1])>>> y = np.array([[1, 2, 3], [5, 6, 1]])>>> x.mean()1.75>>> np.median(x)1.5>>> np.median(y, axis=-1) # 最后一维,即进行行聚合array([ 2.,  5.])>>> x.std()     # 求标准差 0.82915619758884995

9.广播机制

对于不同维度大小的array,同样可以进行运算,可以视作是低维度array对于高维度array的“广播”或者“扩散”。

>>> a = np.tile(np.arange(0, 40, 10), (3, 1)).T>>> aarray([[ 0,  0,  0],       [10, 10, 10],       [20, 20, 20],       [30, 30, 30]])>>> b = np.array([0, 1, 2])>>> a + barray([[ 0,  1,  2],       [10, 11, 12],       [20, 21, 22],       [30, 31, 32]])

如果还是不理解,可以参考下图,以下的三个矩阵运算在广播机制的作用下其实是一样的:

广播操作

“广播机制”还存在于赋值运算中,下面的小技巧可谓方便且实用:

>>> a = np.ones((4, 5))>>> aarray([[ 1.,  1.,  1.,  1.,  1.],       [ 1.,  1.,  1.,  1.,  1.],       [ 1.,  1.,  1.,  1.,  1.],       [ 1.,  1.,  1.,  1.,  1.]])>>> a[0] = 2>>> aarray([[ 2.,  2.,  2.,  2.,  2.],       [ 1.,  1.,  1.,  1.,  1.],       [ 1.,  1.,  1.,  1.,  1.],       [ 1.,  1.,  1.,  1.,  1.]])

10.shape操作

10.1.展开操作(ravel)

将任意shape的array统一展开为一个一维array

>>> a = np.array([[1, 2, 3], [4, 5, 6]])>>> a.ravel()array([1, 2, 3, 4, 5, 6])>>> a.Tarray([[1, 4],       [2, 5],       [3, 6]])>>> a.T.ravel()array([1, 4, 2, 5, 3, 6])

10.2.Reshape操作

Reshape操作可以看作是ravel的逆操作

>>> a.shape(2, 3)>>> b = a.ravel()>>> b = b.reshape((2, 3))>>> barray([[1, 2, 3],       [4, 5, 6]])

或者直接对原始array进行Reshape操作

>>> a.reshape((2, -1))    # -1代表该数值根据a的元素总数动态计算得出array([[1, 2, 3],       [4, 5, 6]])

!!!值得注意的是:reshape()函数的返回值有可能是视图,也有可能是全新的拷贝

10.3.维度追加

如果使用np.newaxis对象作为array的索引下标,就可以进行追加维度的操作。

>>> z = np.array([1, 2, 3])>>> zarray([1, 2, 3])>>> z[:, np.newaxis]        # 相当于z.reshape((3, 1))array([[1],       [2],       [3]])>>> z[np.newaxis, :]        # 相当于z.reshape((1, 3))array([[1, 2, 3]])

10.4.维度替换

>>> a = np.arange(4*3*2).reshape(4, 3, 2)>>> a.shape(4, 3, 2)>>> a[0, 2, 1]5>>> b = a.transpose(1, 2, 0)>>> b.shape(3, 2, 4)>>> b[2, 1, 0]5

当然,维度替换的返回值是毋庸置疑的视图。

10.5.Resize操作

它的用法和作用与Reshape操作相类似

>>> a = np.arange(4)>>> a.resize((8,))>>> aarray([0, 1, 2, 3, 0, 0, 0, 0])

但是它只能用于只有一个引用变量的array,否则会报错:

>>> b = a>>> a.resize((4,))   Traceback (most recent call last):  File "<stdin>", line 1, in <module>ValueError: cannot resize an array that has been referenced or isreferencing another array in this way.  Use the resize function

11.排序操作

以某个维度为轴进行排序操作:

>>> a = np.array([[4, 3, 5], [1, 2, 1]])>>> b = np.sort(a, axis=1)>>> barray([[3, 4, 5],       [1, 1, 2]])

也可以获取排序后各元素在原array中的索引下标:

>>> a = np.array([4, 3, 1, 2])>>> j = np.argsort(a)>>> jarray([2, 3, 1, 0])>>> a[j]array([1, 2, 3, 4])
原创粉丝点击