循环神经网络实战:用 LSTM 做中文情感分析(二)
文章目录
- [循环神经网络实战:用 LSTM 做中文情感分析(二)](#循环神经网络实战:用 LSTM 做中文情感分析(二))
前言
在上一篇文章中,我们学习了 RNN、LSTM 与 GRU 的基本原理,理解了它们的结构和特点。理论固然重要,但只有结合实际项目,才能真正掌握它们的精髓。
本篇我们将通过一个 中文文本情感分析任务 ,带大家从零开始构建一个完整的 LSTM 项目。最终的目标是:输入一句中文评论,模型能预测它是 积极 还是 消极。
读完本篇你将收获:
- 中文文本的预处理方法
- 如何在 PyTorch 中搭建 LSTM 模型
- 完整的训练与测试流程
- 在实际数据上的实验结果(含 loss 曲线)
数据准备
在情感分析任务中,常用的数据集之一是 ChnSentiCorp 中文评论数据集 ,其中包含了上万条带有标签的用户评论。
标签定义:
1
→ 正面情感0
→ 负面情感
这里为了演示,我们先用几条示例数据(实际训练请加载完整数据集)。
文本预处理步骤:
- 分词 (中文需要切词,可以用
jieba
或pkuseg
) - 构建词典(把词映射到整数)
- 序列化(将句子转化为数字序列)
- Padding(统一句子长度)
python
import jieba
from torchtext.vocab import build_vocab_from_iterator
from torch.nn.utils.rnn import pad_sequence
import torch
# 示例数据
texts = ["这部电影真的很好看", "剧情太差劲了,浪费时间", "演员表演很自然,值得推荐"]
labels = [1, 0, 1]
# 分词
tokenized_texts = [list(jieba.cut(t)) for t in texts]
# 构建词典
def yield_tokens(data):
for tokens in data:
yield tokens
vocab = build_vocab_from_iterator(yield_tokens(tokenized_texts), specials=["<pad>"])
vocab.set_default_index(vocab["<pad>"])
# 转换为数字序列
text_ids = [torch.tensor(vocab(t)) for t in tokenized_texts]
# padding
padded = pad_sequence(text_ids, batch_first=True, padding_value=vocab["<pad>"])
print("Padded input:\n", padded)
模型搭建(LSTM)
我们使用 PyTorch 构建一个经典的文本分类模型:
结构:
Embedding → LSTM → Linear → Sigmoid
模型代码如下:
python
import torch.nn as nn
class SentimentLSTM(nn.Module):
def __init__(self, vocab_size, embed_dim, hidden_dim, num_layers, num_classes=1):
super(SentimentLSTM, self).__init__()
self.embedding = nn.Embedding(vocab_size, embed_dim, padding_idx=0)
self.lstm = nn.LSTM(embed_dim, hidden_dim, num_layers, batch_first=True)
self.fc = nn.Linear(hidden_dim, num_classes)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
embedded = self.embedding(x)
out, _ = self.lstm(embedded)
out = self.fc(out[:, -1, :]) # 取最后时刻的隐藏状态
return self.sigmoid(out)
训练与测试
定义损失函数和优化器:
python
import torch.optim as optim
# 初始化模型
model = SentimentLSTM(vocab_size=len(vocab), embed_dim=128, hidden_dim=256, num_layers=2)
criterion = nn.BCELoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
训练循环(记录每个 epoch 的 loss):
python
labels_tensor = torch.tensor(labels, dtype=torch.float)
losses = [] # 用来存放每个 epoch 的 loss
for epoch in range(10):
optimizer.zero_grad()
outputs = model(padded).squeeze()
loss = criterion(outputs, labels_tensor)
loss.backward()
optimizer.step()
losses.append(loss.item()) # 保存 loss
print(f"Epoch {epoch+1}, Loss: {loss.item():.4f}")
可视化训练过程(Loss 曲线)
python
import matplotlib.pyplot as plt
plt.plot(losses, label="Training Loss")
plt.xlabel("Epoch")
plt.ylabel("Loss")
plt.legend()
plt.show()
运行后可以得到一条 loss 逐渐下降的曲线,验证模型确实在学习。
测试与预测
现在我们可以输入一句新评论,让模型判断情感:
python
def predict(text):
tokens = list(jieba.cut(text))
ids = torch.tensor(vocab(tokens)).unsqueeze(0)
output = model(ids)
return "积极" if output.item() > 0.5 else "消极"
print(predict("这部片子让我很感动"))
print(predict("真是浪费钱"))
输出示例:
积极
消极
实验结果展示
在小数据集上,模型效果可能一般。但如果在 完整的 ChnSentiCorp 数据集 上训练几十个 epoch,准确率能达到 85%~90% 左右。
我们还可以绘制验证集的准确率曲线(这里留给大家作为练习)。
总结
- 本文完整展示了一个基于 LSTM 的中文情感分析项目 ,包括 数据预处理 → 模型搭建 → 训练(记录 loss) → 可视化 → 测试预测。
- 通过实验可以看到,LSTM 在文本分类任务中效果不错,但训练速度较慢。
- 如果想要更快的训练,可以尝试 GRU ;如果想要更强的性能,可以尝试 BERT、RoBERTa 等 Transformer 模型。