Python PyTorch相当于索引_add u,取最大值

Python PyTorch相当于索引_add u,取最大值,python,pytorch,Python,Pytorch,在PyTorch中,张量的索引添加方法使用提供的索引张量进行求和: idx = torch.LongTensor([0,0,0,0,1,1]) child = torch.FloatTensor([1, 3, 5, 10, 8, 1]) parent = torch.FloatTensor([0, 0]) parent.index_add_(0, idx, child) 前四个子值相加为父值[0],后两个子值相加为父值[1],因此结果为张量([19,9.]) 但是,我需要做index\u ma

在PyTorch中,张量的
索引添加
方法使用提供的索引张量进行求和:

idx = torch.LongTensor([0,0,0,0,1,1])
child = torch.FloatTensor([1, 3, 5, 10, 8, 1])
parent = torch.FloatTensor([0, 0])
parent.index_add_(0, idx, child)
前四个子值相加为父值[0],后两个子值相加为父值[1],因此结果为
张量([19,9.])

但是,我需要做
index\u max\u
,这在API中是不存在的。有没有一种有效的方法(不必循环或分配更多内存)?一个(坏的)循环解决方案是:

for i in range(max(idx)+1):
    parent[i] = torch.max(child[idx == i])

这就产生了所需的张量([10,8.]),但速度非常慢。

一种解决方案,可以使用索引:

def index_max(子分区、idx分区、num分区):
#构建num\u分区x num\u示例矩阵'idx\u tiled':
partition_idx=torch.range(0,num_partitions-1,dtype=torch.long)
partition\u idx=partition\u idx.view(-1,1).expand(num\u partitions,idx.shape[0])
idx_tiled=idx.view(1,-1)。重复(num_分区,1)
idx_tiled=(idx_tiled==分区.float()
#即,如果idx[j]==i,则idx_平铺[i,j]==1,否则为0
父项=idx_平铺*子项
父级,u=火炬最大值(父级,尺寸=1)
返回父级
基准:

import timeit
设置=“”
进口火炬
def index_max_v0(子分区、idx分区、num_分区):
parent=torch.zero(num_分区)
对于范围内的i(最大(idx)+1):
父[i]=torch.max(子[idx==i])
返回父级
def index_max(子分区、idx分区、num_分区):
#构建num_分区x num_采样矩阵'idx_tiled`
#包含索引的每行
partition_idx=torch.range(0,num_partitions-1,dtype=torch.long)
partition\u idx=partition\u idx.view(-1,1).expand(num\u partitions,idx.shape[0])
idx_tiled=idx.view(1,-1)。重复(num_分区,1)
idx_tiled=(idx_tiled==分区.float()
父项=idx_平铺*子项
父级,u=火炬最大值(父级,尺寸=1)
返回父级
idx=火炬长传感器([0,0,0,0,1,1])
child=torch.FloatTensor([1,3,5,10,8,1])
num_partitions=torch.unique(idx).shape[0]
'''
打印(最小值(timeit.Timer('index_max_v0(子分区、idx分区、num_分区)'),设置=设置)。重复(51000)))
# > 0.05308796599274501
打印(最小值(timeit.Timer('index\u max(子分区、idx分区、num\u分区)),设置=设置。重复(51000)))
# > 0.024736385996220633

这确实更快,但我希望避免分配(num\u分区x num\u样本)临时存储。你认为有没有一种比循环更快的内存效率更高的方法,或者是我们在没有API支持的情况下所能做的最好的方法?是的,这里的内存分配确实是一个缺点。。。我想不出比这更好的方法了,也没有比当前API的循环更好的方法了,尽管我不是完全最新的。。。一个相当于的可能是一个很好的功能在这里。。。