本文主要是介绍深度学习 - 张量的广播机制和复杂运算,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
张量的广播机制(Broadcasting)是一种处理不同形状张量进行数学运算的方式。通过广播机制,PyTorch可以自动扩展较小的张量,使其与较大的张量形状兼容,从而进行元素级的运算。广播机制遵循以下规则:
- 如果张量维度不相同,在较小张量的形状前面加上1,直到两个张量的维度相同。
- 如果两个张量在某个维度的长度不相同,但其中一个张量在该维度的长度为1,那么在该维度上,较小长度的张量会被扩展为较大长度。
- 如果两个张量在任何维度上长度不同且均不为1,则无法进行广播,会引发错误。
广播机制的规则示例
规则1:在较小张量的形状前面加1
a = torch.tensor([1, 2, 3])
b = torch.tensor([[1], [2], [3]])
c = a + b
print(c)
运行结果:
tensor([[2, 3, 4],[3, 4, 5],[4, 5, 6]])
解释:a
的形状是(3,), b
的形状是(3,1)。在较小的张量前面加1变成(1,3)和(3,1),然后在第0维度上广播。
规则2:在某个维度的长度为1
a = torch.tensor([[1, 2, 3]])
b = torch.tensor([[4], [5], [6]])
c = a + b
print(c)
运行结果:
tensor([[5, 6, 7],[6, 7, 8],[7, 8, 9]])
解释:a
的形状是(1,3), b
的形状是(3,1)。a
被广播到(3,3),b
也被广播到(3,3)。
规则3:无法广播的情况
a = torch.tensor([1, 2, 3])
b = torch.tensor([[1, 2], [3, 4]])
try:c = a + b
except RuntimeError as e:print(e)
运行结果:
The size of tensor a (3) must match the size of tensor b (2) at non-singleton dimension 1
解释:a
的形状是(3,), b
的形状是(2,2),它们的形状不兼容,无法进行广播。
广播机制的详细示例
示例1:标量与多维张量相加
a = torch.tensor(5)
b = torch.tensor([[1, 2, 3], [4, 5, 6]])
c = a + b
print(c)
运行结果:
tensor([[ 6, 7, 8],[ 9, 10, 11]])
解释:标量a
被广播到与b
形状匹配,变成(2,3)。
示例2:形状不一致但能广播
a = torch.tensor([1, 2, 3])
b = torch.tensor([[1], [2], [3]])
c = a + b
print(c)
运行结果:
tensor([[2, 3, 4],[3, 4, 5],[4, 5, 6]])
解释:a
的形状是(3,), b
的形状是(3,1)。a
被广播到(3,3),b
被广播到(3,3)。
示例3:不同维度的广播
a = torch.tensor([1, 2, 3])
b = torch.tensor([[[1]], [[2]], [[3]]])
c = a + b
print(c)
运行结果:
tensor([[[2, 3, 4]],[[3, 4, 5]],[[4, 5, 6]]])
解释:a
的形状是(3,),b
的形状是(3,1,1)。a
被广播到(3,1,3),b
被广播到(3,1,3)。
示例4:标量与高维张量的广播
a = torch.tensor(10)
b = torch.tensor([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
c = a * b
print(c)
运行结果:
tensor([[[10, 20],[30, 40]],[[50, 60],[70, 80]]])
解释:标量a
被广播到与b
的形状匹配。
示例5:不同形状的广播加法
a = torch.tensor([[1, 2], [3, 4], [5, 6]])
b = torch.tensor([10, 20])
c = a + b
print(c)
运行结果:
tensor([[11, 22],[13, 24],[15, 26]])
解释:a
的形状是(3,2),b
的形状是(2,)。b
被广播到(3,2)。
张量的基本操作
示例1:基本运算
a = torch.tensor([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
b = torch.tensor([[[2, 2], [2, 2]], [[2, 2], [2, 2]]])
c = a * b
print(c)
运行结果:
tensor([[[ 2, 4],[ 6, 8]],[[10, 12],[14, 16]]])
解释:对a
和b
中的每个元素进行乘法运算。
示例2:列表索引
a = torch.tensor([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
b = a[0]
print(b)
运行结果:
tensor([[1, 2],[3, 4]])
解释:选择张量a
的第0个二维子张量。
示例3:范围索引
a = torch.tensor([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
b = a[:, 0, :]
print(b)
运行结果:
tensor([[1, 2],[5, 6]])
解释:选择张量a
中所有的第0个二维子张量的所有元素。
示例4:布尔索引
a = torch.tensor([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
b = a > 4
c = a[b]
print(c)
运行结果:
tensor([5, 6, 7, 8])
解释:选择张量a
中所有大于4的元素。
示例5:多维索引
a = torch.tensor([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
b = a[1, 1, 1]
print(b)
运行结果:
tensor(8)
解释:选择张量a
的第二个三维子张量中的第二个二维子张量中的第二个元素。
示例6:形状操作(reshape)
a = torch.tensor([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
b = a.reshape(4, 2)
print(b)
运行结果:
tensor([[1, 2],[3, 4],[5, 6],[7, 8]])
解释:将张量a
重塑为形状为(4, 2)的张量。
示例7:形状操作(squeeze)
a = torch.tensor([[[1, 2]], [[3, 4]], [[5, 6]]])
b = a.squeeze()
print(b)
运行结果:
tensor([[1, 2],[3, 4],[5, 6]])
解释:删除张量a
中所有为1的维度。
示例8:形状操作(unsqueeze)
a = torch.tensor([[1, 2], [3, 4], [5, 6]])
b = a.unsqueeze(1)
print(b)
运行结果:
tensor([[[1, 2]],[[3, 4]],[[5, 6]]])
解释:在张量a
的第一维度增加一个维度。
示例9:形状操作(transpose)
a = torch.tensor([[[1, 2, 3], [4, 5, 6]]])
b = a.transpose(1, 2)
print(b)
运行结果:
tensor([[[1, 4],[2, 5],[3, 6]]])
解释:交换张量a
的第1维和第2维。
示例10:形状操作(permute)
a = torch.tensor([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
b = a.permute(2, 0, 1)
print(b)
运行结果:
tensor([[[1, 3],[5, 7]],[[2, 4],[6, 8]]])
解释:根据指定的顺序重新排列张量a
的维度。
这篇关于深度学习 - 张量的广播机制和复杂运算的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!