pyro中建立贝叶斯LSTM模型
。在这个阶段,只有一个LSTM器和两个线性连接到输出端。我为pytorch lstm做了同样的例子,以确保代码能够顺利运行并获得良好的结果。现在,当我尝试将代码更改为pyro进行贝叶斯估计,并为LSTM模块和线性模块赋予权重时,我发现在训练模型后,我的预测几乎不稳定,并且不遵循任何趋势!然而,pytorch的传统LSTM至少给出了一个好的趋势。
如果有人能告诉我如何发现这个问题,以及如何使贝叶斯LSTM预测模型更好,我将不胜感激。这将有助于其他研究人员,因为我做了大量的调查,但是还没有找到以前解决过的LSTM案例
import torch
import torch.nn as nn
import pyro
from pyro.distributions import Normal, Gamma
from pyro.nn import PyroModule, PyroSample
from torch.autograd import Variable
class Model(PyroModule):
def __init__(self, input_size=1, num_classes=1, hidden_size=3, num_layers=1, prior_scale=50.0):
super(Model, self).__init__()
self.num_classes = num_classes
self.num_layers = num_layers
self.input_size = input_size
self.hidden_size = hidden_size
# 使用PyroModule包装nn.Module
self.lstm = PyroModule[nn.LSTM](input_size, hidden_size, num_layers, batch_first=True, bidirectional=False)
self.linear = PyroModule[nn.Linear](hidden_size, 128) # 调整为单向LSTM
self.fc = PyroModule[nn.Linear](128, num_classes)
# 初始化权重和偏置
self.init_parameters(prior_scale)
def init_parameters(self, prior_scale):
# 输入到隐藏层
self.lstm.weight_ih_l0 = PyroSample(Normal(0., prior_scale).expand([4 * self.hidden_size, self.input_size]).to_event(2))
self.lstm.bias_ih_l0 = PyroSample(Normal(0., prior_scale).expand([4 * self.hidden_size]).to_event(1))
# 隐藏到隐藏层
self.lstm.weight_hh_l0 = PyroSample(Normal(0., prior_scale).expand([4 * self.hidden_size, self.hidden_size]).to_event(2))
self.lstm.bias_hh_l0 = PyroSample(Normal(0., prior_scale).expand([4 * self.hidden_size]).to_event(1))
self.linear.weight = PyroSample(Normal(0., prior_scale).expand([128, self.hidden_size]).to_event(2))
self.linear.bias = PyroSample(Normal(0., prior_scale).expand([128]).to_event(1))
self.fc.weight = PyroSample(Normal(0., prior_scale).expand([self.num_classes, 128]).to_event(2))
self.fc.bias = PyroSample(Normal(0., prior_scale).expand([self.num_classes]).to_event(1))
def forward(self, x, y=None, noise_shape=0.5):
h_0 = Variable(torch.zeros(self.num_layers, x.size(0), self.hidden_size))
c_0 = Variable(torch.zeros(self.num_layers, x.size(0), self.hidden_size))
output, (hn, cn) = self.lstm(x, (h_0, c_0))
hn = hn.view(-1, self.hidden_size)
out = self.activation(hn)
out = self.linear(out)
out = self.activation(out)
mu = self.fc(out)
sigma = pyro.sample("sigma", Gamma(noise_shape, 1.0)) # 推断响应噪声
with pyro.plate("data", x.shape[0]):
obs = pyro.sample("obs", Normal(mu, sigma), obs=y)
return mu
# 注意:在实际使用中,你需要确保所有的张量都被移动到了正确的设备上(CPU或GPU)。
以下是对代码的一些修正和说明:
- 在
__init__
方法中,使用super(Model, self).__init__()
来正确地调用基类的初始化方法。 - 将权重和偏置的初始化移到了一个单独的
init_parameters
方法中,以保持代码的清晰。 - 使用
PyroSample
来定义模型中的随机变量。 - 在
forward
方法中,使用Variable
来初始化隐藏状态和细胞状态。请注意,Variable
在最新版本的PyTorch中已经被弃用,可以直接使用torch.zeros
。 - 在
forward
方法中,使用pyro.sample
来定义观测数据的分布。 - 确保所有的张量操作都符合PyTorch的API,并且所有的张量都被移动到了正确的设备上(如果使用GPU)。
请注意,这个代码是一个示例,可能需要根据你的具体需求进行调整。此外,如果你使用的是PyTorch 1.0或更高版本,Variable
已经不再需要,可以直接使用torch.tensor
。