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)。

以下是对代码的一些修正和说明:

  1. __init__方法中,使用super(Model, self).__init__()来正确地调用基类的初始化方法。
  2. 将权重和偏置的初始化移到了一个单独的init_parameters方法中,以保持代码的清晰。
  3. 使用PyroSample来定义模型中的随机变量。
  4. forward方法中,使用Variable来初始化隐藏状态和细胞状态。请注意,Variable在最新版本的PyTorch中已经被弃用,可以直接使用torch.zeros
  5. forward方法中,使用pyro.sample来定义观测数据的分布。
  6. 确保所有的张量操作都符合PyTorch的API,并且所有的张量都被移动到了正确的设备上(如果使用GPU)。

请注意,这个代码是一个示例,可能需要根据你的具体需求进行调整。此外,如果你使用的是PyTorch 1.0或更高版本,Variable已经不再需要,可以直接使用torch.tensor