NumPy,Numerical Python创建的ndarray数组在某些方面与Python中的list对象很相似;但是二者还是很多区别,比如数据类型一致性的要求、维度等。

NumPy Ndarray | Working and Different Examples of NumPy Ndarray

Array的保存与加载

1
2
3
4
5
6
import numpy as np
data = np.array([1, 2, 3, 4, 5])
# 保存
np.save('my_array.npy', data)
# 加载
loaded_data = np.load('my_array.npy')

Torch.tensor的保存与加载

1
2
3
4
5
6
import torch
tensor = torch.randn(3, 4)
# Save
torch.save(tensor, 'tensor.pt')
# Load
loaded_tensor = torch.load('tensor.pt')

1、创建数组对象

  • 储存为数组的数据要求具有相同的数据类型,在创建数组时需要指定是哪种数据类型;

  • NumPy支持多种数据类型,常见的有整型int64(默认), int32, int16,int8;浮点型float64(默认), float32, float16,float8

1.1 list转为数组

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
##(1) 普通list转为一维数组
import numpy as np
np.array([1,2,3,4,5]) #如果列表内元素为整数,则默认为int64
# array([1, 2, 3, 4, 5])
np.array([1,2,3,4,5], dtype=int) #若指定数据类型为int,同样默认为int64

np.array([1,2,3,4,5], dtype="int32") #指定为其它数据类型
# array([1, 2, 3, 4, 5], dtype=int32)

np.array([1,2,3,4,5], dtype="float64")
# array([1., 2., 3., 4., 5.])

np.array(range(1,6))
# array([1, 2, 3, 4, 5])

##(2) 嵌套列表转为二维数组
np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
# array([[ 1,  2,  3,  4],
#        [ 5,  6,  7,  8],
#        [ 9, 10, 11, 12]])
# 一个子列表视为1行
np.array([range(1,5), range(5,9), range(9,13)])

数组有.tolist方法将其转为list对象

1.2 特定模式数组

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import numpy as np
##(1) 创建全0数组,第一个参数交代维度,第二个参数交代数据类型
np.zeros(5, dtype=int)
np.zeros((2,4), dtype=float)

#np.ones与之类似,创建全1数组

##(2) 创建有序一维数组
np.arange(5)
# array([0, 1, 2, 3, 4])
np.linspace(1,5, num=9)
# array([1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5, 5. ])

##(3) 创建random随机分布数组
np.random.random(5)  #0 1之间随机分布
# array([0.48928279, 0.76854168, 0.70242817, 0.13372169, 0.4132587 ])
np.random.randint(0,5,(2,3)) #指定整数区间随机分布
# array([[2, 1, 2],
#        [3, 4, 4]])
np.random.normal(0, 1, 5) #正态分布
# array([-2.16054171, -0.40716729,  0.19965792, -1.00849158,  0.36834892]) 

np.random.randn(10)    #返回10个符合0,1正态分布的随机数
np.random.randn(1,2)   #返回1行2列,符合0,1正态分布的随机数

np.random.choice(range(10),5,replace=False)
# array([3, 6, 5, 1, 0])

##随机种子
#方式(1)
np.random.seed(42)
np.random.random(5)
#方式(2)
np.random.RandomState(42).random(5)


## (4) 单位矩阵
np.eye(3)
# array([[1., 0., 0.],
#        [0., 1., 0.],
#        [0., 0., 1.]])
## 一个矩阵与相应的单位矩阵进行矩阵乘法运算,值不变
np.array_equal(t4, np.matmul(t4, torch.eye(3)))
# True
1
2
3
4
5
6
import torch
torch.randn(2, 3, 4).shape
# torch.Size([2, 3, 4])

torch.normal(0, 1, (3,)).shape
# torch.Size([3])

1.3 数据类型转换

1
2
3
4
5
6
7
np.array([1, 2, 3]).dtype
# dtype('int64')
np.array([1, 2, 3]).astype(float).dtype
# dtype('float64')
np.array([1, 2, 3]).astype(np.float32).dtype
# dtype('float32')
np.array([1, 2, 3]).astype(np.int32).dtype
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import torch
torch.tensor([1, 2, 3]).dtype
# torch.int64
torch.tensor([1, 2, 3]).to(torch.float16).dtype
# torch.float16
torch.tensor([1, 2, 3]).to(torch.int16).dtype
# torch.int16

torch.tensor([1, 2, 3]).long() #int64
torch.tensor([1, 2, 3]).int() #int32
torch.tensor([1, 2, 3]).float() #float32
torch.tensor([1, 2, 3]).double() #float64

2、数组维度转换

  • 查看
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import numpy as np
test = np.arange(6)
# array([0, 1, 2, 3, 4, 5])
##(1) 查看数量
test.size
# 6

##(2) 查看维度
test.ndim
# 1

##(3) 查看每个维度的大小
test.shape
# (6,)
  • reshape转换
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
##(4) 维度转换
#转换为2行3列的新数组
test.reshape((2,3))
# array([[0, 1, 2],
#        [3, 4, 5]])

#转换为1行6列的行向量二维数组
test.reshape((1,6))
test.reshape((1,-1))
# array([[0, 1, 2, 3, 4, 5]])

#转换为6行1列的列向量二维数组
test.reshape((6,1))
test.reshape((-1,1))
# array([[0],
#        [1],
#        [2],
#        [3],
#        [4],
#        [5]])

#二维转为一维
test.reshape((6,1)).reshape((6,))
test.reshape((6,1)).reshape((-1))
test.reshape((6,1)).ravel()

#array([0, 1, 2, 3, 4, 5])

#二维行列转换
test.reshape((2,3)).T
#array([[0, 3],
#       [1, 4],
#       [2, 5]])
# 任意维度的转换
test.transpose(1, 0) #轴1与轴0交换

reshape操作:不改变数据顺序,可将将多维数据展平成一维,或将一维数据恢复为多维。

transpose操作:数据的轴交换。 例如,将图像数据从 (height, width, channels) 转换为 (channels, height, width)

  • 其它(20241013补充)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
test = np.random.randn(2, 1, 5)
test.shape
# (2, 1, 5)
test.squeeze(axis = 1).shape
# (2, 5)

np.expand_dims(test, 0).shape
# (1, 2, 1, 5)


## torch
import torch
test = torch.randn(2, 1, 5)

test.squeeze(dim = 1).shape
# torch.Size([2, 5])

test.unsqueeze(dim = 0).shape
# torch.Size([1, 2, 1, 5])
  • repeat复制
1
2
3
4
5
6
7
8
test = np.random.randn(3, 4)
test.repeat(2, axis=1).shape
# (3, 8)

## torch的操作方式不同
t3 = torch.randn(2, 1, 3)
t3.repeat(1, 2, 2).shape
# torch.Size([2, 2, 6])

3、索引与切片

3.1 一维数组

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
##(1)索引操作返回单个数值
import numpy as np
aa=np.array([1,2,3,4,5])
aa[1]
# 2

###列表索引返回数组
aa[[0,2,3]]
# array([1, 3, 4])

##(2)切片操作返回子数组
aa[0:2]
# array([1, 2])
aa[3:]
# array([4, 5])

3.2 二维数组

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
##(1)索引操作返回单个数值
import numpy as np
bb=np.array([[1,2,3],[4,5,6]])
bb[0,0]
# 1
bb[1,2]
# 6

##(2)数组切片返回子数组
bb[:,0:2] #第1,2列
# array([[1, 2],
#        [4, 5]])
bb[1,:]   #第2行
# array([4, 5, 6])

###列表索引
bb[:,[0,2]] #第1,3列

bb[[1],:]   #第2行
bb[[1]]     #第2行(列表索引)
bb[:2]      #第1、2行(切片)

4、数组计算

4.1 基础算数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import numpy as np
np.add            # +
np.subtract       # -
np.negative       # 相反数
np.abs            # 绝对值
np.multipy        # ×
np.divide         # /
np.floor_divide   # // , 7//2=3
np.mod            # %  , 7%2 =1
np.power          # ** , 2**3=8
np.exp            # 底数为e的指数运算
np.log2           # log2(x)


a1=np.array([1,2,3])
np.add(a1, 10)
# array([11, 12, 13])
np.power(3,a1)
# array([ 3,  9, 27])

##如果是二维数组,也是同样对所有数操作

4.2 基础统计

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
np.sum            #和
np.mean           #均值
np.std            #标准差
np.var            #方差
np.min            #最小值
np.argmin         #最小值的索引
np.median         #中位数
np.percentile     #百分位数

##(1) 一维数组
a1=np.array([1,2,3])
np.sum(a1)
# 6
np.argmin(a1)
# 0

##(2) 二维数组
b1=np.arange(0,6).reshape((2,3))
#array([[0, 1, 2],
#       [3, 4, 5]])
##按列统计:如下计算每一列的均值
np.mean(b1, axis=0)
#array([1.5, 2.5, 3.5])
##按行统计:如下计算每一行的均值
np.mean(b1, axis=1)
#array([1., 4.])

对于numpy提供的基础统计函数,都对应有每一个array实例的方法名。例如b1.mean(), a1.sum

4.3 数组与数组运算

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
##(1) 一维数组 与 一维数组: 长度需要相同
import numpy as np
a1 = np.array([1,2,3])
a2 = np.array([4,5,6])
a1 + a2

##(2) 二维数组 与 二维数组
b1=np.arange(0,6).reshape((2,3)) #2行3列
#列数相同,纵向扩展
b2=np.array([100,101,102]).reshape((1,3)) #1行3列
b1 + b2
# array([[100, 102, 104],
#       [103, 105, 107]])

#行数相同,横向扩展
b3=np.array([100,101]).reshape((2,1)) #2行1列
b1 + b3
# array([[100, 101, 102],
#        [104, 105, 106]])

b2 + b3 #Error

5、逻辑数组

  • 运算符:== != < <= > >=
  • 布尔运算符:&与 |或 ~否。使用布尔运算符时,对每一个子运算需要括号括起来。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import numpy as pd

##(1) 通过比较运算符产生布尔数组
x = np.arange(5)
# array([0, 1, 2, 3, 4])
x > 2
# array([False, False, False,  True,  True])
y = np.arange(6).reshape((2,3))
# array([[0, 1, 2],
#        [3, 4, 5]])
y == 2
# array([[False, False,  True],
#        [False, False, False]])

##(2) 统计布尔数组结果:
# True=1,False=0
#np.any : 有一个True即为True
#np.all : 全为True才为True
np.sum(x>2) #2
np.any(x>2) #True

np.sum(y==1, axis=0) 
# array([0, 1, 0])
np.all(y>=1, axis=0)
# array([False,  True,  True])

##(3)使用布尔数组筛选数组
x[x>2]
# array([3, 4])
y[y>=2]
# array([2, 3, 4, 5])
y[:,np.any(y>=4,axis=0)]
# array([[1, 2],
#        [4, 5]])

如上已经有多种方法可用于取数组子集:索引,切片,布尔值。这些方法可以混合使用。

6、数组排序

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
##(1) 一维数组
import numpy as np
x1 = np.random.choice(range(10),5,replace=False)
# array([0, 8, 4, 9, 3])

#### np.sort()
np.sort(x1)       #array([0, 3, 4, 8, 9])
np.sort(x1)[::-1] #array([9, 8, 4, 3, 0])
#### np.argsort()
np.argsort(x1)    #array([0, 4, 2, 1, 3])
#如上结果中:第一个元素是数组中最小元素的索引值,第二个是次小元素的索引值...以此类推

##(2) 二维数组
###每行/列都排序:但这样处理的后果是行列关系将会打乱
x2 = np.random.choice(range(20),9,replace=False).reshape((3,3))
# array([[16,  5, 14],
#        [ 0, 10, 12],
#        [19,  8, 18]])
np.sort(x2, axis=0)
# array([[ 0,  5, 12],
#        [16,  8, 14],
#        [19, 10, 18]])

###如下:按第一列值大小,调整整行顺序
x2[np.argsort(x2[:,0]),:]
# array([[ 0, 10, 12],
#        [16,  5, 14],
#        [19,  8, 18]])

7、拼接与分割

7.1 维度不变

  • 一维
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
##(1)拼接多个数组
import numpy as np
a1=np.array([1,2,3])
a2=np.array([4,5,6,7])
np.concatenate([a1, a2])
# array([1, 2, 3, 4, 5, 6, 7])

##(2)分割一个数组
np.split(a2,[1])
# [array([4]), array([5, 6, 7])]
s1, s2 = np.split(a2,[1])
  • 二(高)维数组
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
b1=np.arange(0,6).reshape((2,3))
b2=np.arange(10,16).reshape((2,3))
##(1)上下拼接数组
np.concatenate([b1, b2], axis=0).shape
# (4, 3)
np.vstack([b1, b2]).shape
# (4, 3)

##(2)左右拼接数组
np.concatenate([b1, b2], axis=1).shape
# (2, 6)
np.hstack([b1, b2]).shape
# (2, 6)

b3=np.arange(0,12).reshape((3,4))
##(3)按行分割数组
np.split(b3, [1], axis=0)
#[array([[0, 1, 2, 3]]),
# array([[ 4,  5,  6,  7],
#        [ 8,  9, 10, 11]])]
s1,s2=np.split(b3, [1], axis=0)
np.vsplit(b3, [1])

##(4)按列分割数组
np.split(b3, [2], axis=1)
s1,s2=np.split(b3, [2], axis=1)
np.hsplit(b3, [2])

7.2 维度变化

1
2
3
4
5
6
7
8
9
b1=np.arange(0,6).reshape((2,3))
b2=np.arange(10,16).reshape((2,3))

np.stack([b1, b2]).shape
# (2, 2, 3)
np.stack([b1, b2],axis=1).shape
# (2, 2, 3)
np.stack([b1, b2],axis=2).shape
# (2, 3, 2)