使用Pytorch手动实现单层LSTM

本文详细介绍了如何在Pytorch中手动实现单层LSTM,包括LSTM的基本原理、权重定义、输入输出处理及代码实现。作者在研究元学习过程中遇到Pytorch Module不支持特定操作的问题,因此选择手动实现LSTM。文章强调了手动实现的重点在于理解权重形状和计算流程,以及在实际编码中需要注意的细节。
摘要由CSDN通过智能技术生成

背景

最近在研究meta learning(元学习),正在尝试其中一个非常经典的方法叫做MAML(Model Agnostic Meta Learning)。这个方法比较特殊,需要我们维护两套模型的权重,并且进行求导,而Pytorch中封装好的Module模块不支持这样的做法(我没有找到很好的方法,如果有大神知道还望赐教),因此需要手动去实现各种层。

对于卷积、BatchNorm等层,Pytorch提供了Functional接口,如torch.nn.functional.conv2d等,这些接口支持我们传入自定义的权重,因此手动实现一个卷积层相对简单一些,过程如下:

# 定义权重 weight: out_ch, in_ch, kernel_size, kernel_size
# b: out_ch
w = nn.Parameter(torch.ones(out_ch, in_ch, kernel_size, kernel_size))
b = nn.Parameter(torch.zeors(out_ch))
output = nn.functional.conv2d(input, w, b, stride, padding)

然而在官方文档里,并没有找到LSTM的相应接口,所以就必须得自己实现了,这篇文章主要记录一下这个过程。

单层LSTM实现

首先看一下LSTM的原理示意图,此图引自台大李宏毅教授机器学习课程的PPT,关于LSTM比较细致的理解,可以去B站先看一下李洪义老师的课程或者可以看一下知乎陈诚老师的这篇人人都能看懂的LSTM

本文主要关注于LSTM的实现,对于其原理(比如几个门各自的作用,为什么网络要这么设计之类的)不会有太多阐述,其实主要是因为这一部分我自己还没太弄明白,但是目前觉得并不影响实现,所以如果有错误的地方还望大家指出。
LSTM原理示意图

LSTM简单原理

LSTM其实主要就是由隐藏状态h记忆细胞c四个门控状态所组成,其中这四个门控状态里可以细分为三个门控状态和一个候选记忆细胞,但是在实现时简单起见可以把他们看成是一样的中间状态。LSTM的过程其实可以看做通过当前时间步输入 x t x_t xt,上一步的隐藏层 h t − 1 h_{t-1} ht1来决定四个中间状态,然后通过这四个中间状态联合上一步的细胞状态 c t − 1 c_{t-1} ct1来决定当前时间步的隐藏层 h t h_{t} ht细胞状态 c t c_{t} ct以及输出 y t y_t yt

生成的公式在官方文档中有详细的阐述:
在这里插入图片描述

LSTM重要向量形状

看明白网络的计算方法后,我们先来看一下网络各个部分比较重要的形状。LSTM要求输入的形状为 T ∗ B ∗ C T * B * C TBC,其中, T T T代表输入的序列长度,也就是时间步的长度; B B B代表Batch size,输入样本的数量; C C C代表特征的通道数,可以理解为一个时间步上的特征用多少个通道来表示。因此可知,每一个时间步的输入 x t x_t xt的形状为 B ∗ C B * C BC。同时,隐藏状态 h t h_{t} ht和候选细胞状态 c t c_{t} c

  • 7
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
好的,以下是一个基于 PyTorch 实现双层 LSTM 的示例代码: ```python import torch import torch.nn as nn class DoubleLSTM(nn.Module): def __init__(self, input_size, hidden_size, num_layers): super(DoubleLSTM, self).__init__() self.num_layers = num_layers self.hidden_size = hidden_size # 第一层 LSTM self.lstm1 = nn.LSTM(input_size, hidden_size, num_layers) # 第二层 LSTM self.lstm2 = nn.LSTM(hidden_size, hidden_size, num_layers) def forward(self, inputs, hidden): # 第一层 LSTM 的前向计算 output1, hidden1 = self.lstm1(inputs, hidden[0]) # 第二层 LSTM 的前向计算 output2, hidden2 = self.lstm2(output1, hidden[1]) return output2, (hidden1, hidden2) def init_hidden(self, batch_size): # 初始化隐藏状态 hidden1 = torch.zeros(self.num_layers, batch_size, self.hidden_size) hidden2 = torch.zeros(self.num_layers, batch_size, self.hidden_size) return (hidden1, hidden2) ``` 在上述代码中,我们定义了一个名为 DoubleLSTM 的类,它继承自 PyTorch 的 nn.Module 类。在该类的初始化方法中,我们首先定义了两个 LSTM 层,分别是第一层 LSTM 和第二层 LSTM。在 forward 方法中,我们调用了两个 LSTM 层的前向计算方法,分别是 lstm1 和 lstm2。在 init_hidden 方法中,我们初始化了两个 LSTM 层的隐藏状态。 接下来,我们可以使用该类来创建一个双层 LSTM 模型: ```python input_size = 10 hidden_size = 20 num_layers = 2 batch_size = 5 model = DoubleLSTM(input_size, hidden_size, num_layers) inputs = torch.randn(3, batch_size, input_size) hidden = model.init_hidden(batch_size) output, hidden = model(inputs, hidden) ``` 在上述代码中,我们首先定义了输入数据的维度(input_size)、隐藏状态的维度(hidden_size)、LSTM 层数(num_layers)和批大小(batch_size)。然后我们创建了一个 DoubleLSTM 实例,并使用 init_hidden 方法初始化了隐藏状态。接着我们传入输入数据和隐藏状态调用了 DoubleLSTM 的 forward 方法,并获取了输出和更新后的隐藏状态。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值