您的位置:

深入探究PyTorch中torch.nn.lstm

一、LSTM模型介绍

LSTM(Long Short-Term Memory)是一种常用的循环神经网络模型,它具有较强的记忆功能和长短期依赖学习能力,常用于序列数据的建模。相较于传统的RNN,LSTM拥有三个门,分别为输入门、遗忘门、输出门,能够有效地控制信息的流动和遗忘。在PyTorch中,LSTM模型封装在torch.nn.lstm类中。

二、torch.nn.lstm参数解析

在实例化torch.nn.lstm类时,需要传递的参数如下:


torch.nn.LSTM(
    input_size: int, # 输入数据的特征维度,即输入数据的最后一维的大小
    hidden_size: int, # 隐藏层的特征维度
    num_layers: int = 1, # LSTM模型的层数,默认是1层,表示只有一个LSTM单元
    bias: bool = True, # 是否使用偏置,默认为True
    batch_first: bool = False, # 是否将batch_size放在输入数据的第一维,默认为False,即维度顺序为(seq_len, batch, input_size)
    dropout: float = 0., # 在LSTM网络中,对输出的dropout比例,默认为0,即不对输出进行dropout处理
    bidirectional: bool = False, # 是否使用双向LSTM,默认为False,即单向LSTM
) -> None

其中,最重要的参数为input_size和hidden_size。input_size表示输入数据的特征维度,即输入数据的最后一维的大小;hidden_size表示隐藏层的特征维度。

三、torch.nn.lstm输入数据格式

在使用torch.nn.lstm进行序列数据建模时,输入数据需要满足以下格式要求:

  1. 输入数据维度为(seq_len, batch, input_size),其中seq_len表示序列长度,batch表示批量大小,input_size表示每个时间步的特征维度。
  2. 如果使用batch_first=True,输入数据维度需调整为(batch, seq_len, input_size)。即将批量大小放在第一维。
  3. 如果输入数据的seq_len不足LSTM模型所要求的长度,可以使用torch.nn.utils.rnn.pad_sequence()函数进行填充,使得所有输入数据的seq_len一致。

四、torch.nn.lstm输出数据格式

LSTM模型的输出包含两个部分,一个是每个时间步的输出,另一个是每个时间步的隐藏状态和cell状态。

  1. 每个时间步的输出为(seq_len, batch, num_directions * hidden_size),其中num_directions表示LSTM模型是否为双向LSTM。
  2. 每个时间步的隐藏状态和cell状态为(num_layers * num_directions, batch, hidden_size),其中num_layers表示LSTM模型的层数。

五、torch.nn.lstm使用示例

1、基本使用方法

以下代码展示了如何使用torch.nn.lstm类创建一个单层单向LSTM模型,并对输入数据进行前向传播。


import torch

# 定义输入数据
input_data = torch.randn(10, 32, 128)

# 定义LSTM模型
lstm_model = torch.nn.LSTM(input_size=128, hidden_size=256)

# 对输入数据进行前向传播
output, (h_n, c_n) = lstm_model(input_data)

2、使用双向LSTM进行情感分析

以下代码展示了如何使用torch.nn.lstm类创建一个双向LSTM模型,并对情感分类数据进行训练和预测。


import torch
import torchtext
from torchtext.datasets import IMDB
from torchtext.data import get_tokenizer
from torchtext.vocab import Vocab
from torch.utils.data import DataLoader

# 加载情感分类数据集IMDB
train_data, test_data = IMDB(split=('train', 'test'))

# 构建词汇表
tokenizer = get_tokenizer('basic_english') # 使用basic_english分词器进行分词
counter = torchtext.vocab.Counter()
for data in train_data:
    counter.update(tokenizer(data.text))
vocab = Vocab(counter, min_freq=10)
vocab.set_default_index(vocab['
   '])

# 定义对输入文本进行预处理的函数
def text_transform(text):
    tokens = tokenizer(text)
    return [vocab[token] for token in tokens]

# 加载训练集和测试集,并对数据进行处理后,转化为数据加载器
train_data_processed = [(text_transform(data.text), data.label) for data in train_data]
test_data_processed = [(text_transform(data.text), data.label) for data in test_data]
train_data_loader = DataLoader(train_data_processed, batch_size=64, shuffle=True)
test_data_loader = DataLoader(test_data_processed, batch_size=64, shuffle=False)

# 定义双向LSTM模型
class BiLSTM(torch.nn.Module):
    def __init__(self, vocab_size, embedding_size, hidden_size, num_classes):
        super(BiLSTM, self).__init__()
        self.embedding = torch.nn.Embedding(num_embeddings=vocab_size, embedding_dim=embedding_size)
        self.lstm = torch.nn.LSTM(input_size=embedding_size, hidden_size=hidden_size, bidirectional=True)
        self.fc = torch.nn.Linear(in_features=hidden_size*2, out_features=num_classes)
        
    def forward(self, input_dict):
        embedding = self.embedding(input_dict['text']) # 对文本进行嵌入
        lstm_output, _ = self.lstm(embedding) # 对嵌入后的文本进行LSTM处理
        last_output = lstm_output[-1] # 取最后一个时间步的输出
        output = self.fc(last_output) # 进行分类输出
        return output

# 实例化模型,并对模型进行训练和测试
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = BiLSTM(vocab_size=len(vocab), embedding_size=128, hidden_size=256, num_classes=2).to(device)
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
criterion = torch.nn.CrossEntropyLoss()
for epoch in range(10):
    for input_dict in train_data_loader:
        input_dict = {key: value.to(device) for key, value in input_dict.items()}
        optimizer.zero_grad()
        output = model(input_dict)
        loss = criterion(output, input_dict['label'])
        loss.backward()
        optimizer.step()
    with torch.no_grad():
        total_correct = 0.
        for input_dict in test_data_loader:
            input_dict = {key: value.to(device) for key, value in input_dict.items()}
            output = model(input_dict)
            pred = output.argmax(dim=-1)
            total_correct += (pred == input_dict['label']).sum().item()
        accuracy = total_correct / len(test_data)
        print(f'Epoch {epoch}, test accuracy: {accuracy:.2%}')

   

六、总结

本文通过对PyTorch中的torch.nn.lstm类进行详细的解析,详细介绍了LSTM模型的特点、类的参数、输入数据格式、输出数据格式以及使用方法。并以一个双向LSTM情感分类模型的例子进行了实际应用,希望能够对使用PyTorch进行序列数据建模的读者有所帮助。