Python深度学习:基于PyTorch
上QQ阅读APP看书,第一时间看更新

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]]]