阶段3 | NLP传统 · 第15课/共30课

📖 第15课:主题分类

🎯 课程目标

主题分类将文本归入预定义的主题类别,与主题模型发现隐藏主题互补。本课学习监督分类和无监督主题发现。

📐 核心原理

主题分类 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股成交额创新高基金上涨', '综艺节目收视率游戏大作发售']

✅ 验证通过:代码实机运行结果如上

📝 练习

动手练习

  1. 调整LDA的主题数量,用perplexity指标选择最优K
  2. 对比NMF和LDA在相同数据上的主题质量
  3. 用主题模型的文档-主题分布作为特征,训练分类器
📂

🏆 成就解锁:主题猎手

掌握了主题分类与主题发现技术,能自动识别和归类文本主题。

🧪 扩展:主题模型的评估

主题连贯性(Topic Coherence)

衡量主题中词的语义相关度:

选择最优主题数K

  1. 用不同K训练LDA,计算perplexity和coherence
  2. perplexity越低越好,但可能过拟合
  3. coherence在某K值达到峰值后不再提升
  4. 选择coherence峰值对应的K

📚 参考文献

推荐阅读

在线资源

主题分类 - 关键概念速查

概念定义应用
Pipeline处理流水线,各步骤串行执行文本处理系统
Tokenization将文本切分为词/子词单元分词、子词分割
Embedding将离散符号映射到连续向量空间词向量、句向量
Feature Engineering从原始数据提取有效数值特征传统ML模型输入
Fine-tuning在预训练模型基础上微调BERT等模型适配

本课要点回顾

  1. 主题分类是NLP技术栈的重要组件
  2. 理解原理比调用API更重要——知道为什么比知道怎么做更有价值
  3. 代码验证是学习的好方法——动手跑一遍胜过读十遍
  4. 从简单方法开始,逐步过渡到复杂方法——简单方法的基线作用不可替代
  5. 实践出真知——用自己的数据跑一遍,发现课本上没写的问题

❓ 常见问题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传统MLpip install scikit-learn
nltk英文NLP工具pip install nltk
spaCy工业NLP管线pip install spacy
hanlp中文NLP工具包pip install hanlp
fasttextFacebook文本分类pip install fasttext
textblob简单NLP接口pip install textblob