1.4 数组变形
在机器学习以及深度学习的任务中,通常需要将处理好的数据以模型能接收的格式输入给模型,然后由模型通过一系列的运算,最终返回一个处理结果。然而,由于不同模型所接收的输入格式不一样,往往需要先对其进行一系列的变形和运算,从而将数据处理成符合模型要求的格式。在矩阵或者数组的运算中,经常会遇到需要把多个向量或矩阵按某轴方向合并,或展平(如在卷积或循环神经网络中,在全连接层之前,需要把矩阵展平)的情况。下面介绍几种常用的数据变形方法。
1.4.1 更改数组的形状
修改指定数组的形状是Numpy中最常见的操作之一,常见的方法有很多,表1-3列出了一些常用函数。
表1-3 Numpy中改变向量形状的一些函数
下面来看一些示例。
1.reshape
改变向量的维度(不修改向量本身):
import numpy as np arr =np.arange(10) print(arr) # 将向量 arr 维度变换为2行5列 print(arr.reshape(2, 5)) # 指定维度时可以只指定行数或列数, 其他用 -1 代替 print(arr.reshape(5, -1)) print(arr.reshape(-1, 5))
输出结果:
[0 1 2 3 4 5 6 7 8 9] [[0 1 2 3 4] [5 6 7 8 9]] [[0 1] [2 3] [4 5] [6 7] [8 9]] [[0 1 2 3 4] [5 6 7 8 9]]
值得注意的是,reshape函数不支持指定行数或列数,所以-1在这里是必要的。且所指定的行数或列数一定要能被整除,例如上面代码如果修改为arr.reshape(3,-1)即为错误的。
2.resize
改变向量的维度(修改向量本身):
import numpy as np arr =np.arange(10) print(arr) # 将向量 arr 维度变换为2行5列 arr.resize(2, 5) print(arr)
输出结果:
[0 1 2 3 4 5 6 7 8 9] [[0 1 2 3 4] [5 6 7 8 9]]
3.T
向量转置:
import numpy as np arr =np.arange(12).reshape(3,4) # 向量 arr 为3行4列 print(arr) # 将向量 arr 进行转置为4行3列 print(arr.T)
输出结果:
[[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]] [[ 0 4 8] [ 1 5 9] [ 2 6 10] [ 3 7 11]]
4.ravel
向量展平:
import numpy as np arr =np.arange(6).reshape(2, -1) print(arr) # 按照列优先,展平 print("按照列优先,展平") print(arr.ravel('F')) # 按照行优先,展平 print("按照行优先,展平") print(arr.ravel()) 输出结果: [[0 1 2] [3 4 5]] 按照列优先,展平 [0 3 1 4 2 5] 按照行优先,展平 [0 1 2 3 4 5]
5.flatten
把矩阵转换为向量,这种需求经常出现在卷积网络与全连接层之间。
import numpy as np a =np.floor(10*np.random.random((3,4))) print(a) print(a.flatten())
输出结果:
[[4. 0. 8. 5.] [1. 0. 4. 8.] [8. 2. 3. 7.]] [4. 0. 8. 5. 1. 0. 4. 8. 8. 2. 3. 7.]
6.squeeze
这是一个主要用来降维的函数,把矩阵中含1的维度去掉。在PyTorch中还有一种与之相反的操作——torch.unsqueeze,这个后面将介绍。
import numpy as np arr =np.arange(3).reshape(3, 1) print(arr.shape) #(3,1) print(arr.squeeze().shape) #(3,) arr1 =np.arange(6).reshape(3,1,2,1) print(arr1.shape) #(3, 1, 2, 1) print(arr1.squeeze().shape) #(3, 2)
7.transpose
对高维矩阵进行轴对换,这个在深度学习中经常使用,比如把图片中表示颜色顺序的RGB改为GBR。
import numpy as np arr2 = np.arange(24).reshape(2,3,4) print(arr2.shape) #(2, 3, 4) print(arr2.transpose(1,2,0).shape) #(3, 4, 2)
1.4.2 合并数组
合并数组也是最常见的操作之一,表1-4列举了常见的用于数组或向量合并的方法。
表1-4 Numpy数组合并方法
【说明】
1)append、concatenate以及stack都有一个axis参数,用于控制数组的合并方式是按行还是按列。
2)对于append和concatenate,待合并的数组必须有相同的行数或列数(满足一个即可)。
3)stack、hstack、dstack,要求待合并的数组必须具有相同的形状(shape)。
下面选择一些常用函数进行说明。
1.append
合并一维数组:
import numpy as np a =np.array([1, 2, 3]) b = np.array([4, 5, 6]) c = np.append(a, b) print(c) # [1 2 3 4 5 6]
合并多维数组:
import numpy as np a =np.arange(4).reshape(2, 2) b = np.arange(4).reshape(2, 2) # 按行合并 c = np.append(a, b, axis=0) print('按行合并后的结果') print(c) print('合并后数据维度', c.shape) # 按列合并 d = np.append(a, b, axis=1) print('按列合并后的结果') print(d) print('合并后数据维度', d.shape)
输出结果:
按行合并后的结果 [[0 1] [2 3] [0 1] [2 3]] 合并后数据维度 (4, 2) 按列合并后的结果 [[0 1 0 1] [2 3 2 3]] 合并后数据维度 (2, 4)
2.concatenate
沿指定轴连接数组或矩阵:
import numpy as np a =np.array([[1, 2], [3, 4]]) b = np.array([[5, 6]]) c = np.concatenate((a, b), axis=0) print(c) d = np.concatenate((a, b.T), axis=1) print(d)
输出结果:
[[1 2] [3 4] [5 6]] [[1 2 5] [3 4 6]]
3.stack
沿指定轴堆叠数组或矩阵:
import numpy as np a =np.array([[1, 2], [3, 4]]) b = np.array([[5, 6], [7, 8]]) print(np.stack((a, b), axis=0))
输出结果:
[[[1 2] [3 4]] [[5 6] [7 8]]]