PyTorch实战:三种神经网络模型对决IMDB电影评论情感分类,LSTM以88.76%准确率夺冠
本文使用PyTorch实现IMDB电影评论情感分析二分类任务,比较了LSTM、CNN和Transformer三种神经网络模型。介绍了数据加载、构建词表、Dataset类和批处理填充的完整流程。实验结果表明,双向LSTM表现最佳,10个epoch时测试准确率达88.93%;CNN训练速度快且不易过拟合,5个epoch达86.68%准确率;Transformer因数据集规模有限表现中等。使用GloVe预训练词向量可提升LSTM性能至88.76%。文章还提供了模型代码实现、训练流程和优化建议,完整代码可在GPU环境下10-20分钟完成训练。
情感分析是自然语言处理中的经典任务,IMDB电影评论数据集包含25000条训练数据和25000条测试数据,每条评论被标记为正面(1)或负面(0)。本文将使用PyTorch实现三种不同的神经网络模型来完成这个二分类任务。
数据集处理
1. 数据加载与预处理
我们使用torchtext库提供的IMDB数据集:
from torchtext import datasets
from torchtext.data import get_tokenizer
from torchtext.vocab import build_vocab_from_iterator
train_pipe, test_pipe = datasets.IMDB()
tokenizer = get_tokenizer('basic_english')
2. 构建词表
vocab = build_vocab_from_iterator(
[tokenizer(text) for label, text in train_pipe],
min_freq=2,
specials=["<unk>", "<pad>"],
special_first=True
)
vocab.set_default_index(vocab["<unk>"])
padding_idx = vocab['<pad>']
3. 创建Dataset类
class IMDBDataset(Dataset):
def __init__(self, pipe):
self.texts = []
self.labels = []
for label, text in pipe:
self.texts.append(text)
self.labels.append(label)
def __len__(self):
return len(self.texts)
def __getitem__(self, index):
text = self.texts[index]
label = self.labels[index] - 1 # 将标签转换为0/1
tokens = [vocab[token] for token in tokenizer(text)]
return torch.tensor(tokens, dtype=torch.long), torch.tensor(label, dtype=torch.long)
4. 批处理与填充
max_sequence = 400
def collate_fn(batch):
texts, labels = zip(*batch)
texts = pad_sequence(texts, batch_first=True, padding_value=padding_idx)
return texts[:, :max_sequence], torch.tensor(labels)
train_loader = DataLoader(train_dataset, batch_size=50, shuffle=True, collate_fn=collate_fn)
test_loader = DataLoader(test_dataset, batch_size=50, shuffle=True, collate_fn=collate_fn)
模型实现
1. LSTM模型
双向LSTM能够捕捉上下文信息,适合处理序列数据:
class RNNModel(nn.Module):
def __init__(self):
super().__init__()
self.embedding = nn.Embedding(
num_embeddings=vocab_len,
embedding_dim=100,
padding_idx=padding_idx
)
self.rnn = nn.LSTM(
input_size=100,
hidden_size=256,
num_layers=2,
batch_first=True,
dropout=0.5,
bidirectional=True
)
self.dropout = nn.Dropout()
self.fc = nn.Linear(256 * 2, 2)
def forward(self, x):
out = self.embedding(x)
out = self.dropout(out)
_, (hidden, _) = self.rnn(out)
out = torch.concat((hidden[-1], hidden[-2]), dim=1)
out = self.dropout(out)
return self.fc(out)
2. CNN模型
卷积神经网络通过多个卷积核提取局部特征:
class CNNModel(nn.Module):
def __init__(self):
super().__init__()
self.embedding = nn.Embedding(vocab_len, 100, padding_idx=padding_idx)
self.cnn1 = nn.Sequential(
nn.Conv1d(in_channels=100, out_channels=128, kernel_size=3, stride=1, padding=1),
nn.ReLU(),
nn.MaxPool1d(kernel_size=2, stride=2)
)
self.cnn2 = nn.Sequential(
nn.Conv1d(in_channels=128, out_channels=256, kernel_size=3, stride=1, padding=1),
nn.ReLU(),
nn.MaxPool1d(kernel_size=2, stride=2)
)
self.flatten = nn.Flatten()
self.dropout = nn.Dropout(0.5)
self.fc = nn.Linear(256 * 100, 2)
def forward(self, x):
out = self.embedding(x)
out = out.permute(0, 2, 1) # 转换维度以适应Conv1d
out = self.cnn1(out)
out = self.cnn2(out)
out = self.dropout(out)
out = self.flatten(out)
return self.fc(out)
3. Transformer模型
使用自注意力机制捕获长距离依赖:
class TransformerModel(nn.Module):
def __init__(self):
super().__init__()
self.embedding = nn.Embedding(
num_embeddings=vocab_len,
embedding_dim=96,
padding_idx=padding_idx,
)
self.positional_encoding = nn.Parameter(torch.zeros(1, max_sequence, 96))
self.transformer = nn.Transformer(
d_model=96,
nhead=8,
num_encoder_layers=2,
num_decoder_layers=2,
dim_feedforward=256,
dropout=0.5,
batch_first=True,
)
self.fc = nn.Linear(96, 2)
def forward(self, x):
seq_length = x.size(1)
x = self.embedding(x) + self.positional_encoding[:, :seq_length, :]
output = self.transformer(x, x)
output = output.mean(dim=1)
return self.fc(output)
训练流程
统一的训练循环:
model = RNNModel().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
for epoch in range(num_epochs):
for i, (texts, labels) in enumerate(train_loader):
texts = texts.to(device)
labels = labels.to(device)
output = model(texts)
loss = criterion(output, labels)
optimizer.zero_grad()
loss.backward()
optimizer.step()
使用预训练词向量
使用GloVe预训练词向量可以提升模型性能:
from torchtext.vocab import GloVe
vocab = GloVe(name="6B", dim=100)
# 在Dataset中使用
tokens = [vocab.stoi[token] if token in vocab.stoi else 0 for token in tokenizer(text)]
实验结果对比
| 方法 | 轮数 | 训练数据准确度 | GloVe预训练准确度 |
|---|---|---|---|
| LSTM | 5 | 85.58% | 77.55% |
| LSTM | 10 | 88.93% | 88.76% |
| LSTM | 15 | 89.08% | 88.52% |
| LSTM | 20 | 88.81% | 88.14% |
| CNN | 5 | 86.68% | 86.26% |
| CNN | 10 | 85.62% | 86.10% |
| CNN | 15 | 85.82% | 85.51% |
| CNN | 20 | 86.44% | 85.82% |
| Transformer | 5 | 86.32% | - |
| Transformer | 10 | 84.52% | - |
结果分析
LSTM表现最佳:在10个epoch时达到88.76%的测试准确率,说明双向LSTM能有效捕捉文本的上下文信息。
CNN性能稳定:CNN在5个epoch时达到峰值86.68%,训练速度快且不易过拟合。
Transformer表现中等:由于数据集规模有限,Transformer的优势未能充分发挥。
GloVe的影响:对于LSTM,GloVe预训练词向量在10个epoch时达到与训练词表相近的效果(88.76% vs 88.93%)。
总结
本文使用PyTorch实现了IMDB电影评论情感分类任务,对比了LSTM、CNN和Transformer三种模型的效果。实验表明,LSTM在该任务上表现最佳,准确率可达88.76%。完整代码可在GPU环境下运行,约需10-20分钟完成训练。
如需进一步提升性能,可以尝试:
- 调整超参数(学习率、批次大小、隐藏层维度)
- 使用更深的网络结构
- 集成多个模型
- 数据增强技术
最后更新于1小时前
本文由人工编写,AI优化,转载请注明原文地址: PyTorch实战:三种神经网络模型对决IMDB电影评论情感分类,LSTM以88.76%准确率夺冠
推荐阅读
从非交互到交互式备案,手把手教你一周内搞定公安安全评估,轻松解锁网站互动功能
2812026-04-11
CodeBuddyIDE与Trae终极对决:谁是最强国产AI编程IDE?最新版本深度横评
28712025-09-25
Windows系统PyTorch安装教程:CUDA 12.1环境配置与TorchText版本兼容性指南
30752024-06-21
GeoServer适配达梦数据库完整教程:从账号创建到图层发布
1722026-04-14
OpenVPN安装配置完整指南:从零搭建安全VPN服务器与客户端
29712024-06-21
XWiki只允许本机访问:Jetty绑定127.0.0.1配置方法
1642026-04-28