NMF_Topic-NMF 主题模型
NMFTopic-NMF 主题模型 的真实实现位于 core/nmfrunner.py 与 core/textprep.py。该模块的核心不是概率主题模型,而是:
NMF_Topic-NMF 主题模型
1. 方法概述
NMF_Topic-NMF 主题模型 的真实实现位于 core/nmf_runner.py 与 core/text_prep.py。该模块的核心不是概率主题模型,而是:
- 读取文本列并做规范化;
- 用
TfidfVectorizer或CountVectorizer构造非负文档-词项矩阵; - 调用
sklearn.decomposition.NMF或MiniBatchNMF分解矩阵; - 输出主题 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 的真实逻辑
VectorizerConfig 中 analyzer 支持 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_minngram_maxmax_featuresmin_dfmax_dfstop_words_modestop_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 表包含:
topicrankwordweight
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_topic 与 top_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_idweighttext_snippet
其中 text_snippet 只截取前 200 个字符,超出部分加省略号。
5. 评价指标、图表与输出结果
5.1 评价指标
当前实现没有分类指标、困惑度或主题一致性指标。核心数值指标主要是 reconstruction_err_,可视为矩阵重构误差:
$$ \mathrm{ReconstructionErr}=\lVert X-WH\rVert \tag{16} $$
实际数值来自 model.reconstruction_err_,并写入 Summary 工作表。
此外,final_results 中还会导出:
n_docsn_featuresn_topicsreconstruction_erreffective_solvereffective_beta_losscompatibility_note
5.2 实际图表
_save_topic_charts() 会为前 4 个主题生成条形图:
topic_0_top_words_时间戳.pngtopic_1_top_words_时间戳.pngtopic_2_top_words_时间戳.pngtopic_3_top_words_时间戳.png(若主题数足够)
注意这里有两个实现细节:
- 图表只画前
max_topics=4个主题; - 图片直接保存到结果目录,而不是嵌入 Excel。
5.3 实际导出的 Excel 工作表
utils/excel_handler.py 中 save_results() 的真实导出内容为:
SummaryDatasetVectorizerModelOutputData_MetaVec_MetaRaw_PreviewTopics_TopWordsDoc_TopicTopic_TopDocsCharts_Index
其中:
Raw_Preview保存的是df.head(50),不是完整原始数据;Data_Meta与Vec_Meta保存的是预处理/向量化元信息;Charts_Index会记录图表路径和文件是否存在。
这说明该模块的 processed_data 并不是一张清洗后的文本表,而是两个元信息字典 dataset 和 vectorizer。
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 的无监督主题发现工具。它支持:
NMF与MiniBatchNMFfrobenius与kullback-leiblerword/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.png、topic_1_top_words_20260323_184551.png、topic_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.xlsx、NMF_Topic_results_20260323_184611.xlsx、NMF_Topic_results_20260329_151143.xlsx。其中第一份更适合视为主运行结果,后两份属于后续再运行/复现实验产物,正文与附录不能把三者误写为同一次单轮导出。 - 这 3 份工作簿的实际工作表一致,均为
Summary、Dataset、Vectorizer、Model、Output、Data_Meta、Vec_Meta、Raw_Preview、Topics_TopWords、Doc_Topic、Topic_TopDocs、Charts_Index。因此当前目录的重点不是结构差异,而是多轮运行在同目录累积落盘。 - 当前实体图只有 3 张,分别为
topic_0_top_words_20260323_184551.png、topic_1_top_words_20260323_184551.png、topic_2_top_words_20260323_184551.png,并未看到与后续两份再运行工作簿完全一一对应的新图集。因此引用图证时应明确这是代表性主题 Top 词图,而不是宣称目录中每份工作簿都配有一套独立图目录。 - 当前标准输入副本位于
repro_inputs/sample_data.csv,repro_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为准。 - 正文应围绕
Summary、Dataset、Vectorizer、Model、Output、Data_Meta、Vec_Meta、Raw_Preview、Topics_TopWords、Doc_Topic、Topic_TopDocs、Charts_Index来写。 - 该目录存在多份工作簿和多轮图像,正文要区分主运行结果与后续再运行产物,不要混成一次导出。
repro_nmf_topic_20260323_184551.py + repro_inputs/sample_data.csv是标准repro_inputs复现口径,论文与附录应按这个路径说明。