携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第17天,上一篇文章中,我们主要进行Tensor的创建,包括,定义的时候初始化,规定里类型,定义特殊的Tensor,随机生成,均匀分布,定义序列,和numpy的比较
今天我们来介绍Tensor的属性、定义稀疏的张量、Tensor的算术运算(加法、减法、乘法、除法、矩阵、幂、对数和开方运算)。
-
1.1 Tensor属性
- 每一个Tensor有torch.dtype、torch.device、torch.layout三种属性。
- torch.device 标识了torch.Tensor对象在创建之后所存储(cpu、Gpu:cuda:0,1,2)的设备名称
- torch.layout表示torch.Tensor内存布局的对象
- 例如:torch.tensor([1, 2, 3], dtype=torch.float32, device=torch.device(‘cpu’))
- 定义稀疏的张量:
- torch.sparse_coo_tensor来定义
- 稀疏表达了当前非零元素的个数,零元素的个数越多,当前数据越稀疏
- 稀疏张量的优点
- 使模型更简单,降低参数的个数
- 减少内存的开销
-
1.2 定义稀疏的张量
获得当前的设备
dev = torch.device("cpu")
a = torch.tensor([2, 2],
dtype=torch.float32,
device=dev)
print(a)
运行结果:
tensor([2., 2.])
定义一个稀疏的张量:
需要定义一个存储非零元素的坐标的Tensor,一个存放非零元素的值的tensor,使用.to_dense()直接将它转成稠密的张量
i = torch.tensor([[0, 1, 2], [0, 1, 2]])
v = torch.tensor([1, 2, 3])
a = torch.sparse_coo_tensor(i, v, (4, 4),
dtype=torch.float32,
device=dev).to_dense()
print(a)
运行结果:
tensor([[1., 0., 0., 0.],
[0., 2., 0., 0.],
[0., 0., 3., 0.],
[0., 0., 0., 0.]])
-
问题:为什么有的数据需要放在cpu上,有些数据需要放在gpu上?
- 在图像处理的过程中,需要对数据进行合理的分配,
- 有些数据,比如说在进行数据读取和数据预处理操作的时候,会优先放在cpu上进行操作,
- 对于参数的计算,推理和进行反向传播的过程会通常放在gpu上进行运算,
- 我们通过对资源的分配来完成资源利用的最大化,保证网络训练和迭代的更加快,这也是在进行算法操作的时候进行的一个非常需要关注的点
-
2.1 Tensor的算术运算
定义两个tensor:
a = torch.rand(2, 3)
b = torch.rand(2, 3)
print(a)
print(b)
运行结果:
tensor([[0.4992, 0.0778, 0.2335],
[0.4446, 0.7612, 0.9462]])
tensor([[0.3567, 0.2755, 0.2872],
[0.6349, 0.3790, 0.4286]])
使用这两个tensor进行算术运算
- 2.1.1 加法运算
带下划线的求解会对原有的值进行修改
print(a + b)
print(a.add(b))
print(torch.add(a, b))
print(a)
print(a.add_(b))
print(a)
运行结果:
tensor([[0.8559, 0.3533, 0.5207],
[1.0795, 1.1403, 1.3748]])
tensor([[0.8559, 0.3533, 0.5207],
[1.0795, 1.1403, 1.3748]])
tensor([[0.8559, 0.3533, 0.5207],
[1.0795, 1.1403, 1.3748]])
tensor([[0.4992, 0.0778, 0.2335],
[0.4446, 0.7612, 0.9462]])
tensor([[0.8559, 0.3533, 0.5207],
[1.0795, 1.1403, 1.3748]])
tensor([[0.8559, 0.3533, 0.5207],
[1.0795, 1.1403, 1.3748]])
可以发现a的值在经过add_修改之后变成了a+b的值
- 2.1.2 减法运算
print(a - b)
print(torch.sub(a, b))
print(a.sub(b))
print(a.sub_(b))
print(a)
运行结果:
tensor([[ 0.1425, -0.1976, -0.0538],
[-0.1903, 0.3822, 0.5176]])
tensor([[ 0.1425, -0.1976, -0.0538],
[-0.1903, 0.3822, 0.5176]])
tensor([[ 0.1425, -0.1976, -0.0538],
[-0.1903, 0.3822, 0.5176]])
tensor([[ 0.1425, -0.1976, -0.0538],
[-0.1903, 0.3822, 0.5176]])
tensor([[ 0.1425, -0.1976, -0.0538],
[-0.1903, 0.3822, 0.5176]])
- 2.1.3 乘法运算
哈达玛积(element wise 对应元素相乘)
print(a * b)
print(torch.mul(a, b))
print(a.mul(b))
print(a)
print(a.mul_(b))
print(a)
运行结果:
tensor([[0.1781, 0.0214, 0.0671],
[0.2823, 0.2885, 0.4056]])
tensor([[0.1781, 0.0214, 0.0671],
[0.2823, 0.2885, 0.4056]])
tensor([[0.1781, 0.0214, 0.0671],
[0.2823, 0.2885, 0.4056]])
tensor([[0.4992, 0.0778, 0.2335],
[0.4446, 0.7612, 0.9462]])
tensor([[0.1781, 0.0214, 0.0671],
[0.2823, 0.2885, 0.4056]])
tensor([[0.1781, 0.0214, 0.0671],
[0.2823, 0.2885, 0.4056]])
- 2.1.4 除法运算
print(a/b)
print(torch.div(a, b))
print(a.div(b))
print(a.div_(b))
print(a)
运行结果:
tensor([[1.3996, 0.2825, 0.8128],
[0.7002, 2.0084, 2.2075]])
tensor([[1.3996, 0.2825, 0.8128],
[0.7002, 2.0084, 2.2075]])
tensor([[1.3996, 0.2825, 0.8128],
[0.7002, 2.0084, 2.2075]])
tensor([[1.3996, 0.2825, 0.8128],
[0.7002, 2.0084, 2.2075]])
tensor([[1.3996, 0.2825, 0.8128],
[0.7002, 2.0084, 2.2075]])
-
2.1.5 矩阵运算
-
二维矩阵乘法运算操作包括torch.mm()、torch.matmul()、@
-
对于高维的Tensor(dim>2),定义其矩阵乘法仅在最后两个维度上,要求前面的维度必须保持一致,就像矩阵的索引一样并且运算操作只有torch.matmul()
-
matmul是没有下划线的,因为最后乘完之后的维度和之前的维度是不一样的了
-
二维矩阵的运算
a = torch.ones(2, 1)
b = torch.ones(1, 2)
print(a @ b)
print(a.matmul(b))
print(torch.matmul(a, b))
print(torch.mm(a, b))
print(a.mm(b))
运行结果:
tensor([[1., 1.],
[1., 1.]])
tensor([[1., 1.],
[1., 1.]])
tensor([[1., 1.],
[1., 1.]])
tensor([[1., 1.],
[1., 1.]])
tensor([[1., 1.],
[1., 1.]])
高维矩阵的运算
a = torch.ones(1, 2, 3, 4)
b = torch.ones(1, 2, 4, 3)
print(a.matmul(b).shape)
运行结果:
torch.Size([1, 2, 3, 3])
前两个维度不变,最后两个维度进行运算,要保证最后两个维度可以进行矩阵运算才可以进行运算
- 2.1.5 幂运算
a = torch.tensor([1, 2])
print(torch.pow(a, 3))
print(a.pow(3))
print(a**3)
print(a.pow_(3))
print(a)
运行结果:
tensor([1, 8])
tensor([1, 8])
tensor([1, 8])
tensor([1, 8])
tensor([1, 8])
e的n次方用exp来表示
a = torch.tensor([1, 2],
dtype=torch.float32)
print(a.type())
print(torch.exp(a))
print(torch.exp_(a))
print(a.exp())
print(a.exp_())
运行结果:
torch.FloatTensor
tensor([2.7183, 7.3891])
tensor([2.7183, 7.3891])
tensor([ 15.1543, 1618.1782])
tensor([ 15.1543, 1618.1782])
- 2.1.5 对数运算
a = torch.tensor([10, 2],
dtype=torch.float32)
print(torch.log(a))
print(torch.log_(a))
print(a.log())
print(a.log_())
运行结果:
tensor([2.3026, 0.6931])
tensor([2.3026, 0.6931])
tensor([ 0.8340, -0.3665])
tensor([ 0.8340, -0.3665])
- 2.1.6 开方运算
1. a = torch.tensor([10, 2],
1. dtype=torch.float32)
1. print(torch.sqrt(a))
1. print(torch.sqrt_(a))
1.
1. print(a.sqrt())
1. print(a.sqrt_())
运行结果:
tensor([3.1623, 1.4142])
tensor([3.1623, 1.4142])
tensor([1.7783, 1.1892])
tensor([1.7783, 1.1892])