深度学习实战(2)用Pytorch搭建双向LSTM

用Pytorch搭建双向LSTM

应最近的课程实验要求,要做LSTM和GRU的实验效果对比。LSTM的使用和GRU十分相似,欢迎参考我的另外一篇介绍搭建双向GRU的Blog:https://blog.csdn.net/icestorm_rain/article/details/108395515

参考Pytorch介绍LSTM的官方文档
其中其定义层时的参数声明方法与GRU完全一致:
在这里插入图片描述
所以,我定义LSTM使用以下代码:

torch.nn.LSTM(out_channels, hidden_size, n_layers, batch_first=True,bidirectional=self.bidirectional)

最关键的地方来了,那就是LSTM在做forward计算时要求输入的参数列表和GRU是不一样的!
在官方文档中GRU的输入格式如下:
它只需要 Input以及所有GRU单元的初始隐藏层状态
在这里插入图片描述
但是对于LSTM来说,还需要所有cell的初始状态,与初始隐藏层状态构成一个二元组进行输入,这是因为LSTM这个神经网络结构的参数是比GRU要多的,具体的可以去学习下两者架构的区别,在此就不做具体介绍了。LSTM的输入格式如下:
在这里插入图片描述
所以,我们来看看GRU与LSTM做forward时的代码区别:

# LSTM
output, (hidden, cell_state) = self.lstm(pooled,(hidden,hidden))
# GRU
output, hidden = self.gru(word_inputs, hidden)

其实区别就是在输入输出LSTM比GRU多了一个cell state。
总结到此结束,给个完整的神经网络代码供大家参考,这是一个CNN与LSTM结合的神经网络。

class HomorNetv3(torch.nn.Module):
    def __init__(self, input_dim,hidden_size, out_size, n_layers=1, batch_size=1,window_size=3,out_channels=200,bidirectional=True):
      super(HomorNetv3, self).__init__()

      self.batch_size = batch_size
      self.hidden_size = hidden_size
      self.n_layers = n_layers
      self.out_size = out_size
      self.out_channels = out_channels
      self.bidirectional = bidirectional
      # convolute the word_vectors first
      self.conv = nn.Conv2d(in_channels=1, out_channels=out_channels,kernel_size=(window_size, input_dim))
      self.conv2 = nn.Conv2d(in_channels=1, out_channels=out_channels,kernel_size=(20, input_dim))
      # 这里指定了 BATCH FIRST
      # then put it into GRU layers
      self.lstm = torch.nn.LSTM(out_channels, hidden_size, n_layers, batch_first=True,bidirectional=self.bidirectional)

      # 加了一个线性层,全连接
      if self.bidirectional:
        self.fc1 = torch.nn.Linear(hidden_size*2, 200)
      else:
        self.fc1 = torch.nn.Linear(hidden_size, 200)
      
      # output_layer
      self.fc2 = torch.nn.Linear(200, out_size)
        
    def forward(self, word_inputs, hidden):
       # hidden 就是上下文输出,output 就是 RNN 输出
      #print("word_inputs",word_inputs.shape)
      embedded = word_inputs.unsqueeze(1)
      feature_maps1 = self.conv(embedded)
      feature_maps2 = self.conv2(embedded)
      feature_maps = torch.cat((feature_maps1,feature_maps2),2)
      pooled = self.pool_normalize_function(feature_maps)
      #print("pooled",pooled)
      output, (hidden, cell_state) = self.lstm(pooled,(hidden,hidden))
      #print("gruoutput",output.shape)
      output = self.fc1(output)
      output = self.fc2(output)

      # 仅仅获取 time seq 维度中的最后一个向量
      # the last of time_seq
      output = output[:,-1,:]
      #print("beforesoftmax",output.shape)
      output = F.softmax(output,dim=1)
      print("output",output)
      return output, hidden

    def init_hidden(self):
      # 这个函数写在这里,有一定迷惑性,这个不是模型的一部分,是每次第一个向量没有上下文,在这里捞一个上下文,仅此而已。
      if self.bidirectional:
        hidden = torch.autograd.Variable(torch.zeros(2*self.n_layers, self.batch_size, self.hidden_size, device='cuda'))
      else:
        hidden = torch.autograd.Variable(torch.zeros(self.n_layers, self.batch_size, self.hidden_size, device='cuda'))
      return hidden

    def pool_normalize_function(self,feature_maps):
      ''' pool the vector '''
      feature_maps = feature_maps.squeeze(3)
      # Apply ReLU
      feature_maps = F.relu(feature_maps)
      # Apply the max pooling layer
      pooled = F.max_pool1d(feature_maps, 2)
      pooled = pooled.permute(0,2,1) # 转置矩阵
      normalized = F.normalize(pooled,p=2,dim=2)
      #normalized = normalized.unsqueeze(2)
      return normalized
  • 7
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要使用双向LSTM进行预测,可以按照以下步骤进行实现: 1. 定义模型:使用`nn.LSTM`模块,并设置`bidirectional=True`,以创建双向LSTM模型。 ```python import torch.nn as nn class BiLSTM(nn.Module): def __init__(self, input_size, hidden_size, num_layers, output_size): super(BiLSTM, self).__init__() self.hidden_size = hidden_size self.num_layers = num_layers self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True, bidirectional=True) self.fc = nn.Linear(hidden_size*2, output_size) def forward(self, x): h0 = torch.zeros(self.num_layers*2, x.size(0), self.hidden_size).to(device) # 初始化双向LSTM的隐状态h0和c0 c0 = torch.zeros(self.num_layers*2, x.size(0), self.hidden_size).to(device) out, _ = self.lstm(x, (h0, c0)) # 输入x和(h0, c0)到双向LSTM中进行前向传播 out = self.fc(out[:, -1, :]) # 取最后一个时间步的输出,并通过全连接层进行预测 return out ``` 2. 准备数据:准备训练集和测试集,并进行数据预处理。 ```python import torch from torch.utils.data import Dataset, DataLoader # 定义自定义数据集类 class MyDataset(Dataset): def __init__(self, data): self.data = data def __len__(self): return len(self.data) def __getitem__(self, index): x, y = self.data[index] return torch.tensor(x, dtype=torch.float32), torch.tensor(y, dtype=torch.float32) # 准备数据 train_data = [...] # 训练集 test_data = [...] # 测试集 train_dataset = MyDataset(train_data) test_dataset = MyDataset(test_data) train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True) test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=True) ``` 3. 训练模型:使用训练集对双向LSTM模型进行训练,并在测试集上进行验证。 ```python # 定义超参数 input_size = ... # 输入大小 hidden_size = ... # 隐藏层大小 num_layers = ... # LSTM层数 output_size = ... # 输出大小 batch_size = ... # 批量大小 num_epochs = ... # 训练轮数 learning_rate = ... # 学习率 # 初始化模型和优化器 model = BiLSTM(input_size, hidden_size, num_layers, output_size).to(device) criterion = nn.MSELoss() optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate) # 训练模型 for epoch in range(num_epochs): for i, (inputs, labels) in enumerate(train_loader): inputs = inputs.to(device) labels = labels.to(device) outputs = model(inputs) loss = criterion(outputs, labels) optimizer.zero_grad() loss.backward() optimizer.step() print('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, num_epochs, loss.item())) # 测试模型 with torch.no_grad(): correct = 0 total = 0 for inputs, labels in test_loader: inputs = inputs.to(device) labels = labels.to(device) outputs = model(inputs) _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() print('Test Accuracy: {} %'.format(100 * correct / total)) ``` 在上述代码中,我们使用MSE损失函数和Adam优化器对模型进行训练,并使用测试集计算模型的准确率。在每个epoch中,我们打印出当前的损失值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值