python - 在 Pytorch 中为模型注册参数的正确方法
问题描述
我试图在 Pytorch 中定义一个简单的模型。该模型计算高斯分布的负对数概率:
import torch
import torch.nn as nn
class GaussianModel(nn.Module):
def __init__(self):
super(GaussianModel, self).__init__()
self.register_parameter('mean', nn.Parameter(torch.zeros(1),
requires_grad=True))
self.pdf = torch.distributions.Normal(self.state_dict()['mean'],
torch.tensor([1.0]))
def forward(self, x):
return -self.pdf.log_prob(x)
model = GaussianModel()
然后我尝试优化mean
参数:
optimizer = torch.optim.SGD(model.parameters(), lr=0.002)
for _ in range(5):
optimizer.zero_grad()
nll = model(torch.tensor([3.0], requires_grad=True))
nll.backward()
optimizer.step()
print('mean : ', model.state_dict()['mean'],
' - Negative Loglikelihood : ', nll.item())
但似乎梯度为零并且mean
没有改变:
mean : tensor([0.]) - Negative Loglikelihood : 5.418938636779785
mean : tensor([0.]) - Negative Loglikelihood : 5.418938636779785
mean : tensor([0.]) - Negative Loglikelihood : 5.418938636779785
mean : tensor([0.]) - Negative Loglikelihood : 5.418938636779785
mean : tensor([0.]) - Negative Loglikelihood : 5.418938636779785
我是否mean
正确注册和使用了参数?autograd 可以计算梯度torch.distributions.Normal.log_prob
还是我应该backward()
为模型实现梯度?
解决方案
您注册参数过于复杂。您可以将一个新self.mean
属性分配为nn.Parameter
然后在大多数情况下像张量一样使用它。
nn.Module
覆盖__setattr__
每次分配新类属性时调用的方法。它所做的其中一件事是检查您是否分配了一个nn.Parameter
类型,如果是,它会将其添加到已注册参数的模块字典中。
因此,注册参数的最简单方法如下:
import torch
import torch.nn as nn
class GaussianModel(nn.Module):
def __init__(self):
super(GaussianModel, self).__init__()
self.mean = nn.Parameter(torch.zeros(1))
self.pdf = torch.distributions.Normal(self.mean, torch.tensor([1.0]))
def forward(self, x):
return -self.pdf.log_prob(x)
推荐阅读
- javascript - 如何在 Meteor 中查询具有满足条件的子文档的文档?
- r - 查找特定单元格
- javascript - Chai-http:发送 204 状态而不是预期状态
- angular - 带有 ASP .Net Core 2.1 的 Angular 6 SSR:未定义窗口
- c# - 如何使用 selenium C# 访问 HTML 表
- java - 将 angular2-query-builder 查询转换为逻辑表达式
- android - 使用变量时的 Gradle 库版本建议
- java - 位图“图像”传递给另一个活动(内存不足)
- ruby - 如何在更新 xml 节点的内容时保留 CDATA?
- java - IDEA java总是生成私有方法