双向LSTM(Bidirectional LSTM) 是LSTM的一种改进型结构,能够同时利用序列数据的前向和后向信息。
双向性:BiLSTM 通过在输入序列的两个方向上进行处理,即前向和后向,使得模型能够同时捕捉到当前位置前后的上下文信息。这样,模型就能够更全面地理解整个句子的语境,从而更准确地预测下一个单词。

让我们用一个语句的例子来说明LSTM和BiLSTM的区别: 假设我们有以下句子: “我正在学习人工智能,因为它很有趣。”
LSTM会从左到右逐个处理单词,每次只考虑之前的上下文。例如:
LSTM只能利用单词左侧的上下文信息,无法利用右侧的上下文信息。因此,它可能无法完全理解句子的整体语义,尤其是当右侧的上下文对理解当前单词很重要时。
BiLSTM同时从左到右和从右到左处理单词,因此可以同时利用左侧和右侧的上下文信息。例如:
BiLSTM能够同时利用左侧和右侧的上下文信息,因此可以更全面地理解句子的整体语义。这种双向信息利用使得BiLSTM在处理需要上下文信息的任务时表现得更好,例如情感分析、命名实体识别等。
以下是使用PyTorch实现BiLSTM模型的一个简单例子,以"我 喜欢 学习 人工智能"这句话为例,以“学习”为中心词,推理"学习"后最可能出现的上下文词汇。
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import Dataset, DataLoader
import numpy as np
# 示例句子
sentence = "我 喜欢 学习 人工智能"
words = sentence.split()
# 构建词汇表
vocab = list(set(words))
word_to_idx = {word: idx for idx, word in enumerate(vocab)}
idx_to_word = {idx: word for idx, word in enumerate(vocab)}
vocab_size = len(vocab)
# 生成训练数据
train_data = []
context_window = 1
for i in range(context_window, len(words) - context_window):
center_word = word_to_idx[words[i]]
context_words = []
for j in range(i - context_window, i + context_window + 1):
if j != i:
context_words.append(word_to_idx[words[j]])
for context_word in context_words:
train_data.append((center_word, context_word))
# 定义BiLSTM模型
class BiLSTMModel(nn.Module):
def __init__(self, vocab_size, embed_dim, hidden_dim):
super(BiLSTMModel, self).__init__()
self.embeddings = nn.Embedding(vocab_size, embed_dim)
self.lstm = nn.LSTM(embed_dim, hidden_dim, batch_first=True, bidirectional=True)
self.fc = nn.Linear(hidden_dim * 2, vocab_size)
def forward(self, x):
embeds = self.embeddings(x)
lstm_out, _ = self.lstm(embeds)
output = self.fc(lstm_out)
return output
# 超参数
embed_dim = 10
hidden_dim = 10
num_epochs = 1000
learning_rate = 0.001
# 创建数据集和数据加载器
class WordDataset(Dataset):
def __init__(self, data):
self.data = data
def __len__(self):
return len(self.data)
def __getitem__(self, idx):
center_word, context_word = self.data[idx]
return torch.LongTensor([center_word]), torch.LongTensor([context_word])
dataset = WordDataset(train_data)
dataloader = DataLoader(dataset, batch_size=8, shuffle=True)
# 初始化模型、损失函数和优化器
model = BiLSTMModel(vocab_size, embed_dim, hidden_dim)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)
# 训练模型
for epoch in range(num_epochs):
total_loss = 0
for inputs, targets in dataloader:
outputs = model(inputs)
loss = criterion(outputs.squeeze(1), targets.squeeze(1))
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_loss += loss.item()
if (epoch + 1) % 10 == 0:
print(f'Epoch [{epoch + 1}/{num_epochs}], Loss: {total_loss / len(dataloader):.4f}')
# 预测函数
def predict(center_word, k=2):
model.eval()
with torch.no_grad():
input_word = torch.LongTensor([word_to_idx[center_word]])
output = model(input_word)
probabilities = torch.softmax(output, dim=1)
topk_probs, topk_indices = torch.topk(probabilities, k, dim=1)
predicted_words = [idx_to_word[idx.item()] for idx in topk_indices[0]]
return predicted_words, topk_probs[0].tolist()
# 验证结果(以“学习”为中心词进行预测)
print("\n模型预测结果:")
center_word = "学习"
predicted_words, probabilities = predict(center_word, k=2)
print(f"中心词: '{center_word}', 预测上下文词: {predicted_words} (概率: {probabilities})")
运行效果:
Epoch [10/1000], Loss: 1.3580
...
Epoch [1000/1000], Loss: 0.6942
模型预测结果:
中心词: '学习', 预测上下文词: ['喜欢', '人工智能'] (概率: [0.4995916187763214, 0.4993744194507599])