📚 课程目录

第31课:文本分类

📖 本课概述

文本分类是NLP最基础的任务之一——情感分析、垃圾邮件检测、新闻分类都是文本分类。本课实现一个完整的文本分类pipeline。

📝 一、文本分类Pipeline

原始文本 → 分词 → 词嵌入 → 编码器 → 分类头 → 类别

📐 二、词嵌入

2.1 One-Hot的问题

维度=词表大小,稀疏,无法表示语义关系。

2.2 词嵌入 (Word Embedding)

将词映射到低维稠密向量

相似词 → 相似向量

King - Man + Woman ≈ Queen

2.3 TextCNN vs LSTM

模型优点缺点
TextCNN快,捕获局部n-gram特征忽略长距离依赖
LSTM建模序列依赖较慢
Transformer并行,全局注意力数据量少时容易过拟合

2.4 PyTorch实现文本分类


import torch
import torch.nn as nn

# 文本分类实现
print("=== 文本分类实战 ===")

# 模拟文本数据
vocab_size = 5000
embed_dim = 64
num_classes = 4
class_names = ['体育', '科技', '娱乐', '财经']

# 生成模拟数据
torch.manual_seed(42)
seq_len = 30
X_train = torch.randint(0, vocab_size, (500, seq_len))
y_train = torch.randint(0, num_classes, (500,))
X_test = torch.randint(0, vocab_size, (100, seq_len))
y_test = torch.randint(0, num_classes, (100,))

# TextCNN
class TextCNN(nn.Module):
    def __init__(self, vocab_size, embed_dim, num_classes, num_filters=100, filter_sizes=[3,4,5]):
        super().__init__()
        self.embedding = nn.Embedding(vocab_size, embed_dim)
        self.convs = nn.ModuleList([
            nn.Conv2d(1, num_filters, (fs, embed_dim)) for fs in filter_sizes
        ])
        self.fc = nn.Linear(num_filters * len(filter_sizes), num_classes)
        self.dropout = nn.Dropout(0.5)
    
    def forward(self, x):
        x = self.embedding(x).unsqueeze(1)  # B×1×L×D
        conv_outs = []
        for conv in self.convs:
            c = torch.relu(conv(x)).squeeze(3)  # B×F×(L-fs+1)
            c = torch.max(c, dim=2)[0]  # B×F
            conv_outs.append(c)
        x = torch.cat(conv_outs, dim=1)
        x = self.dropout(x)
        return self.fc(x)

# LSTM分类器
class LSTMClassifier(nn.Module):
    def __init__(self, vocab_size, embed_dim, hidden_dim, num_classes):
        super().__init__()
        self.embedding = 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, num_classes)
    
    def forward(self, x):
        x = self.embedding(x)
        _, (h, _) = self.lstm(x)
        h = torch.cat([h[-2], h[-1]], dim=1)  # 双向最后隐状态
        return self.fc(h)

# 对比训练
models = {
    "TextCNN": TextCNN(vocab_size, embed_dim, num_classes),
    "BiLSTM": LSTMClassifier(vocab_size, embed_dim, 64, num_classes),
}

for name, model in models.items():
    optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
    loss_fn = nn.CrossEntropyLoss()
    
    for epoch in range(50):
        optimizer.zero_grad()
        loss = loss_fn(model(X_train), y_train)
        loss.backward()
        optimizer.step()
    
    with torch.no_grad():
        train_acc = (model(X_train).argmax(1) == y_train).float().mean()
        test_acc = (model(X_test).argmax(1) == y_test).float().mean()
        params = sum(p.numel() for p in model.parameters())
    
    print(f"{name}: train_acc={train_acc:.2%}, test_acc={test_acc:.2%}, params={params:,}")

# 词嵌入可视化概念
print("\n=== 词嵌入关系 ===")
# 模拟预训练词向量
embedding = nn.Embedding(vocab_size, embed_dim)
word_pairs = [("国王", "女王"), ("男人", "女人"), ("中国", "北京")]
print("词向量类比: King - Man + Woman ≈ Queen")
print("v(国王) - v(男人) + v(女人) ≈ v(女王)")
print("这种语义关系是词嵌入的核心价值")
🟢 运行结果 ✅验证通过 === 文本分类实战 === TextCNN: train_acc=92.40%, test_acc=23.00%, params=398,304 BiLSTM: train_acc=96.60%, test_acc=21.00%, params=387,076 === 词嵌入关系 === 词向量类比: King - Man + Woman ≈ Queen v(国王) - v(男人) + v(女人) ≈ v(女王) 这种语义关系是词嵌入的核心价值

🔬 深入拓展

核心要点回顾

本课的核心知识点构成了实战项目学习的重要一环。让我们从更高维度审视这些知识之间的关系:

常见陷阱与最佳实践

⚠️ 初学者常犯的错误:

💡 最佳实践:

与前后课程的联系

深度学习是一个整体——每一课的知识都不是孤立的:

📖 延伸阅读

💡 继续深入的学习路径:

📝 练习

练习1:真实文本分类

用AG News或IMDB数据集训练文本分类器。

练习2:BERT微调

用预训练BERT做文本分类,对比TextCNN。

练习3:类别不平衡处理

实现Focal Loss和过采样,处理类别不平衡问题。

💡 文本分类技巧

分类优化

常见错误与解决方案

⚠️ 需要避免的典型错误:

  1. 不了解模型假设就盲目使用
  2. 没有建立基线就追求复杂方法
  3. 忽视数据质量和预处理
  4. 过度调参而不理解原理
  5. 只看训练指标忽略验证指标

性能优化建议

💡 提升模型性能的系统方法:

  1. 确保数据管道正确且高效
  2. 建立简单但正确的基线模型
  3. 分析基线的错误类型
  4. 针对性地改进(数据/模型/训练)
  5. 持续迭代,每步验证

🔬 深度拓展:从理论到实践

核心概念网络

理解本课内容需要将其置于更大的知识网络中。每个核心概念都不是孤立的,它们相互关联、相互支撑:

关键洞察与直觉

建立正确的直觉比记住公式更重要:

1. 维度直觉:高维空间中,数据分布与低维直觉截然不同(维度诅咒)

2. 信息瓶颈:神经网络逐层压缩信息,保留任务相关的、丢弃无关的

3. 流形假设:高维数据实际分布在低维流形上,学习即发现流形结构

4. 偏差-方差权衡:简单模型欠拟合(高偏差),复杂模型过拟合(高方差)

与其他课程的关联

本课作为实战项目阶段的核心内容,与前后课程紧密关联:

关联课程关联点协同效应
前序课程提供了本课的基础知识循序渐进的理解
后续课程本课内容是后续的基础逐步构建能力
平行课程同一阶段的互补知识多角度深入理解
实战项目综合运用所有知识理论与实践结合

面试常见问题

💡 准备面试时,确保能回答以下问题:

  1. 用简单语言解释本课核心概念
  2. 画出关键算法/结构的流程图
  3. 比较不同方法的优缺点
  4. 举出实际应用场景
  5. 讨论常见误解和注意事项

进阶学习路径

掌握本课内容后,可以通过以下方式继续深入:

📝

成就解锁:文本实战家

文本分类全流程——NLP的基础你已掌握!