长短期记忆(LSTM)

37 篇文章 1 订阅
27 篇文章 1 订阅

一、历史

长短期记忆(LSTM)是一种特殊的循环神经网络(RNN),由Sepp Hochreiter和Jürgen Schmidhuber于1997年首次提出。该模型的目的是解决传统RNN在长序列训练中的梯度消失和梯度爆炸问题。LSTM通过引入门控机制,使得模型能够自主地选择哪些信息需要保留和哪些信息需要遗忘,从而更好地捕捉序列中的长期依赖关系。

二、优点

LSTM相对于传统的RNN有以下优点:

  1. 解决了梯度消失和梯度爆炸问题,可以处理长序列数据;
  2. 引入门控机制,能够自主选择哪些信息需要保留和哪些信息需要遗忘;
  3. 可以处理多层结构,提高了模型的表达能力。

三、与其他方法的不同之处

相对于其他的序列模型,LSTM的不同之处在于其引入了三个门控单元:输入门、遗忘门和输出门。这些门控单元可以自主地选择哪些信息需要保留和哪些信息需要遗忘,从而更好地捕捉序列中的长期依赖关系。除此之外,LSTM还引入了一个细胞状态,用来存储和传递信息。

四、LSTM的结构

LSTM的结构可以用下面的Mermaid代码表示:

输入
输入门
细胞状态
遗忘门
细胞状态
更新
细胞状态
输出门
输出

其中,输入门、遗忘门和输出门的计算公式如下:

i t = σ ( W x i x t + W h i h t − 1 + b i ) i_t = \sigma(W_{xi}x_t + W_{hi}h_{t-1} + b_i) it=σ(Wxixt+Whiht1+bi)

f t = σ ( W x f x t + W h f h t − 1 + b f ) f_t = \sigma(W_{xf}x_t + W_{hf}h_{t-1} + b_f) ft=σ(Wxfxt+Whfht1+bf)

o t = σ ( W x o x t + W h o h t − 1 + b o ) o_t = \sigma(W_{xo}x_t + W_{ho}h_{t-1} + b_o) ot=σ(Wxoxt+Whoht1+bo)

其中, x t x_t xt表示输入序列的第 t t t个元素, h t − 1 h_{t-1} ht1表示上一个时刻的隐状态, W x i W_{xi} Wxi W h i W_{hi} Whi b i b_i bi分别是输入门的权重矩阵、隐状态的权重矩阵和偏置向量, W x f W_{xf} Wxf W h f W_{hf} Whf b f b_f bf分别是遗忘门的权重矩阵、隐状态的权重矩阵和偏置向量, W x o W_{xo} Wxo W h o W_{ho} Who b o b_o bo分别是输出门的权重矩阵、隐状态的权重矩阵和偏置向量, σ \sigma σ表示sigmoid函数。

细胞状态的计算公式如下:

c t = f t c t − 1 + i t tanh ( W x c x t + W h c h t − 1 + b c ) c_t = f_tc_{t-1} + i_t\text{tanh}(W_{xc}x_t + W_{hc}h_{t-1} + b_c) ct=ftct1+ittanh(Wxcxt+Whcht1+bc)

其中, c t − 1 c_{t-1} ct1表示上一个时刻的细胞状态, W x c W_{xc} Wxc W h c W_{hc} Whc b c b_c bc分别是细胞状态的权重矩阵、隐状态的权重矩阵和偏置向量, tanh \text{tanh} tanh表示双曲正切函数。

更新的计算公式如下:

f t = σ ( W x f x t + W h f h t − 1 + b f ) f_t = \sigma(W_{xf}x_t + W_{hf}h_{t-1} + b_f) ft=σ(Wxfxt+Whfht1+bf)

i t = σ ( W x i x t + W h i h t − 1 + b i ) i_t = \sigma(W_{xi}x_t + W_{hi}h_{t-1} + b_i) it=σ(Wxixt+Whiht1+bi)

c ~ t = tanh ( W x c x t + W h c h t − 1 + b c ) \tilde{c}_t = \text{tanh}(W_{xc}x_t + W_{hc}h_{t-1} + b_c) c~t=tanh(Wxcxt+Whcht1+bc)

其中, c ~ t \tilde{c}_t c~t表示当前时刻的候选细胞状态。

最终输出的计算公式如下:

h t = o t tanh ( c t ) h_t = o_t\text{tanh}(c_t) ht=ottanh(ct)

其中, h t h_t ht表示当前时刻的输出, tanh \text{tanh} tanh表示双曲正切函数。

五、LSTM的实现

下面我们用PyTorch实现一个简单的LSTM模型,以MNIST手写数字识别任务为例。

首先,我们需要导入相关的库:

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms

然后,我们定义一个LSTM模型:

class LSTM(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers, num_classes):
        super(LSTM, 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)
        self.fc = nn.Linear(hidden_size, num_classes)

    def forward(self, x):
        h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(device)
        c0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(device)

        out, _ = self.lstm(x, (h0, c0))
        out = self.fc(out[:, -1, :])
        return out

其中,input_size表示输入序列的特征维度,hidden_size表示LSTM的隐藏状态维度,num_layers表示LSTM的层数,num_classes表示分类的类别数。在__init__函数中,我们定义了一个LSTM层和一个全连接层,其中LSTM层的参数由输入的input_sizehidden_sizenum_layers决定。在forward函数中,我们将输入数据x传入LSTM层,得到最后一个时刻的输出,然后通过全连接层进行分类。

接着,我们定义一些超参数:

input_size = 28
sequence_length = 28
hidden_size = 128
num_layers = 2
num_classes = 10
batch_size = 100
num_epochs = 5
learning_rate = 0.001

其中,input_sizesequence_length分别为输入序列的特征维度和长度,hidden_size为LSTM的隐藏状态维度,num_layers为LSTM的层数,num_classes为分类的类别数,batch_size为每个batch的大小,num_epochs为训练的轮数,learning_rate为学习率。

接着,我们加载MNIST数据集:

train_dataset = datasets.MNIST(root='./data', train=True, transform=transforms.ToTensor(), download=True)
test_dataset = datasets.MNIST(root='./data', train=False, transform=transforms.ToTensor(), download=True)

train_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)
test_loader = torch.utils.data.DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False)

然后,我们定义一个设备变量,用来将模型和数据移到GPU上(如果有的话):

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

接着,我们实例化一个LSTM模型,并将其移动到设备上:

model = LSTM(input_size, hidden_size, num_layers, num_classes).to(device)

然后,我们定义一个损失函数和一个优化器:

criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)

接着,我们训练模型:

total_step = len(train_loader)
for epoch in range(num_epochs):
    for i, (images, labels) in enumerate(train_loader):
        images = images.reshape(-1, sequence_length, input_size).to(device)
        labels = labels.to(device)

        outputs = model(images)
        loss = criterion(outputs, labels)

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        if (i + 1) % 100 == 0:
            print('Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}'.format(epoch + 1, num_epochs, i + 1, total_step, loss.item()))

其中,我们将每个图像reshape成一个28x28的序列,并将其移动到设备上。然后,我们将序列传入LSTM模型,得到最后一个时刻的输出,并计算损失函数。接着,我们清空梯度、进行反向传播和更新参数。最后,我们每100个batch打印一次损失函数。

最后,我们测试模型的性能:

with torch.no_grad():
    correct = 0
    total = 0
    for images, labels in test_loader:
        images = images.reshape(-1, sequence_length, input_size).to(device)
        labels = labels.to(device)
        outputs = model(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()

    print('Test Accuracy of the model on the 10000 test images: {} %'.format(100 * correct / total))

六、总结

LSTM是一种特殊的循环神经网络,通过引入门控机制,使得模型能够自主地选择哪些信息需要保留和哪些信息需要遗忘,从而更好地捕捉序列中的长期依赖关系。相对于传统的RNN,LSTM具有更好的表达能力和更好的序列建模能力。在实际应用中,LSTM被广泛应用于语音识别、机器翻译、自然语言处理等领域。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值