摘要: 本贴通过例子描述 python 的矩阵运算.
1. 一般乘法 (mm 与 matmul)
代码:
input_mat1 = torch.tensor([[1, 2, 3, 4],[1, 2, 2, 3]])input_mat2 = torch.tensor([[1, 2, 3, 3],[2, 1, 2, 3],[3, 1, 2, 2],[2, 3, 2, 3]])print("input_mat1: ", input_mat1)print("input_mat2: ", input_mat2)output_mat1 = torch.mm(input_mat1, input_mat2)print("torch.mm() test, output_mat1 = ", output_mat1)output_mat2 = torch.matmul(input_mat1, input_mat2)print("torch.matmul() test, output_mat2 = ", output_mat2)
结果:
input_mat1: tensor([[1, 2, 3, 4],[1, 2, 2, 3]])
input_mat2: tensor([[1, 2, 3, 3],[2, 1, 2, 3],[3, 1, 2, 2],[2, 3, 2, 3]])
torch.mm() test, output_mat1 = tensor([[22, 19, 21, 27],[17, 15, 17, 22]])
torch.matmul() test, output_mat2 = tensor([[22, 19, 21, 27],[17, 15, 17, 22]])
分析:
- 利用 torch.tensor 来定义张量 (含矩阵);
- torch.mm() 和 torch.matmul() 在这个例子里面的作用相同, 都是将 m × n m \times n m×n 与 n × k n \times k n×k 的矩阵进行乘法, 获得 m × k m \times k m×k 的矩阵;
- torch.matmul() 在 3 维及以上数据中有些奇怪的用法.
2. 逐点乘法 (乘法符号)
2.1 一维数组
代码:
print("---torch.tensor star product test---")input_array1 = torch.tensor([1, 2, 3, 4])input_array2 = torch.tensor([4, 3, 2, 1])star_product = input_array1 * input_array2print("star_product: ", star_product)
结果:
---torch.tensor star product test---
star_product: tensor([4, 6, 6, 4])
分析:
- 不改变向量尺寸.
2.2 二维矩阵
代码:
print("---element_wise_product test---")input_matrix = np.array([[1, 2], [3, 4]])element_wise_product = input_matrix * input_matrixprint("element_wise_product : ", element_wise_product)
结果:
---element_wise_product test---
element_wise_product : [[ 1 4][ 9 16]]
分析:
- 不改变矩阵尺寸.
3. 点乘 (dot)
3.1 一维数组
代码:
print("---torch.tensor dot_product test---")input_array1 = torch.tensor([1, 2, 3, 4])input_array2 = torch.tensor([4, 3, 2, 1])dot_product = torch.dot(input_array1, input_array2)print("array dot_product: ", dot_product)print("---np.array dot_product test---")input_array1 = np.array([1, 2, 3, 4])input_array2 = np.array([4, 3, 2, 1])dot_product = np.dot(input_array1, input_array2)print("array dot_product: ", dot_product)
结果:
---torch.tensor dot_product test---
array dot_product: tensor(20)
---np.array dot_product test---
array dot_product: 20
分析:
- 相当于内积;
- torch.tensor 和 np.array 都支持 dot;
- torch 返回结果是一个 1 × 1 1 \times 1 1×1 tensor, np 返回的是一个标量.
3.2 矩阵
与 torch.matmul 相同.
4. 拼接 (cat)
cat 不改变数据性质 (向量/矩阵/张量仍然是向量/矩阵/张量)
4.1 向量
代码:
print("---array test---")input_mat1 = torch.tensor([1, 2, 3, 4])print("input: ", input_mat1)horizontal_stack = torch.cat((input_mat1, input_mat1), 0)#vertical_stack = torch.cat((input_mat1, input_mat1), 1)print("horizontal_cat = ", horizontal_stack)#print("vertical_cat = ", vertical_stack)
结果:
---array test---
input: tensor([1, 2, 3, 4])
horizontal_cat = tensor([1, 2, 3, 4, 1, 2, 3, 4])
分析:
- cat 的第 2 个参数指定方向, 0 表示水平, 1 表示垂直;
- 向量支持水平叠加, 不支持垂直叠加, 否则向量变成二维矩阵, 不合适.
4.2 矩阵
代码:
print("---matrix test---")input_mat1 = torch.tensor([[1, 2, 3, 4],[1, 2, 2, 3]])print("input: ", input_mat1)horizontal_cat = torch.cat((input_mat1, input_mat1), 0)vertical_cat = torch.cat((input_mat1, input_mat1), 1)print("horizontal_cat = ", horizontal_cat)print("vertical_cat = ", vertical_cat)print("shape: ", np.shape(input_mat1), np.shape(horizontal_cat), np.shape(vertical_cat))
结果:
---matrix test---
input: tensor([[1, 2, 3, 4],[1, 2, 2, 3]])
horizontal_cat = tensor([[1, 2, 3, 4],[1, 2, 2, 3],[1, 2, 3, 4],[1, 2, 2, 3]])
vertical_cat = tensor([[1, 2, 3, 4, 1, 2, 3, 4],[1, 2, 2, 3, 1, 2, 2, 3]])
shape: torch.Size([2, 4]) torch.Size([4, 4]) torch.Size([2, 8])
分析:
- 水平叠加两个 m × n m \times n m×n 矩阵, 将获得一个 2 m × n 2m \times n 2m×n 矩阵; 垂直叠加两个 m × n m \times n m×n 矩阵, 将获得一个 m × 2 n m \times 2n m×2n 矩阵.
4.3 张量
print("---tensor test---")input_tensor1 = torch.tensor([[[1, 2, 3, 4], [1, 2, 2, 3]],[[5, 6, 7, 8], [8, 7, 6, 5]]])print("input: ", input_tensor1)horizontal_cat = torch.cat((input_tensor1, input_tensor1), 0)vertical_cat = torch.cat((input_tensor1, input_tensor1), 1)print("horizontal_cat = ", horizontal_cat)print("vertical_cat = ", vertical_cat)print("shape: ", np.shape(input_tensor1), np.shape(horizontal_cat), np.shape(vertical_cat))
结果:
---tensor test---
input: tensor([[[1, 2, 3, 4],[1, 2, 2, 3]],[[5, 6, 7, 8],[8, 7, 6, 5]]])
horizontal_cat = tensor([[[1, 2, 3, 4],[1, 2, 2, 3]],[[5, 6, 7, 8],[8, 7, 6, 5]],[[1, 2, 3, 4],[1, 2, 2, 3]],[[5, 6, 7, 8],[8, 7, 6, 5]]])
vertical_cat = tensor([[[1, 2, 3, 4],[1, 2, 2, 3],[1, 2, 3, 4],[1, 2, 2, 3]],[[5, 6, 7, 8],[8, 7, 6, 5],[5, 6, 7, 8],[8, 7, 6, 5]]])
shape: torch.Size([2, 2, 4]) torch.Size([4, 2, 4]) torch.Size([2, 4, 4])
分析:
- 水平叠加两个 m × n × k m \times n \times k m×n×k 张量, 将获得一个 2 m × n × k 2m \times n \times k 2m×n×k 张量; 垂直叠加两个 m × n m \times n m×n 矩阵, 将获得一个 m × 2 n × k m \times 2n \times k m×2n×k 矩阵.
5. 堆叠 (stack)
5.1 向量堆叠成矩阵
代码:
print("---torch.tensor stack test---")input_array1 = torch.tensor([1, 2, 3, 4])input_array2 = torch.tensor([4, 3, 2, 1])array_stack_horizontal = np.stack([input_array1, input_array2], axis=0)print("horizontal stack: ", array_stack_horizontal)array_stack_vertical = np.stack([input_array1, input_array2], axis=1)print("vertical stack: ", array_stack_vertical)
结果:
---torch.tensor stack test---
horizontal stack: [[1 2 3 4][4 3 2 1]]
vertical stack: [[1 4][2 3][3 2][4 1]]
分析: k k k 个 n n n 维向量堆叠, k × n k \times n k×n 维矩阵.
- 如果按照 axis=0 来读取, 则对应于 ( y , x ) (y, x) (y,x) 坐标;
- 如果按照 axis=1 来读取, 则对应于 ( x , y ) (x, y) (x,y) 坐标, 即获得 n × k n \times k n×k 维矩阵.
5.2 矩阵堆叠成张量
代码:
print("---numpy stack test---")tensor1 = np.arange(1, 13).reshape((3, 4))tensor2 = np.arange(13, 25).reshape((3, 4))print("tensor1: ", tensor1)print("tensor2: ", tensor2)tensor_stack0 = np.stack([tensor1, tensor2], axis=0)print("\r\naxis 0 stack: ", tensor_stack0)print("shape: ", np.shape(tensor_stack0))tensor_stack1 = np.stack([tensor1, tensor2], axis=1)print("axis 1 stack: ", tensor_stack1)print("shape: ", np.shape(tensor_stack1))tensor_stack2 = np.stack([tensor1, tensor2], axis=2)print("axis 2 stack: ", tensor_stack2)print("shape: ", np.shape(tensor_stack2))
结果:
---numpy stack test---
tensor1: [[ 1 2 3 4][ 5 6 7 8][ 9 10 11 12]]
tensor2: [[13 14 15 16][17 18 19 20][21 22 23 24]]axis 0 stack: [[[ 1 2 3 4][ 5 6 7 8][ 9 10 11 12]][[13 14 15 16][17 18 19 20][21 22 23 24]]]
shape: (2, 3, 4)
axis 1 stack: [[[ 1 2 3 4][13 14 15 16]][[ 5 6 7 8][17 18 19 20]][[ 9 10 11 12][21 22 23 24]]]
shape: (3, 2, 4)
axis 2 stack: [[[ 1 13][ 2 14][ 3 15][ 4 16]][[ 5 17][ 6 18][ 7 19][ 8 20]][[ 9 21][10 22][11 23][12 24]]]
shape: (3, 4, 2)
分析: k k k 个 m × n m \times n m×n 矩阵堆叠
- 方向 0: k × m × n k \times m \times n k×m×n 张量;
- 方向 1: m × k × n m \times k \times n m×k×n 张量;
- 方向 2: m × n × k m \times n \times k m×n×k 张量.
进一步理解:
m × n m \times n m×n 矩阵在描述的时候, 可以用 ( x , y ) (x, y) (x,y) 坐标描述. 堆叠成 k × m × n k \times m \times n k×m×n 张量 (立方体), 可以用三种顺序描述: ( z , x , y ) (z, x, y) (z,x,y), ( x , z , y ) (x, z, y) (x,z,y), ( x , y , z ) (x, y, z) (x,y,z), 只要控制每个维度从小到大即可.