本文是书籍学习中摘录的Numpy相关知识
一、Numpy
Numpy是Python中最常见用于科学计算的基础包,提供:
多维数组对象、各种派生对象(如掩码数组MaskedArray 和 矩阵),以及一系列数组的操作(数学运算、逻辑运算、分片操作、排序、选择、输入输出、离散傅里叶变换、基本线性代数、基本统计运算、随机模拟)等。
Numpy的核心是ndarray对象,封装了相同数据类型的n维数组。
Numpy数组注意点:
- Numpy数组在创建时有固定大小,更改ndarray的大小将创建新的数组并删除原值。
- Numpy数组中的元素必须是相同的数据类型,内存中元素的大小相同。
- Numpy数组通常对大量数据进行高级数学运算和其他类型的操作,比python内置代码更高效
- 即使驶入是Python序列数组,但在高级计算前通常会转换为Numpy数组,相互转化的方式!
Numpy的主要对象是同种元素的多维数组。在Numpy中维度/dimensions 叫做 轴/axes,轴的个数叫 秩/rank。(轴长度指一个维度中的数组个数;秩就是维度的个数,二维数组的秩为2)
二、函数介绍
import numpy as np #numpy包头引入
1.ndarray的属性
在使用属性时,通常是查看ndarray对象中的一些属性(属性不是函数,不调用,可以认为是访问该对象的一些默认创建的“变量”),只需要如下使用:
print(ndarray.shape)
ndarray.ndim #数组轴的个数
ndarray.shape #数组的维度,n排m列的shape是(n,m)
ndarray.size #数组元素的总个数: n*m
ndarray.dtype #描述数组中元素类型
ndarray.itemsize #每个元素的字节大小,float64是8(64/8);
ndarray.data #通常不使用,包含实际数组元素的缓冲区
type(ndarray) #返回 numpy.ndarray
2.创建数组
a = np.array([1,2,3,4]) #提供一个由数值组成的列表作为一个参数
b = np.array([(1.5,2,3),(4,5,6)])
c = np.array([[1,2],[3,4]], dtype=complex)
np.zeros((3,4)) #创建全0的数组
np.ones((2,3,4)) #创建全1的数组
np.empty((2,3),dtype=np.int16) #创建随机值的数组(大小固定,值无初始化,随机)
np.random.random((2,3))
np.arange(10,30,5) #常见的数组为[10,15,20,25] 不包括最大值 [10,30)
np.linspace(0,2,9) #创建一个数组,范围为0~2,总共9个数 包括最大值 [0,2]
3.基本运算
Numpy中数组的算数运算时按照元素位置执行的,包括加(+)、减(-)、乘法(*)、平方(**2)、立方(**3)、根号(**(1/2))或(**(1/2.))等、复合运算(10*np.sin(a))、比较(a<35)。
A = np.array([[1,1],[0,1]])
B = np.array([[2,0],[3,4]])
A*B = [[2,0],[0,4]] #按照矩阵位置相乘,Aij*Bij
A.dot(B) = [[5,4],[3,4]] #矩阵乘法
np.dot(A,B) = [[5,4],[3,4]] #矩阵乘法
##更改已存在数组操作
a+ = b ## 若a为整数类型,b为浮点数类型,则出现报错,反之不会
a* = 3
##当a为整数类型,b为浮点数时,c自动设置为浮点数类型(优先考虑以更精确的方式存储,称为upcast)
c = a+b
##统计类运算
a.sum() #a.sum(axis=0)为列求和, a.sum(axis=1) 为行求和
a.min()
a.cumsum(axis=1) ##每行累加求和。
4.索引、切片和迭代
Numpy的一维数组可以被索引、切片和迭代。多维数组的每个轴(维度)有一个索引,由一个逗号分割的元组给出。(索引就是访问数组中的单个或一部分元素,数组序号从0开始)
a = np.arange(10)**2 ## a = [ 0 1 4 9 16 25 36 49 64 81]
print(a[2]) ## output: 4
print(a[3:5]) ## output:[9, 16]
a[:6:2] = -1000 #从开始位置到6号索引位,每隔一个元素将其赋值为-1000(不包括6号位)
##[-1000 1 -1000 9 -1000 25 36 49 64 81]
a[::-1] ##反转a,但a本身不产生变化
#################################################################
def f(x,y):
return 10*x+y
b = np.fromfunction(f,(5,4),dtype=int)
# b = [[ 0 1 2 3]
# [10 11 12 13]
# [20 21 22 23]
# [30 31 32 33]
# [40 41 42 43]]
b[0:5,1]
or b[:,1] ##每行第2个元素 [ 1 11 21 31 41]
b[1:3,:] ##第2到3行(切片行为)
b[-1] ##等价于b[-1,:],最后一行
##################################################################
#c.shape 为(2,2,3)三维数组时
c[1,...] #等价于c[1,:,:]或c[1]
c[...,2] #等价于c[:,:,2]
5.numpy 的独特操作
上述均为常规操作,而numpy还提供了独特的索引和切片功能:
数组可以被整数数组和布尔数组索引。
当被索引数组a是多维的时候,每个唯一的索引数列指向a的第一维(二维为例就是每行)。使用整数的情况一般为手动精准定位,而布尔数组更像是做数据筛选。
这种索引方式比较复杂,看下面的例子更快。
import numpy as np
a = np.arange(12)**2
print('a=',a)
i = np.array([1,1,3,8,5])
print('a[i]=',a[i])
j = np.array([[3,4],[9,7]])
print('a[j]=',a[j])
palette = np.array([[0,0,0],
[255,0,0],
[0,255,0],
[0,0,255],
[255,255,255]])
image = np.array([[0,1,2,0],[0,3,4,0]])
print('palette[image]=',palette[image])
布尔值的情况:
import numpy as np
a = np.arange(12).reshape(3,4)
b = a>4
print('a[b] = ',a[b]) # a不发生变化
b1 = np.array([False,True,True])
b2 = np.array([True,False,True,False])
print('a[b1,:]=',a[b1,:]) ## equal to a[b1]
print('a[:,b2]=',a[:,b2])
print('a[b1,b2]=',a[b1,b2])
6.更改数组的形状
ndarray的形状能使用很多函数修改:
ravel 函数能将数组展开成扁平化的形式;
reshape函数根据给定的轴大小,将数组改为指定形状;
(以上两种会新建更改后的数组,维度-1时,该维度将自动被计算)
resize函数改变数组本身,而不新建ndarray数组。
import numpy as np
a =np.floor(10*np.random.random((3,4))) #floor 向下取整;ceil 向上取整
print(a)
print(a.ravel())
print(a.reshape(2,6)) #与 a.reshape(2,-1) 结果相同
print(a.T) #转置,a.T.shape = (4,3)
a.resize((2,6))
print(a.shape) #(2,6)
7.组合、拆分数组
组合的函数:vstack函数——多个ndarray数组沿着第一个轴组合;
hstack函数——多个ndarray数组沿着第二个轴组合。
column_stack仅支持以序列的顺序将多个一位数组或一个二维数组组合(列向量concat)。
import numpy as np
a = np.array([[2,0],[3,4]])
print('vstack:',np.vstack((a,a)))
print('hstack:',np.hstack((a,a)))
b = np.array([2,0,3,3,4,2])
print(np.column_stack((b,b,b)))
拆分的函数:vsplit函数——将ndarray数组沿着纵向轴分割
hsplit函数——将数组沿着水平轴分割,允许指定返回数组的个数或切割位置
import numpy as np
from torch import dtype
a = np.floor(5*np.random.random((2,12)))
print(a)
print('hsplit(a,3):\n',np.hsplit(a,3)) #切成相同大小的三份
print('hsplit(a,(3,4)):\n',np.hsplit(a,(3,4))) #在第3列、第4列后发生切割
x = np.arange(16).reshape(4,4)
print(x)
print('vsplit(x,2):\n',np.vsplit(x,2)) #上下分层,横向切成相同大小的两份
print('vsplit(x,np.array([3,6])):\n',np.vsplit(x,np.array([3,6]))) #切第三排和第6排,不存在则切成空的
更好用的拆分函数(更灵活)——split函数
np.split(x,3)
np.split(x,[3,5,6,10])
*8.广播
广播的原则能使通用函数有意义地处理不具有相同形状的输入。(对于数组来说,沿着扩展维度的数组元素的值理应相同)
广播第一原则:如果所有的输入数组维度都不相同,数值 “1” 将被重复地添加在维度较小的数组上,知道所有数组拥有相同维度。
广播第二原则:确定长度为 1 的数组沿着特殊的方向向最大形状伸展。
import numpy as np
x = np.arange(4)
y = np.ones(5)
z = np.ones((3,4))
print('x+y:\n',x.reshape(4,1)+y)
print('Shape of x+z: ',(x+z).shape) #x.shape: (4,)
print('x+z:\n',x+z)
#===============================
#output:
# x+y:
# [[1. 1. 1. 1. 1.]
# [2. 2. 2. 2. 2.]
# [3. 3. 3. 3. 3.]
# [4. 4. 4. 4. 4.]]
# Shape of x+z: (3, 4)
# x+z:
# [[1. 2. 3. 4.]
# [1. 2. 3. 4.]
# [1. 2. 3. 4.]]
利用广播的原则,Numpy允许执行交叉运算(例):
import numpy as np
a = np.array([0.0,10.0,20.0,30.0])
b = np.array([1.0,2.0,3.0])
print(a[:,np.newaxis]+b)
##a.shape 首先因为newaxis变成了(4,1)
##然后因为广播原则,(4,1)+(1,3) ——> (4,3)
计算结果:
[[ 1. 2. 3.]
[11. 12. 13.]
[21. 22. 23.]
[31. 32. 33.]]
总结
本篇对常用的numpy中ndarray数组的常规操作进行了一些介绍及样例说明。这些内容均摘抄自《Pytorch机器学习 从入门到实战》一书,仅作为学习笔记记录。
Enable GingerCannot connect to Ginger Check your internet connection
or reload the browserDisable in this text fieldRephraseRephrase current sentence7Log in to edit with Ginger×