正在加载中...

展开本页目录
算法教程NMF_Topic-NMF 主题模型

NMF_Topic-NMF 主题模型

No.066 · 在线教程

NMFTopic-NMF 主题模型 的真实实现位于 core/nmfrunner.py 与 core/textprep.py。该模块的核心不是概率主题模型,而是:

NMF_Topic-NMF 主题模型

1. 方法概述

NMF_Topic-NMF 主题模型 的真实实现位于 core/nmf_runner.pycore/text_prep.py。该模块的核心不是概率主题模型,而是:

  1. 读取文本列并做规范化;
  2. TfidfVectorizerCountVectorizer 构造非负文档-词项矩阵;
  3. 调用 sklearn.decomposition.NMFMiniBatchNMF 分解矩阵;
  4. 输出主题 Top 词、文档主题权重和每个主题的 Top 文档。

设语料为

$$ \mathcal{D}=\{d_i\}_{i=1}^{N} \tag{1} $$

向量化后得到非负矩阵 \(X\in\mathbb{R}_{\ge 0}^{N\times V}\),其中 \(V\) 为词表大小。NMF 的目标是寻找两个非负矩阵

$$ X \approx W H \tag{2} $$

其中:

  • \(W\in\mathbb{R}_{\ge 0}^{N\times K}\) 为文档-主题矩阵;
  • \(H\in\mathbb{R}_{\ge 0}^{K\times V}\) 为主题-词矩阵;
  • \(K=\text{n\_topics}\) 为主题数。

2. 文本清洗与向量化

2.1 文本规范化

load_text_dataset() 会先读取用户选择的文本列 text_col,再对每条文本执行 _normalize_text()。其处理逻辑包括:

  • 可选转小写 lowercase
  • 可选去标点 strip_punct
  • 保留中文、字母、数字和空白
  • 删除空文本

记规范化函数为 \(\mathrm{Norm}(\cdot)\),则

$$ \tilde{d}_i=\mathrm{Norm}(d_i) \tag{3} $$

如果用户没有提供 id_col,代码会自动生成连续文档 ID:

$$ \mathrm{doc\_id}_i=i,\qquad i=1,2,\dots,N \tag{4} $$

2.2 向量化方式

模块支持两类文本表示:

  • vectorizer="tfidf"
  • vectorizer="count"

若使用词频表示,则

$$ X_{iv}=c(v,\tilde{d}_i) \tag{5} $$

若使用 TF-IDF,则可写为

$$ X_{iv}=\mathrm{tf}_{iv}\cdot \log\frac{N}{\mathrm{df}_v} \tag{6} $$

其中 \(\mathrm{df}_v\) 为包含词项 \(v\) 的文档数。

2.3 analyzer 的真实逻辑

VectorizerConfiganalyzer 支持 auto / word / char。其中 auto 不是占位参数,而是真有启发式逻辑:若文本中含中日韩字符的文档比例达到 30% 及以上,则自动切到字符级分析;否则使用词级分析。可写为

$$ \mathrm{analyzer}= \begin{cases} \text{char}, & \frac{\#\{\text{含 CJK 文档}\}}{N}\ge 0.3 \\ \text{word}, & \text{otherwise} \end{cases} \tag{7} $$

此外,词表参数还包括:

  • ngram_min
  • ngram_max
  • max_features
  • min_df
  • max_df
  • stop_words_mode
  • stop_words_custom

stop_words_mode="custom" 时,会把文本框里的内容按换行、逗号或空白分割成自定义停用词表。

3. NMF 模型与实际优化目标

3.1 标准 NMF

nmf_type="nmf" 时,代码调用 sklearn.decomposition.NMF。若 beta_loss="frobenius",其目标可以理解为最小化重构误差

$$ \min_{W\ge 0,H\ge 0}\; \frac{1}{2}\lVert X-WH\rVert_F^2 \tag{8} $$

beta_loss="kullback-leibler",则对应 KL 散度型目标

$$ \min_{W\ge 0,H\ge 0}\; D_{\mathrm{KL}}(X\Vert WH) \tag{9} $$

其中 \(D_{\mathrm{KL}}\) 表示广义 KL 散度。

3.2 solver 与 beta_loss 的兼容处理

代码里有一个明确的兼容性逻辑:当 beta_loss 不是 frobenius,而用户又没有选择 mu 求解器时,程序会自动把 solver 改成 mu,并写入 compatibility_note。这个逻辑可以记为

$$ \text{if } \beta \neq \text{frobenius},\quad \text{solver}\leftarrow \text{mu} \tag{10} $$

这不是文档建议,而是 run_nmf_topic() 中真实存在的代码分支。

3.3 MiniBatchNMF

nmf_type="minibatch" 时,模块改用 MiniBatchNMF。这一分支仍然是求 \(X\approx WH\),只是把迭代方式改为小批量更新,并额外使用 batch_size 参数控制每次更新的样本块大小。

3.4 W 与 H 的含义

模型训练后,代码执行

$$ W=\mathrm{fit\_transform}(X),\qquad H=\mathrm{components} \tag{11} $$

其中 \(W_{ik}\) 表示文档 \(i\) 在主题 \(k\) 上的权重,\(H_{kv}\) 表示主题 \(k\) 对词项 \(v\) 的权重。

需要注意:这里的 \(W\) 和 \(H\) 都不是概率分布,代码也没有做行归一化。因此 Doc_Topic 表中的值是非负权重,不是像 LDA 那样严格求和为 1 的主题概率。

4. 主题词、主主题与 Top 文档

4.1 主题 Top 词

_top_words_df() 会对每个主题的 \(H_k\) 按权重降序排序,取前 top_words 个词:

$$ \mathrm{TopWords}(k)=\operatorname{argsort}_v(H_{kv}) \tag{12} $$

导出的 Topics_TopWords 表包含:

  • topic
  • rank
  • word
  • weight

4.2 文档主主题

_doc_topic_df() 会把 \(W\) 展成 topic_0, topic_1, ... 列,并额外计算每篇文档的主主题:

$$ \mathrm{top\_topic}_i=\arg\max_k W_{ik} \tag{13} $$

$$ \mathrm{top\_topic\_weight}_i=\max_k W_{ik} \tag{14} $$

这正是 Doc_Topic 工作表中的 top_topictop_topic_weight 两列来源。

4.3 每个主题的 Top 文档

_topic_top_docs_df() 会对每个主题 \(k\) 按文档权重 \(W_{ik}\) 排序,取前 top_docs 个文档:

$$ \mathrm{TopDocs}(k)=\operatorname{argsort}_i(W_{ik}) \tag{15} $$

同时保存:

  • doc_id
  • weight
  • text_snippet

其中 text_snippet 只截取前 200 个字符,超出部分加省略号。

5. 评价指标、图表与输出结果

5.1 评价指标

当前实现没有分类指标、困惑度或主题一致性指标。核心数值指标主要是 reconstruction_err_,可视为矩阵重构误差:

$$ \mathrm{ReconstructionErr}=\lVert X-WH\rVert \tag{16} $$

实际数值来自 model.reconstruction_err_,并写入 Summary 工作表。

此外,final_results 中还会导出:

  • n_docs
  • n_features
  • n_topics
  • reconstruction_err
  • effective_solver
  • effective_beta_loss
  • compatibility_note

5.2 实际图表

_save_topic_charts() 会为前 4 个主题生成条形图:

  • topic_0_top_words_时间戳.png
  • topic_1_top_words_时间戳.png
  • topic_2_top_words_时间戳.png
  • topic_3_top_words_时间戳.png(若主题数足够)

注意这里有两个实现细节:

  • 图表只画前 max_topics=4 个主题;
  • 图片直接保存到结果目录,而不是嵌入 Excel。

5.3 实际导出的 Excel 工作表

utils/excel_handler.pysave_results() 的真实导出内容为:

  • Summary
  • Dataset
  • Vectorizer
  • Model
  • Output
  • Data_Meta
  • Vec_Meta
  • Raw_Preview
  • Topics_TopWords
  • Doc_Topic
  • Topic_TopDocs
  • Charts_Index

其中:

  • Raw_Preview 保存的是 df.head(50),不是完整原始数据;
  • Data_MetaVec_Meta 保存的是预处理/向量化元信息;
  • Charts_Index 会记录图表路径和文件是否存在。

这说明该模块的 processed_data 并不是一张清洗后的文本表,而是两个元信息字典 datasetvectorizer

6. 复现脚本与实现说明

6.1 复现脚本

结果页提供“导出复现代码”按钮,会生成 repro_nmf_topic_时间戳.py。脚本会:

  • 复制原始输入文件到结果目录的 repro_inputs/
  • 固化 DatasetConfig / VectorizerConfig / NmfModelConfig / OutputConfig
  • 重新调用 run_nmf_topic()save_results()

因此复现脚本复用的是同一套工程实现,而不是额外手写的算法代码。

6.2 实现说明与注意事项

结合真实代码,这个模块可以概括为:一个基于 TF-IDF/Count + sklearn NMF 的无监督主题发现工具。它支持:

  • NMFMiniBatchNMF
  • frobeniuskullback-leibler
  • word/char/auto 三种 analyzer
  • 自定义停用词
  • 主题 Top 词与主题 Top 文档导出

但它的边界也很明确:

  • 不是 LDA 概率主题模型;
  • 不输出主题一致性 coherence
  • 不做自动主题数选择;
  • 不使用验证集或测试集;
  • Doc_Topic 中是权重,不是归一化概率。

因此,这个实现更适合做工程化的 NMF 主题探索与结果导出,而不是概率主题建模研究。

7. 论文写作模板

可在论文“方法部分”中写为:

“本文采用基于矩阵分解思想的 NMF 主题模型对文本语料进行无监督主题提取。首先,对原始文本执行清洗、停用词过滤以及词级或字符级向量化,构造 TF-IDF 或词频矩阵;其次,通过非负矩阵分解将文档-词项矩阵分解为文档-主题矩阵和主题-词矩阵,从而得到各主题的高权重词及各文档的主题权重;随后,结合重构误差、主题 Top 词和主题 Top 文档对主题语义进行解释;最后,导出主题词表、文档主题权重表与可视化结果,用于辅助文本内容归纳与主题结构分析。”

8. 单篇终审补充

8.1 图题与表题对齐建议

  • Summary 表可写为:表X NMF 主题模型运行摘要表。
  • Dataset 表可写为:表X NMF 主题模型数据集配置表。
  • Vectorizer 表可写为:表X NMF 主题模型向量化参数表。
  • Model 表可写为:表X NMF 主题模型参数设置表。
  • Output 表可写为:表X NMF 主题模型输出摘要表。
  • Data_Meta 表可写为:表X NMF 主题模型数据元信息表。
  • Vec_Meta 表可写为:表X NMF 主题模型向量化元信息表。
  • Raw_Preview 表可写为:表X NMF 主题模型原始文本预览表。
  • Topics_TopWords 表可写为:表X NMF 主题 Top 词表。
  • Doc_Topic 表可写为:表X NMF 文档主题权重表。
  • Topic_TopDocs 表可写为:表X NMF 主题 Top 文档表。
  • Charts_Index 表可写为:表X NMF 主题模型图表索引与路径清单。
  • topic_0_top_words_*.png 建议写为:图X 第1个主题 Top 词条形图。
  • topic_1_top_words_*.png 建议写为:图X 第2个主题 Top 词条形图。
  • topic_2_top_words_*.png 建议写为:图X 第3个主题 Top 词条形图。

8.2 终审说明

  • 当前代表性结果目录可采用 results/nmf_manual_ui_20260323_184550。其中主工作簿为 NMF_Topic-NMF 主题模型分析结果_20260323_184550.xlsx,同目录下还保留了后续复现输出工作簿,正文和附录应把“主运行结果”与“复现结果”分开描述。
  • 当前真实工作表为 Summary/Dataset/Vectorizer/Model/Output/Data_Meta/Vec_Meta/Raw_Preview/Topics_TopWords/Doc_Topic/Topic_TopDocs/Charts_Index。论文表题应按这组英文工作表口径落地,不要改写成 LDA 风格的“主题词分布/困惑度”等术语。
  • Raw_Preview 只是原始文本预览,不是全量清洗结果;Doc_Topic 中的数值是 NMF 分解得到的主题权重,不应直接写成“主题概率”。
  • 当前真实图文件为 topic_0_top_words_20260323_184551.pngtopic_1_top_words_20260323_184551.pngtopic_2_top_words_20260323_184551.png。图数量受可视化上限和实际主题输出影响,正文不要想当然写成“每个主题均对应一张图”。
  • 真实 repro 脚本为 repro_nmf_topic_20260323_184551.py,并通过 SRC_FILE = 'repro_inputs/sample_data.csv' 读取输入副本。附录中的复现实验描述应保持这一相对路径口径。

8.3 全量强化补充

  • 本轮按真实磁盘再次核对,算法目录为 具体的算法3/NLP基础/NMF_Topic-NMF 主题模型,代表性结果目录为 具体的算法3/NLP基础/NMF_Topic-NMF 主题模型/results/nmf_manual_ui_20260323_184550
  • 该目录当前不是“主结果目录只含一主一副”那么简单,而是并存 3 份工作簿:NMF_Topic-NMF 主题模型分析结果_20260323_184550.xlsxNMF_Topic_results_20260323_184611.xlsxNMF_Topic_results_20260329_151143.xlsx。其中第一份更适合视为主运行结果,后两份属于后续再运行/复现实验产物,正文与附录不能把三者误写为同一次单轮导出。
  • 这 3 份工作簿的实际工作表一致,均为 SummaryDatasetVectorizerModelOutputData_MetaVec_MetaRaw_PreviewTopics_TopWordsDoc_TopicTopic_TopDocsCharts_Index。因此当前目录的重点不是结构差异,而是多轮运行在同目录累积落盘。
  • 当前实体图只有 3 张,分别为 topic_0_top_words_20260323_184551.pngtopic_1_top_words_20260323_184551.pngtopic_2_top_words_20260323_184551.png,并未看到与后续两份再运行工作簿完全一一对应的新图集。因此引用图证时应明确这是代表性主题 Top 词图,而不是宣称目录中每份工作簿都配有一套独立图目录。
  • 当前标准输入副本位于 repro_inputs/sample_data.csvrepro_nmf_topic_20260323_184551.py 中明确写有 SRC_FILE = 'repro_inputs/sample_data.csv'。这篇可以归为标准 repro_inputs/... 结构案例。
  • 论文写作时还应额外提醒:当前代表性目录中的 Raw_Preview 仅是预览表,而不是完整原始文本全集;目录命名 nmf_manual_ui_20260323_184550 说明其证据来源是手动 UI 运行,不是 smoke/baseline 测试目录。

9. 软件实现核查补充(2026-07)

  • 当前实现的主结果目录应写作 具体的算法3/NLP基础/NMF_Topic-NMF 主题模型/results/nmf_manual_ui_20260323_184550,主工作簿以 NMF_Topic-NMF 主题模型分析结果_20260323_184550.xlsx 为准。
  • 正文应围绕 SummaryDatasetVectorizerModelOutputData_MetaVec_MetaRaw_PreviewTopics_TopWordsDoc_TopicTopic_TopDocsCharts_Index 来写。
  • 该目录存在多份工作簿和多轮图像,正文要区分主运行结果与后续再运行产物,不要混成一次导出。
  • repro_nmf_topic_20260323_184551.py + repro_inputs/sample_data.csv 是标准 repro_inputs 复现口径,论文与附录应按这个路径说明。