PyTorch - 28 - PyTorch,TensorFlow和NumPy中的Stack vs Concat - 深度学习Tensor Ops
Existing Vs New Axes
张量和级联张量之间的差异可以用一个句子描述,所以这里是。
级联沿着现有轴连接一系列张量,而堆叠则沿着新轴连接一系列张量。
这就是全部!
这是堆叠和串联之间的区别。但是,这里的描述有些棘手,因此让我们看一些示例,以了解如何更好地理解这一点。我们将介绍在PyTorch,TensorFlow和NumPy中的堆叠和连接。我们开始做吧。
在大多数情况下,沿着张量的现有轴进行连接非常简单。当我们想沿着新的轴进行连接时,通常会产生混乱。为此,我们堆叠。表示堆叠的另一种方式是说我们创建一个新轴,然后在该轴上连接。
Join Method | Where |
---|---|
Concatenate | 沿现有轴连接 |
Stack | 沿新轴堆叠 |
因此,请确保我们知道如何为给定张量创建新轴,然后开始堆叠和连接。
How To Add Or Insert An Axis Into A Tensor
为了演示添加轴的想法,我们将使用PyTorch。
import torch
t1 = torch.tensor([1,1,1])
在这里,我们要导入PyTorch并创建一个简单的张量,其单轴长度为3。现在,要在PyTorch中向张量添加轴,我们使用unsqueeze()函数。请注意,这与压缩相反。
> t1.unsqueeze(dim=0)
tensor([[1, 1, 1]])
在这里,我们正在添加一个轴,也就是该张量的索引零处的尺寸。这给我们一个形状为1 x 3的张量。当我们说张量的索引为零时,是指张量形状的第一个索引。
现在,我们还可以在该张量的第二个索引处添加一个轴。
> t1.unsqueeze(dim=1)
tensor([[1],
[1],
[1]])
这为我们提供了一个3 x 1形状的张量。添加这样的轴会更改数据在张量内部的组织方式,但不会更改数据本身。基本上,我们只是在重塑张量。通过检查每个形状,我们可以看到这一点。
> print(t1.shape)
> print(t1.unsqueeze(dim=0).shape)
> print(t1.unsqueeze(dim=1).shape)
torch.Size([3])
torch.Size([1, 3])
torch.Size([3, 1])
现在,回想一下级联堆叠的问题,当我们进行合并时,我们将沿着现有轴连接一系列张量。这意味着我们正在扩展现有轴的长度。
当我们堆叠时,我们正在创建一个以前不存在的新轴,并且该轴遍历了序列中的所有张量,然后沿着这个新序列进行合并。
让我们看看如何在PyTorch中完成此操作。
Stack Vs Cat In PyTorch
使用PyTorch,我们用于这些操作的两个函数是stack和cat。让我们创建一个张量序列。
import torch
t1 = torch.tensor([1,1,1])
t2 = torch.tensor([2,2,2])
t3 = torch.tensor([3,3,3])
现在,让我们将它们彼此串联在一起。请注意,每个张量都具有一个轴。这意味着cat函数的结果也将具有单个轴。这是因为当我们连接时,我们会沿着现有的轴进行连接。请注意,在此示例中,唯一存在的轴是第一个轴。
> torch.cat(
(t1,t2,t3)
,dim=0
)
tensor([1, 1, 1, 2, 2, 2, 3, 3, 3])
好了,所以我们取了三个单轴张量,每个张量的轴长为3,现在我们有了一个单张量,轴长为9。
现在,让我们沿着将要插入的新轴堆叠这些张量。我们将在第一个索引处插入一个轴。请注意,此插入将由stack函数在后台隐式发生。
> torch.stack(
(t1,t2,t3)
,dim=0
)
tensor([[1, 1, 1],
[2, 2, 2],
[3, 3, 3]])
这为我们提供了一个新的张量,其形状为3 x3。请注意,这三个张量是如何沿着该张量的第一个轴连接的。请注意,我们还可以显式插入新轴,然后直接执行串联。
看到这句话是真的。让我们张开所有的张量,添加一个长度为1的新轴,然后沿第一个轴倾斜。
> torch.cat(
(
t1.unsqueeze(0)
,t2.unsqueeze(0)
,t3.unsqueeze(0)
)
,dim=0