如何将 PyTorch 的 torch.inverse() 函数应用于批次中的每个样本?
Posted
技术标签:
【中文标题】如何将 PyTorch 的 torch.inverse() 函数应用于批次中的每个样本?【英文标题】:How to apply the torch.inverse() function of PyTorch to every sample in the batch? 【发布时间】:2018-03-17 15:15:09 【问题描述】:这似乎是一个基本问题,但我无法解决。
在我的神经网络的正向传递中,我有一个形状为 8x3x3 的输出张量,其中 8 是我的批量大小。我们可以假设每个 3x3 张量是一个非奇异矩阵。我需要找到这些矩阵的逆矩阵。 PyTorch inverse() 函数仅适用于方阵。由于我现在有 8x3x3,如何以可微分的方式将此函数应用于批次中的每个矩阵?
如果我遍历样本并将逆向附加到 python 列表,然后我将其转换为 PyTorch 张量,在反向传播期间是否会出现问题? (我问的是因为将 PyTorch 张量转换为 numpy 以执行某些操作,然后再返回张量不会在此类操作的反向传播期间计算梯度)
当我尝试做类似的事情时,我也会收到以下错误。
a = torch.arange(0,8).view(-1,2,2)
b = [m.inverse() for m in a]
c = torch.FloatTensor(b)
TypeError: 'torch.FloatTensor' 对象不支持索引
【问题讨论】:
【参考方案1】:编辑:
从 Pytorch 1.0 版开始,torch.inverse
现在支持批量张量。见here。所以你可以简单地使用内置函数torch.inverse
老答案
计划很快实施批量逆。有关讨论,请参见例如 issue 7500 或 issue 9102。但是,在撰写本文时,当前的稳定版本(0.4.1)还没有批量逆操作可用。
话虽如此,最近添加了对torch.gesv
的批量支持。这可以(ab)用于定义您自己的批量逆运算,如下所示:
def b_inv(b_mat):
eye = b_mat.new_ones(b_mat.size(-1)).diag().expand_as(b_mat)
b_inv, _ = torch.gesv(eye, b_mat)
return b_inv
我发现在 GPU 上运行时,这比 for 循环提供了很好的加速。
【讨论】:
目前这似乎是最好的选择。谢谢。 torch.gesv 的替代方案是什么?好像已经被弃用了。torch.gesv
已在 pytorch-1.2.0 (source) 中替换为 torch.solve
【参考方案2】:
您可以使用torch.functional.unbind()
拆分张量,对结果的每个元素应用逆,然后再叠加:
a = torch.arange(0,8).view(-1,2,2)
b = [t.inverse() for t in torch.functional.unbind(a)]
c = torch.functional.stack(b)
【讨论】:
这看起来非常非常慢! 在torch 1.1中unbind
已经消失了。可以改用torch.functional.split
。以上是关于如何将 PyTorch 的 torch.inverse() 函数应用于批次中的每个样本?的主要内容,如果未能解决你的问题,请参考以下文章
如何将 AMD GPU 用于 fastai/pytorch?