阶段3
|
NLP传统 · 第15课/共30课
📖 第15课:主题分类
🎯 课程目标
主题分类将文本归入预定义的主题类别,与主题模型发现隐藏主题互补。本课学习监督分类和无监督主题发现。
- 构建多类文本分类器
- 理解NMF和LDA主题模型
- 掌握主题解释与评估
📐 核心原理
主题分类 vs 主题模型
- 主题分类(监督):已知类别标签,训练分类器预测新文本类别
- 主题模型(无监督):发现文本中的隐藏主题结构,无需标签
💡 LDA假设每篇文档是多个主题的混合,每个主题是词的概率分布。它从词频共现模式中自动发现主题。
🔬 监督式主题分类
TF-IDF + 逻辑回归
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
import numpy as np
# 模拟新闻主题数据
texts = [
"股市今日大涨,沪指突破3500点", "央行宣布降息,市场反应积极", "A股成交额创历史新高",
"基金净值大幅上涨", "券商研报看好后市", "银行理财产品收益率下降",
"科技公司发布新款智能手机", "人工智能芯片取得突破性进展", "5G网络覆盖率达到80%",
"国产操作系统正式发布", "量子计算研究取得重大成果", "芯片制造工艺突破3纳米",
"中国女排3比0横扫对手", "梅西获得年度最佳球员", "NBA总决赛精彩对决",
"世界杯预选赛战况激烈", "马拉松比赛刷新赛会纪录", "奥运冠军宣布退役",
"新电影票房突破20亿", "音乐节吸引十万观众", "网红直播带货再创新高",
"综艺节目收视率领先", "游戏大作全球发售", "明星演唱会一票难求",
]
labels = (['财经'] * 6 + ['科技'] * 6 + ['体育'] * 6 + ['娱乐'] * 6)
vectorizer = TfidfVectorizer(token_pattern=r'(?u)\b\w+\b', max_features=200)
X = vectorizer.fit_transform(texts)
y = np.array(labels)
clf = LogisticRegression(max_iter=1000, random_state=42, multi_class='multinomial')
scores = cross_val_score(clf, X, y, cv=4, scoring='accuracy')
print("=== 主题分类(TF-IDF + 逻辑回归) ===")
print(f"交叉验证准确率: {scores.mean():.4f} (±{scores.std():.4f})")
clf.fit(X, y)
test_texts = ["比特币价格再创新高", "自动驾驶技术取得进展", "中国乒乓球再夺金牌", "综艺节目收视率第一"]
test_X = vectorizer.transform(test_texts)
preds = clf.predict(test_X)
probs = clf.predict_proba(test_X)
for text, pred, prob in zip(test_texts, preds, probs):
idx = list(clf.classes_).index(pred)
print(f" '{text}' → {pred} (置信度: {prob[idx]:.3f})")
[STDERR] Traceback (most recent call last):
File "<string>", line 24, in <module>
TypeError: LogisticRegression.__init__() got an unexpected keyword argument 'multi_class'
⚠️ 部分验证:代码实机运行结果如上
🔧 无监督主题发现
NMF与LDA主题模型
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.decomposition import NMF, LatentDirichletAllocation
import numpy as np
texts = [
"股市大涨央行降息市场积极", "A股成交额创新高基金上涨",
"科技公司发布新手机AI芯片突破", "5G网络覆盖量子计算成果",
"女排横扫对手梅西最佳球员", "NBA总决赛世界杯预选赛",
"电影票房突破网红直播带货", "综艺节目收视率游戏大作发售",
"银行利率下调理财产品收益", "券商研报看好后市投资",
"国产芯片3纳米工艺突破", "自动驾驶激光雷达传感器",
"马拉松纪录奥运冠军退役", "足球联赛积分榜排名",
"明星演唱会音乐节观众", "短视频平台用户增长数据",
]
# NMF主题模型
vectorizer = TfidfVectorizer(token_pattern=r'(?u)\b\w+\b', max_features=100)
X = vectorizer.fit_transform(texts)
feature_names = vectorizer.get_feature_names_out()
print("=== NMF主题模型 ===")
nmf = NMF(n_components=4, random_state=42, max_iter=500)
W = nmf.fit_transform(X)
H = nmf.components_
for topic_idx, topic in enumerate(H):
top_words = [feature_names[i] for i in topic.argsort()[-5:][::-1]]
print(f" 主题{topic_idx+1}: {top_words}")
print("\n=== LDA主题模型 ===")
lda = LatentDirichletAllocation(n_components=4, random_state=42, max_iter=50)
lda.fit(X)
for topic_idx, topic in enumerate(lda.components_):
top_words = [feature_names[i] for i in topic.argsort()[-5:][::-1]]
print(f" 主题{topic_idx+1}: {top_words}")
=== NMF主题模型 ===
主题1: ['nba总决赛世界杯预选赛', '电影票房突破网红直播带货', '女排横扫对手梅西最佳球员', '5g网络覆盖量子计算成果', '短视频平台用户增长数据']
主题2: ['银行利率下调理财产品收益', '券商研报看好后市投资', '综艺节目收视率游戏大作发售', '5g网络覆盖量子计算成果', '自动驾驶激光雷达传感器']
主题3: ['马拉松纪录奥运冠军退役', '股市大涨央行降息市场积极', '自动驾驶激光雷达传感器', '综艺节目收视率游戏大作发售', '科技公司发布新手机ai芯片突破']
主题4: ['a股成交额创新高基金上涨', '足球联赛积分榜排名', '明星演唱会音乐节观众', '国产芯片3纳米工艺突破', '科技公司发布新手机ai芯片突破']
=== LDA主题模型 ===
主题1: ['国产芯片3纳米工艺突破', '股市大涨央行降息市场积极', '女排横扫对手梅西最佳球员', '自动驾驶激光雷达传感器', '5g网络覆盖量子计算成果']
主题2: ['短视频平台用户增长数据', '银行利率下调理财产品收益', '5g网络覆盖量子计算成果', '自动驾驶激光雷达传感器', '综艺节目收视率游戏大作发售']
主题3: ['nba总决赛世界杯预选赛', '券商研报看好后市投资', '科技公司发布新手机ai芯片突破', '足球联赛积分榜排名', '综艺节目收视率游戏大作发售']
主题4: ['马拉松纪录奥运冠军退役', '电影票房突破网红直播带货', '明星演唱会音乐节观众', 'a股成交额创新高基金上涨', '综艺节目收视率游戏大作发售']
✅ 验证通过:代码实机运行结果如上
📝 练习
动手练习
- 调整LDA的主题数量,用perplexity指标选择最优K
- 对比NMF和LDA在相同数据上的主题质量
- 用主题模型的文档-主题分布作为特征,训练分类器
📂
🏆 成就解锁:主题猎手
掌握了主题分类与主题发现技术,能自动识别和归类文本主题。
🧪 扩展:主题模型的评估
主题连贯性(Topic Coherence)
衡量主题中词的语义相关度:
- UMass:基于文档共现的连贯性,有监督
- UMass越大越好,通常>0.2认为主题有意义
- 人工评估:展示主题top词,让人判断是否连贯
选择最优主题数K
- 用不同K训练LDA,计算perplexity和coherence
- perplexity越低越好,但可能过拟合
- coherence在某K值达到峰值后不再提升
- 选择coherence峰值对应的K
📚 参考文献
推荐阅读
- Jurafsky & Martin. Speech and Language Processing (3rd ed). 第15课相关章节
- Manning, Raghavan & Schutze. Introduction to Information Retrieval
- Goodfellow, Bengio & Courville. Deep Learning. 自然语言处理章节
在线资源
- NLTK文档: https://www.nltk.org/
- spaCy文档: https://spacy.io/
- gensim文档: https://radimrehurek.com/gensim/
- sklearn文本处理: https://scikit-learn.org/stable/modules/feature_extraction.html
主题分类 - 关键概念速查
| 概念 | 定义 | 应用 |
| Pipeline | 处理流水线,各步骤串行执行 | 文本处理系统 |
| Tokenization | 将文本切分为词/子词单元 | 分词、子词分割 |
| Embedding | 将离散符号映射到连续向量空间 | 词向量、句向量 |
| Feature Engineering | 从原始数据提取有效数值特征 | 传统ML模型输入 |
| Fine-tuning | 在预训练模型基础上微调 | BERT等模型适配 |
本课要点回顾
- 主题分类是NLP技术栈的重要组件
- 理解原理比调用API更重要——知道为什么比知道怎么做更有价值
- 代码验证是学习的好方法——动手跑一遍胜过读十遍
- 从简单方法开始,逐步过渡到复杂方法——简单方法的基线作用不可替代
- 实践出真知——用自己的数据跑一遍,发现课本上没写的问题
❓ 常见问题FAQ
- Q: 这个方法的数据需求量是多少?
- A: 传统方法通常需要几百到几千条标注数据。深度学习方法通常需要万级以上。数据量少时优先用传统方法。
- Q: 如何处理中文的特殊情况?
- A: 中文没有天然词边界,分词质量直接影响下游效果。建议:1)使用领域词典优化分词 2)比较不同分词工具的效果 3)对关键任务做分词错误分析。
- Q: 传统方法和深度学习如何选择?
- A: 考虑三个因素:1)数据量——少数据用传统方法 2)可解释性——需要解释选传统方法 3)计算资源——资源受限选传统方法。深度学习在大数据+强算力场景下优势明显。
- Q: 如何评估和调优?
- A: 1)建立基线:用最简单方法确定性能下限 2)错误分析:找出模型最常犯的错误类型 3)针对性改进:根据错误模式选择改进策略 4)避免过拟合:在独立测试集上验证。
- Q: 生产环境部署要注意什么?
- A: 1)延迟要求:简单模型推理更快 2)吞吐量:批处理提升吞吐 3)模型版本:做好版本管理和回滚 4)监控:持续跟踪线上模型性能 5)A/B测试:新模型上线前小流量验证。
🛠️ 实用工具箱
| 工具 | 用途 | 安装 |
| jieba | 中文分词 | pip install jieba |
| gensim | 词向量训练 | pip install gensim |
| scikit-learn | 传统ML | pip install scikit-learn |
| nltk | 英文NLP工具 | pip install nltk |
| spaCy | 工业NLP管线 | pip install spacy |
| hanlp | 中文NLP工具包 | pip install hanlp |
| fasttext | Facebook文本分类 | pip install fasttext |
| textblob | 简单NLP接口 | pip install textblob |