我有一个二维Tensor:
samples = torch.Tensor([
[0.1, 0.1], #-> group / class 1
[0.2, 0.2], #-> group / class 2
[0.4, 0.4], #-> group / class 2
[0.0, 0.0] #-> group / class 0
])
以及对应于类的每个样本的标签:
labels = torch.LongTensor([1, 2, 2, 0])
因此len(samples) == len(labels)
。现在我想计算每个类/标签的平均值。因为有3个类(0、1和2),所以最终向量的维数应为[n_classes, samples.shape[1]]
。因此,预期解应为:
result == torch.Tensor([
[0.1, 0.1],
[0.3, 0.3], # -> mean of [0.2, 0.2] and [0.4, 0.4]
[0.0, 0.0]
])
问题:如何在没有for循环的情况下,在纯pytorch(即没有numpy,这样我就可以autograd)中完成这一操作?
4条答案
按热度按时间neskvpey1#
你需要做的就是构造一个mxn矩阵(m=num个类,n=num个样本),它将选择合适的权重,并适当地缩放均值。然后你可以在新构造的矩阵和样本矩阵之间执行矩阵乘法。
给定您的标签,您的矩阵应为(每行是一个类编号,每个类是一个样本编号及其权重):
可以按如下方式形成:
输出量:
请注意,输出均值按类顺序正确排序。
为什么
M[labels, torch.arange(len(samples))] = 1
可以工作?这是在标签和样本数之间执行广播操作。本质上,我们为标签中的每个元素生成一个二维索引:第一种方法指定它属于m个类中的哪一个,第二种方法简单地指定它的索引位置(从1到N)。另一种方法是显式地生成所有2D索引:
p8ekf7hl2#
在此重新发布来自Pytorch forums中@ptrblck_de的答案
0md85ypi3#
由于以前的解决方案不适用于稀疏组的情况(例如,不是所有的组都在数据中),因此我做了一个:)
mgdq6dx14#
对于3DTensor:
对于那些感兴趣的人。我将@yhenon的答案扩展到了这样的情况,其中
labels
是一个2DTensor,samples
是一个3DTensor。如果你想批量执行这个操作(就像我一样),这可能会很有用。但是它附带了一个警告(见最后)。第一个
输出量:
**注意:**现在,
result[0]
的长度为4(而不是@yhenon的答案中的3),因为labels[1]
包含3。最后一行只包含0。如果你不排除结果Tensor最后一行中的0,你可以使用这段代码,并在以后处理0。