ref:
torch.Tensor.index_add_能实现指定行或列的内容相加的功能,类似于tensorflow中tf.unsorted_segment_sum
函数,可以用在比如实例分割中进行特征聚合的步骤。比如一个N*C
的feature根据实例label可以将属于同一实例的点的特征聚合起来,得到Ins_num*C
的聚合特征。
x
相加前后的shape保持不变,被索引的tensor在被索引的维度(第dim维)之外的维度上与tensor的对应维度必须保持一致,且index
中的值最大不能超过x
在被索引的维度上的最大维数,index
的长度必须和tensor[dim]
相同。假如x的shape
为(N, C)
,索引的维度为第0维(dim=0
),那么被索引的tensor的dim=1
的维度也必须为C
,index的值必须介于0
和C-1
之间,index
的长度必须和被索引的tensor的dim=0
的数字相同。import torch
x = torch.ones(5, 3)
t = torch.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]], dtype=torch.float)
index = torch.tensor([0, 2, 4, 2])
new_x = x.index_add_(0, index, t) # 把x的每一行加上index从t中索引出来的值
print('new_x: {}'.format(new_x))
new_x: tensor([[ 2., 3., 4.],
[ 1., 1., 1.],
[15., 17., 19.],
[ 1., 1., 1.],
[ 8., 9., 10.]])
解释一下:x.index_add_()
表示在x的每一行加上index
从t中索引出来的值,这个例子中x初始为一个5行3列全为1的tensor。
i
行要加上的值,首先通过index[j]=i
找到所有满足条件的j
,再把所有的t[j]
加上x[i]
就得到新的x[i]
。一行行来看。index
中值为0的的索引,找index[j]=0
,所以j=0
,新的new_x[0]=t[0]+x[0]
,即new_x[0]=[1, 2, 3]+[1, 1, 1]=[2, 3, 4]
。index
中值为1的的索引,找不到对应的j,所以没有东西可以加上,new_x[1]
保持不变。index
中值为2的的索引,找index[j]=2
,所以j=1, 3
,新的new_x[2]=t[1]+t[3]+x[0]
,即new_x[2]=[4, 5, 6]+[10, 11, 12]+[1, 1, 1]==[15, 17, 19]
。index
中值为3的的索引,找不到对应的j,所以没有东西可以加上,new_x[3]
保持不变。index
中值为4的的索引,找index[j]=4
,所以j=2
,新的new_x[4]=t[2]+x[4]
,即new_x[4]=[7, 8, 9]+[1, 1, 1]=[8, 9, 10]
。(Ins_num, C)
的全0数组;t设置为需要被索引的feature,其shape为(N, C)
;索引就可以为实例label,shape为(N, )
。0
到Ins_num-1
。(如果这个当中某些背景点的label为-100或者其他值就要注意了,索引会报错,记得处理一下)(Ins_num, C)
的新tensor,每i
行代表对应实例label为i
的所有点相加后的特征。