ニューラル ネットワーク内に、値が 0 ~ 1 の 2D 特徴マップがいくつかあります。これらのマップでは、各座標の値に基づいて共分散行列を計算したいと考えています。残念ながら、pytorch には.cov()
numpy のような機能はありません。そこで、代わりに次の関数を書きました。
def get_covariance(tensor):
bn, nk, w, h = tensor.shape
tensor_reshape = tensor.reshape(bn, nk, 2, -1)
x = tensor_reshape[:, :, 0, :]
y = tensor_reshape[:, :, 1, :]
mean_x = torch.mean(x, dim=2).unsqueeze(-1)
mean_y = torch.mean(y, dim=2).unsqueeze(-1)
xx = torch.sum((x - mean_x) * (x - mean_x), dim=2).unsqueeze(-1) / (h * w - 1)
xy = torch.sum((x - mean_x) * (y - mean_y), dim=2).unsqueeze(-1) / (h * w - 1)
yx = xy
yy = torch.sum((y - mean_y) * (y - mean_y), dim=2).unsqueeze(-1) / (h * w - 1)
cov = torch.cat((xx, xy, yx, yy), dim=2)
cov = cov.reshape(bn, nk, 2, 2)
return cov
それは正しい方法ですか?
編集:
numpy 関数との比較は次のとおりです。
a = torch.randn(1, 1, 64, 64)
a_numpy = a.reshape(1, 1, 2, -1).numpy()
torch_cov = get_covariance(a)
numpy_cov = np.cov(a_numpy[0][0])
torch_cov
tensor([[[[ 0.4964, -0.0053],
[-0.0053, 0.4926]]]])
numpy_cov
array([[ 0.99295635, -0.01069122],
[-0.01069122, 0.98539236]])
どうやら、私の値は 2 分の 1 に小さすぎるようです。なぜでしょうか?
Edit2:ああ、私はそれを理解しました。で割る必要があり(h*w/2 - 1)
ます:)その後、値が一致します。