本节主要讲解pytorch中,tensor和矩阵的各类数学运算。
首先从最基本的加减乘除开始
.add (相加)
.sub (相减)
.mul (相乘)
.div (相除)
代码语言:javascript复制import torch
a = torch.rand(2, 3)
b = torch.rand(3)
c = torch.add(a, b)
d = torch.sub(a, b)
e = torch.mul(a, b)
f = torch.div(a, b)
print('c, d, e, f=', c, 'n', d, 'n', e, 'n', f)
输出为
代码语言:javascript复制c, d, e, f= tensor([[0.8616, 0.8815, 0.5835],
[1.3956, 1.0337, 0.9400]])
tensor([[-0.7527, 0.0045, 0.2063],
[-0.2186, 0.1567, 0.5628]])
tensor([[0.0440, 0.1943, 0.0745],
[0.4750, 0.2610, 0.1417]])
tensor([[0.0675, 1.0102, 2.0935],
[0.7291, 1.3573, 3.9837]])
而在tensor的乘法运算中,*又分为element_wise(元素相乘) 和 martix_matmul(矩阵形式相乘)两种。而按矩阵形式相乘有三种表达形式:
(1)torch.mm (只适用于 2D矩阵,不推荐使用)
(2)torch.matmal (适用于2D和3D矩阵相乘,推荐使用)
(3)@ 与torch.matmal原理相同,是matmal的另外一种写法
举例
代码语言:javascript复制a = torch.rand(2, 2)
# print(a)
b = torch.rand(2, 3)
c = torch.mm(a, b)
d = torch.matmul(a, b)
e = a@b
print('c, b, e = ', c, 'n', d, 'n', e)
输出
代码语言:javascript复制c, b, e = tensor([[1.0027, 0.2992, 0.3707],
[1.0420, 0.2906, 0.3730]])
tensor([[1.0027, 0.2992, 0.3707],
[1.0420, 0.2906, 0.3730]])
tensor([[1.0027, 0.2992, 0.3707],
[1.0420, 0.2906, 0.3730]])
为更直观的了解其用法,下面以一个具体的例子进行讲解
代码语言:javascript复制a = torch.rand(4, 784)
# 物理意义为4张图片,全部打平为28*28的数据
# 在图片处理中经常需要使用降维操作,本例考虑将[4, 784]降维成[4, 512]
# 因此按照以上思路,考虑需要构建一个新矩阵,使得[4, 784] * [784, 512] = [4, 512]
# 上面的[784, 512]即为考虑构建的新矩阵
# 下面开始构建
w = torch.rand(784, 512)
out = torch.matmul(a, w)
print(out.shape)
输出为
代码语言:javascript复制torch.Size([4, 512])
而在对高于2维的矩阵进行运算时,使用torch.mm时会报错
代码语言:javascript复制# 对于4维矩阵运算,在使用torch.mm时会报错
a = torch.rand(4, 1, 64, 32)
b = torch.rand(4, 3, 32, 64)
print(torch.mm(a, b).shape)
输出
代码语言:javascript复制RuntimeError: matrices expected, got 4D, 4D tensors at ..atensrcTH/generic/THTensorMath.cpp:956
因此该改用torch.matmul进行计算
代码语言:javascript复制# 高于2维的矩阵运算,应使用torch.matmul函数
a = torch.rand(4, 1, 64, 32)
b = torch.rand(4, 3, 32, 64)
print(torch.matmul(a, b).shape)
输出
代码语言:javascript复制torch.Size([4, 3, 64, 64])
这里注意,四维计算时前两个维度和后两个维度分别进行计算,因此(4, 1)被broadcasting成(4, 3),32*32被消掉,后面变成了(64, 64)。
在此之上,我们更改b,再进行计算
代码语言:javascript复制a = torch.rand(4, 3, 64, 32)
b = torch.rand(4, 64, 32)
print(torch.matmul(a, b).shape)
输出会报错
代码语言:javascript复制RuntimeError: The size of tensor a (3) must match the size of tensor b (4) at non-singleton dimension 1
报错原因在于b会broadcasting成[1, 4, 64, 32],但与a相乘时,dim=1位置上的3和4不相同,无法进行运算。因此矩阵在进行乘法运算时,要么就相同dim位置上的数值相同,要么就为1,以方便进行broadcasting。