Numpy

简介: Numpy

每日分享

You cannot protect yourself from sadness without protecting yourself from happiness.

稳不住幸福,亦躲不过悲伤。



Numpy

1.简单了解Numpy

Numpy是一个开源的Python科学计算库,用于快速处理任意维度的数组,支持常见的数组和矩阵操作。

使用Numpy需要先安装这个模块。

Numpy使用 ndarray对象来处理多维数组,而且 ndarray中所有元素的类型都是相同的。我们先来看看怎么创建一个 ndarray

  1. import numpy as np
  2. np.array(列表)

注意:本文中所使用的np都指 numpy

2.Numpy的优势

2.1内存块的分割

ndarray在存储数据的时候,数据与数据的地址都是连续的,一体式存储使得批量操作数组元素的时候速度更快。而python中的列表元素类型是任意的,采用分离式存储,这样就使得list只能通过地址方式找到下一个元素。因此 numpyndarray在科学计算中大放异彩。

2.2ndarray支持并行化运算(向量化运算)

2.3解除了GIL

numpy底层使用了C语言编写,内部解除了GIL,其对数组的操作速度不受python解释器的限制,所以其效率远高于纯python代码。

3.N维数组-ndarray

3.1属性

ndarray.shape代表的是数组维度的元组。
1. In [3]: np.array([[1,2,3],[4,5,6]]).shape
2. Out[3]: (2, 3)   # 二维数组
ndarray.ndim代表的是数组维数。
1. In [4]: np.array([[1,2,3],[4,5,6]]).ndim
2. Out[4]: 2
ndarray.size代表的是数组中元素数量。
1. In [5]: np.array([[1,2,3],[4,5,6]]).size
2. Out[5]: 6
ndarray.itemsize代表的是一个数组元素的长度(字节)。
1. In [7]: np.array([[1,2,3],[4,5,6]]).itemsize
2. Out[7]: 8
ndarray.dtype代表的是数组元素类型。
1. In [8]: np.array([[1,2,3],[4,5,6]]).dtype
2. Out[8]: dtype('int64')
3.2形状

数组分为一维数组、二位数组、三维数组到N维数组。一维数组类似是线性结构;二维数组则是有两个方向,可以简单的理解为咱们的表;三维数组则可以理解为多张表在另一个方向的叠加。N维数组无法比喻。

3.3类型

我们上面说过了, dtype属性即元素类型,我们也知道 ndarray中的元素类型一致,那么类型都有哪些呢?看下面表格:

名称 描述 简写
np.bool 用一个字节存储的布尔类型(True或False) 'b'
np.int8 一个字节大小,-128 至 127 'i'
np.int16 整数,-32768 至 32767 'i2'
np.int32 整数,-2^31 至 2^31 -1 'i4'
np.int64 整数,-2^63 至 2^63 - 1 'i8'
np.uint8 无符号整数,0 至 255 'u'
np.uint16 无符号整数,0 至 65535 'u2'
np.uint32 无符号整数,0 至 2^32 - 1 'u4'
np.uint64 无符号整数,0 至 2^64 - 1 'u8'
np.float16 半精度浮点数:16位,正负号1位,指数5位,精度10位 'f2'
np.float32 单精度浮点数:32位,正负号1位,指数8位,精度23位 'f4'
np.float64 双精度浮点数:64位,正负号1位,指数11位,精度52位 'f8'
np.complex64 复数,分别用两个32位浮点数表示实部和虚部 'c8'
np.complex128 复数,分别用两个64位浮点数表示实部和虚部 'c16'
np.object_ python对象 'O'
np.string_ 字符串 'S'
np.unicode_ unicode类型 'U'

我们创建数组的时候可以指定类型:

In [17]: np.array(['python','ethanyan'],dtype=np.string_).dtype
Out[17]: dtype('S8')

注意:如果不指定类型,整数默认是 int64,小数默认是 float64

4.基本操作

4.1生成数组

4.1.1生成0和1的数组

np.zeros()
np.ones()
np.zeros_like()
np.ones_like()

以生成0的数组为例:

In [18]: np.zeros([3,4])
Out[18]: 
array([[0., 0., 0., 0.],
       [0., 0., 0., 0.],
       [0., 0., 0., 0.]])
In [19]: np.zeros_like([[1,2],[1,1]])
Out[19]: 
array([[0, 0],
       [0, 0]])

可以看到 zeros中指定数组的形状维度,而 zeros_like是传入一个数组,仿照其形状生成一个新的数组。

4.1.2从现有的数组中生成

a = np.array([[1,2,3],[4,5,6]])
# 从现有的数组当中创建
a1 = np.array(a)
# 相当于索引的形式,并没有真正的创建一个新的
a2 = np.asarray(a)

需要传入一个数组,然后生成一个一模一样的数组。 array类似于深拷贝, asarray则类似于浅拷贝。

4.1.3生成固定范围的数组

np.linspace(start,stop,num,endpoint)
# start 序列的起始值
# stop 序列的终止值,
# num 要生成的等间隔样例数量,默认为50
# endpoint 序列中是否包含stop值,默认为ture
np.arange(start,stop, step, dtype)
np.logspace(start,stop, num)

linspace生成等间隔的数组,其中num指定的是生成的数组中有多少个样例。

In [21]: np.linspace(0,100,11)
Out[21]: array([  0.,  10.,  20.,  30.,  40.,  50.,  60.,  70.,  80.,  90., 100.])

arange生成固定间隔的数组,其中的step指的是间隔大小。

In [22]: np.arange(10,50,2)
Out[22]: 
array([10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42,44, 46, 48])

logspace生成的则是10的指数的数据。

In [23]: np.logspace(0,2,3)
Out[23]: array([  1.,  10., 100.])

其中0,2代表的是从 10^010^2也就是1到100。3指的是生成固定间隔的3个样例。

4.1.4生成随机数组

生成均匀分布数组:

np.random.uniform(low, high, size)
# low: 采样下界,float类型,默认值为0;
# high: 采样上界,float类型,默认值为1;
# size: 输出样本数目,为int或元组(tuple)类型。缺省时输出1个值。
# 返回值:ndarray类型,其形状和参数size中描述一致。例如,size=(m,n,k),仿照我们之前看到的维度的元组。

上面的功能是从一个均匀分布左开右闭的区间 [low,high)中随机采样。

生成正态分布数据:

np.random.normal(loc=0.0, scale=1.0, size=None)
# loc:float;此概率分布的均值(对应着整个分布的中心centre)
# scale:float;此概率分布的标准差(对应于分布的宽度,scale越大越矮胖,scale越小,越瘦高)
# size:int or tuple of ints;输出的shape,默认为None,只输出一个值

4.2数组的索引和切片

我们用一个难一点的例子来说明一下:

In [25]: a1 = np.array([ [[1,2,3],[4,5,6]], [[12,3,34],[5,6,7]]])
In [26]: a1        
Out[26]: 
array([[[ 1,  2,  3],
        [ 4,  5,  6]],
       [[12,  3, 34],
        [ 5,  6,  7]]])
In [27]: a1[0,0,1]
Out[27]: 2

注意:获取的时候先行后列,直接通过 []获取即可。

4.3形状修改

  1. 对象.reshape(shape)
  2. # shape代表的是要转换成的数组的形状
  3. # shape可以不指定行或者列,然后通过-1表示。最后的结果计算机自动计算,但是结果必须可以整除,不能来一个1.5行的数组。
  4. # 如:[-1,20]代表的是不知道多少行,但是生成20列。

注意:没有进行行列互换,而是按顺序原先元素顺序重新分组,新产生了一个 ndarray

  1. 对象.resize()

注意:没有进行行列互换,而且是在原来的 ndarray上修改。

  1. 对象.T

注意:进行了行列互换,而且产生了新的 ndarray

4.4类型修改

ndarray.astype(type)
ndarray.tostring()
ndarray.tobytes()

4.5数组去重

  1. np.unique(ndarray)

例如:

In [28]: np.unique(np.array([[1, 2, 3, 4],[3, 4, 5, 6]]))    
Out[28]: array([1, 2, 3, 4, 5, 6])

5.ndarray运算

5.1逻辑运算

可以直接通过大于号小于号进行运算,返回的是一个数组,其中符合条件的地方标记为True,不符合条件的地方标记为False。

5.2通用判断函数

判断所有元素是否符合条件,如果符合返回True,反之False。

  1. np.all()

判断其中是否有满足条件的元素,有则返回True。

  1. np.any()

5.3三元运算符

我们可以使用 where来进行更加复杂的运算。比如我们判断股票的涨跌幅,数据为 temp,大于0的置为1,否则为0。

  1. np.where(temp >0,1,0)

还可以进行更加复杂的判断。结合两个函数的使用。 np.logical_andnp.logical_or代表的是与和或。

  1. # 判断股票涨跌幅 大于0.5并且小于1的,换为1,否则为0
  2. np.where(np.logical_and(temp >0.5, temp <1),1,0)
  3. # 判断股票涨跌幅 大于0.5或者小于-0.5的,换为1,否则为0
  4. np.where(np.logical_or(temp >0.5, temp <-0.5),1,0)

5.4统计运算

np.max()是最大。

np.main()是最小。

np.std是标准差。

np.mean()是平均值。

np.argmax()是数组中最大值的位置。

np.argmin()是数组中最小值的位置。

注意:在运算的函数里都有一个参数axis,其中0代表列,1代表行。

6.数组间的运算

6.1数组和数的运算

In [29]: arr = np.array([[1,2,3,2,1,4],[5,6,1,2,3,1]])
In [30]: arr + 1
Out[30]: 
array([[2, 3, 4, 3, 2, 5],
       [6, 7, 2, 3, 4, 2]])
In [31]: arr / 2
Out[31]: 
array([[0.5, 1. , 1.5, 1. , 0.5, 2. ],
       [2.5, 3. , 0.5, 1. , 1.5, 0.5]])

可以看到数组和数能进行计算,而且类似咱们线性代数中的矩阵运算。

6.2数组和数组运算

数组和数组之间的运算符合广播机制。那么什么是广播机制呢?

在进行矩阵运算的时候,我们都知道加法是行列相等的时候才可以进行,而且对应位置元素进行加法运算。进行乘法的时候,m×n 的矩阵乘以 n×1 的向量,得到的是 m×1 的向量。

在数组与数组进行运算的时候,如果两个数组形状不相等,我们可以通过扩展数组的方法来实现相加减等运算,这种机制就是广播机制。但是它也是有原则的人,并不是所有的数组都可以进行运算的。只有符合下面情况,才可以:

1.维度相同,其中有个对应的轴长为1。

给大家举个例子。比如有两个数组,他们的shape分别为(4,3)和(4,1)。或者shape分别为(3,5,6)和(3,1,6)。再或者(1,2,1)和(5,2,6)。他们都符合维度相同,在不同轴上,要么相同,要么对应的轴有一个为1。

2.维度不相同,后缘维度(从末尾开始算起的维度)的轴长相同。

同样举例子说明。两个数组分别为(256,256,3)和(3,),虽然维度不同,但是都从尾部开始算,后一个数组后缘维度的轴长为3,前一个数组也是如此,符合广播机制可以运算。再比如(12,5,2)和(5,2)。

3.前两条可以综合。如(9,1,7,1)和(8,1,5)也符合广播机制,可以运算。

  1. 9 x 1 x 7 x 1
  2.    8 x 1 x 5

6.3矩阵乘法

矩阵乘法有两个api,分别是:

  1. np.matmul(a,b)  # a和b为两个数组
  2. np.dot(a,b)

我们先来演示一下:

In [35]: a = np.array([[80, 86], 
    ...: [82, 80], 
    ...: [85, 78], 
    ...: [90, 90], 
    ...: [86, 82], 
    ...: [82, 90], 
    ...: [78, 80], 
    ...: [92, 94]])
In [36]: b = np.array([[0.7],[0.3]])
In [37]: np.matmul(a,b)
Out[37]: 
array([[81.8],
       [81.4],
       [82.9],
       [90. ],
       [84.8],
       [84.4],
       [78.6],
       [92.6]])
In [39]: np.dot(a,b)
Out[39]: 
array([[81.8],
       [81.4],
       [82.9],
       [90. ],
       [84.8],
       [84.4],
       [78.6],
       [92.6]])

可以看到两种方法在计算上面的例子时,结果一样。那么他们有区别吗?答案是肯定的。

区别

np.matmul中禁止矩阵与标量的乘法。 在矢量乘矢量的內积运算中, np.matmulnp.dot没有区别。

6.4矩阵应用场景

大部分的机器学习算法都需要用到矩阵。当然也不难理解,算法嘛,为什么很多岗位招的是计算机或者数学,因为算法运用的都是数学知识,计算机像这些模块只是工具,算法数学才是精髓。

相关文章
|
6月前
|
Python
numpy快速使用
numpy快速使用
50 6
numpy快速使用
|
3月前
|
Python
NumPy 教程 之 NumPy 算术函数 1
本教程介绍NumPy中的基本算术函数,如加(add())、减(subtract())、乘(multiply())及除(divide())。示例展示了两个数组(一个3x3矩阵与一数组[10,10,10])间的运算。值得注意的是,参与运算的数组需有相同形状或可按照NumPy的广播规则进行扩展。此外Numpy还提供了许多其他的算术函数以满足复杂计算需求。
43 7
|
3月前
|
Python
NumPy 教程 之 NumPy 算术函数 2
NumPy 教程 之 NumPy 算术函数 2
34 3
|
22天前
|
存储 机器学习/深度学习 并行计算
介绍一下NumPy
【10月更文挑战第22天】介绍一下NumPy
30 2
|
2月前
|
XML 存储 数据格式
|
2月前
|
存储 Python
|
2月前
|
Python
|
3月前
|
机器学习/深度学习 算法 计算机视觉
厉害了,numpy!!!
厉害了,numpy!!!
|
3月前
|
vr&ar 索引 Python
Numpy学习笔记之Numpy练习
Numpy学习笔记之Numpy练习
|
3月前
|
Python
NumPy 教程 之 NumPy 算术函数 4
本教程详细介绍了NumPy库中的算术函数,包括基本的加、减、乘、除操作:add(),subtract(),multiply() 和 divide(),需确保处理的数组形状一致或满足广播规则。通过`numpy.mod()`及`numpy.remainder()`函数示例展示了如何计算数组元素间的除法余数。两个函数在此例中产生相同结果:对于数组 [10,20,30] 和 [3,5,7],输出余数分别为 [1,0,2]。
47 3

相关课程

更多