pytorch 中关于创建简单mask,张量的索引,变换,张量轴,[None,:]与unsqueeze()的思考


开幕上图,我在实验过程中发现[None,:}和unsqueeze(0)产生了同样的效果,那么我们来探寻一下原理

原本的目的是创建一个[1,2,1]分别是各行从左到右true的数量的mask。如图的结果那般。
第一步:创建一个适合的向量,又分为两步
(1)先找出length中最大的数确定形状,这里使用了max()和item().
(2)用torch.arange()变为合适的向量,即

第二步:创建矩阵,利用torch的广播功能把适合的值变成true
这个过程就利用了[None,:]的功能,它为张量[0,1]增添了一个新的轴,让它从一阶张量(向量)变为二阶张量(矩阵)

可以看到虽然似乎数据没变,但中括号增加一对,阶数增加了!
对于[1,2,1]自然也是同样的道理,不过此时出现了差别,我们现在不仅要增加它的阶数,还要让它变为列向量,即[[1],[2],[1]]的形式,所以我们现在使用[:,None],而其中具体原因是我们后续考虑的另一个问题。

获得这两个二阶张量后,我们只需要利用一下pytorch的广播功能就可以通过简单的比较获得mask了!

但其实我不是很在意mask的事

我主要还是想知道为什么[None,:]和[:,None]会有所差异,而且为何[None,:]与unsqueeze(0)是一样的。

我想如果搞清楚pytorch中张量的轴的问题大概就可以了。

何为张量的轴呢,其实几阶张量就有几个轴,他们在表示的时候会有着固定的排序。
举例来说,对于size为[1,2,3,4]的的一个张量,后面的3和4代表三行四列的矩阵,前面的2代表这样的三行四列矩阵会有两个,1又代表这样的矩阵团队有一个,对于更高阶的情况可以以此类推下去。
并且在[1,0]这样仅为一个向量的情况下,我们是不需要考虑轴这个概念的。

所以,我们重点关注矩阵的行列情况。

而对于一个矩阵,我们会有这样的一个0轴和1轴的划分

所以上边关于[None,:]和[:,None]的问题其实可以这么解释:
[None,:]:增加了0轴但0轴没有设定参数(None),所以会表示为[[1,0]]这样一个仅有一行的矩阵
[:,None]:增加了1轴但1轴没有设定参数(None),所以会表示为[[1],[2],[1]]这样一个仅有一列的矩阵

而unsqueeze(0)与unsqueeze(1)括号中的参数同样可以用0轴和1轴来解释!

到此,我的问题似乎得到了初步的解释。

另外值得注意的是,索引存在负数的表示。

我们可以使用-1作为最后一个维度,-2表示倒数第二个维度。。。
比方说我们现在有一个4阶张量,
"批次"可以用dim=0,dim=-4访问
"通道"可以用dim=1,dim=-3访问
"高度"可以用dim=2,dim=-2访问
"宽度"可以用dim=3,dim=-1访问
再比方说,一个1阶张量,阶数dim的范围是[-1,0].

sum()和unsqueeze()可以联合使用

sum(dim)方法可以对指定的dim进行加和,相应随之而来的是张量阶数会下降1阶,如:

而相应的unsqueeze()可以对张量升阶,让sum()运算只停留在求和的层面,不对张量阶数造成影响,如: