python - PyTorch - 参数不变

标签 python machine-learning statistics pytorch

为了了解 pytorch 的工作原理,我正在尝试对多元正态分布中的一些参数进行最大似然估计。然而,它似乎不适用于任何与协方差相关的参数。

所以我的问题是:为什么这段代码不起作用?

import torch


def make_covariance_matrix(sigma, rho):
    return torch.tensor([[sigma[0]**2, rho * torch.prod(sigma)],
                         [rho * torch.prod(sigma), sigma[1]**2]])


mu_true = torch.randn(2)
rho_true = torch.rand(1)
sigma_true = torch.exp(torch.rand(2))

cov_true = make_covariance_matrix(sigma_true, rho_true)
dist_true = torch.distributions.MultivariateNormal(mu_true, cov_true)

samples = dist_true.sample((1_000,))

mu = torch.zeros(2, requires_grad=True)
log_sigma = torch.zeros(2, requires_grad=True)
atanh_rho = torch.zeros(1, requires_grad=True)

lbfgs = torch.optim.LBFGS([mu, log_sigma, atanh_rho])


def closure():
    lbfgs.zero_grad()
    sigma = torch.exp(log_sigma)
    rho = torch.tanh(atanh_rho)
    cov = make_covariance_matrix(sigma, rho)
    dist = torch.distributions.MultivariateNormal(mu, cov)
    loss = -torch.mean(dist.log_prob(samples))
    loss.backward()
    return loss


lbfgs.step(closure)

print("mu: {}, mu_hat: {}".format(mu_true, mu))
print("sigma: {}, sigma_hat: {}".format(sigma_true, torch.exp(log_sigma)))
print("rho: {}, rho_hat: {}".format(rho_true, torch.tanh(atanh_rho)))

输出:

mu: tensor([0.4168, 0.1580]), mu_hat: tensor([0.4127, 0.1454], requires_grad=True)
sigma: tensor([1.1917, 1.7290]), sigma_hat: tensor([1., 1.], grad_fn=<ExpBackward>)
rho: tensor([0.3589]), rho_hat: tensor([0.], grad_fn=<TanhBackward>)

>>> torch.__version__
'1.0.0.dev20181127'

换句话说,为什么 log_sigmaatanh_rho 的估计值没有偏离其初始值?

最佳答案

创建协方差矩阵的方式不是可逆概率的:

def make_covariance_matrix(sigma, rho):
    return torch.tensor([[sigma[0]**2, rho * torch.prod(sigma)],
                         [rho * torch.prod(sigma), sigma[1]**2]])

从(多个)张量创建新张量时,仅保留输入张量的值。来自输入张量的所有附加信息都被剥离,因此与参数的所有图形连接都从此时开始被切断,因此反向传播无法通过。

这是一个简短的示例来说明这一点:

import torch

param1 = torch.rand(1, requires_grad=True)
param2 = torch.rand(1, requires_grad=True)
tensor_from_params = torch.tensor([param1, param2])

print('Original parameter 1:')
print(param1, param1.requires_grad)
print('Original parameter 2:')
print(param2, param2.requires_grad)
print('New tensor form params:')
print(tensor_from_params, tensor_from_params.requires_grad)

输出:

Original parameter 1:
tensor([ 0.8913]) True
Original parameter 2:
tensor([ 0.4785]) True
New tensor form params:
tensor([ 0.8913,  0.4785]) False

如您所见,张量是根据参数 param1 创建的和param2 ,不跟踪 param1 的梯度和param2 .


因此,您可以使用此代码来保持图形连接并且可逆概率:

def make_covariance_matrix(sigma, rho):
    conv = torch.cat([(sigma[0]**2).view(-1), rho * torch.prod(sigma), rho * torch.prod(sigma), (sigma[1]**2).view(-1)])
    return conv.view(2, 2)

使用 torch.cat 将值连接到平面张量。然后使用 view() 将它们调整为正确的形状。
这会产生与函数中相同的矩阵输出,但它保持与参数的连接 log_sigmaatanh_rho .

这是更改 make_covariance_matrix 的步骤之前和之后的输出。如您所见,现在您可以优化参数,并且值确实会发生变化:

Before:
mu: tensor([ 0.1191,  0.7215]), mu_hat: tensor([ 0.,  0.])
sigma: tensor([ 1.4222,  1.0949]), sigma_hat: tensor([ 1.,  1.])
rho: tensor([ 0.2558]), rho_hat: tensor([ 0.])

After:
mu: tensor([ 0.1191,  0.7215]), mu_hat: tensor([ 0.0712,  0.7781])
sigma: tensor([ 1.4222,  1.0949]), sigma_hat: tensor([ 1.4410,  1.0807])
rho: tensor([ 0.2558]), rho_hat: tensor([ 0.2235])

希望这有帮助!

关于python - PyTorch - 参数不变,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53503234/

相关文章:

matlab - 为什么 Matlab signrank 函数在翻转数据点的符号时返回相同的符号秩统计值?

python - 在没有 lxml 的 Google Appengine 上使用 python-amazon-product-api

python - 计算每个网格点的值数组

machine-learning - 神经网络中的神经元应该异步吗?

python - 我如何知道哪个预测针对哪个数据?那么,如何评估预测呢?

mysql - 分析mysql数据

python - 在不规则列表列表中查找最长列表的长度

python - 从图像python中识别数字

multithreading - 如何使用多 CPU 核心使用 caffe 和 OpenBLAS 训练神经网络

r - 使用 Emacs/ESS 用 R 构建统计分析