计算Pytorch网络参数空间中的距离



我是Pytorch的新手。我想跟踪参数空间中的距离,我的模型通过其优化传播。这是我正在使用的代码。

class ParameterDiffer(object):
    def __init__(self, network):
        network_params = []
        for p in network.parameters():
            network_params.append(p.data.numpy())
        self.network_params = network_params
    def get_difference(self, network):
        total_diff = 0.0
        for i, p in enumerate(network.parameters()):
            p_np = p.data.numpy()
            diff = self.network_params[i] - p_np
            # print(diff)
            scalar_diff = np.sum(diff ** 2)
            total_diff += scalar_diff
        return total_diff

这个可以吗?我一直跟踪total_diff的时间,并正在记录它,但似乎总是为零。即使模型的性能正在改善,这使我非常困惑。

原因

这是因为Pytorch处理Numpy阵列和Torch Tensor之间的转换方式。如果Numpy阵列和火炬张量之间的基本数据类型相同,则它们将共享内存。更改一个值也将更改另一个值的值。我将在这里显示一个具体示例

x = Variable(torch.rand(2, 2))
y = x.data.numpy()
x
Out[39]: 
Variable containing:
 0.8442  0.9968
 0.7366  0.4701
[torch.FloatTensor of size 2x2]
y
Out[40]: 
array([[ 0.84422851,  0.996831  ],
       [ 0.73656738,  0.47010136]], dtype=float32)

然后,如果您更改X 在场并查看x和y中的值,您会发现它们仍然相同。

x += 2
x
Out[42]: 
Variable containing:
 2.8442  2.9968
 2.7366  2.4701
[torch.FloatTensor of size 2x2]
y
Out[43]: 
array([[ 2.84422851,  2.99683094],
       [ 2.7365675 ,  2.47010136]], dtype=float32)

因此,在模型更新期间,模型和类ParameterDiffer中的参数始终相同。这就是为什么您看到零。

如何解决这个问题?

如果numpy阵列和火炬张量的基础数据类型不兼容,它将迫使火炬张量中的原始数据副本,这将使Numpy阵列和Torch Tensor具有单独的内存。

一种简单的方法只是将numpy数组转换为类型np.float64。而不是

network_params.append(p.data.numpy())

您可以使用

network_params.append(p.data.numpy().astype(np.float64))

重要参考

  1. http://pytorch.org/tutorials/beginner/blitz/tensor_tutorial.html#numpy-bridge
  2. https://github.com/pytorch/pytorch/issues/2246

最新更新