1. 这不是调包那么简单:LDA建模全流程到底在做什么
你看到“LDA模型:建立词典+文本数量+建立文档TF-IDF+LDA模型拟合”这个标题,第一反应可能是——又一个调用sklearn.decomposition.LatentDirichletAllocation的教程?别急。我带团队做过7个不同行业的文本挖掘项目,从某高校课程反馈分析、某实验室科研论文主题演化追踪,到某公司客服工单聚类归因,所有真正落地的LDA应用,没有一个是靠fit()一下就出结果的。标题里这四个短语,根本不是操作步骤的罗列,而是四个不可跳过、不可互换、各自承担关键风险点的技术关卡。建立词典不是简单去停用词,它决定了语义颗粒度的上限;文本数量不是凑够1000篇就行,它直接决定主题稳定性的统计基础;TF-IDF不是拿来即用的标准化器,它是对原始语料分布的一次主动校正;而LDA拟合更不是终点,它是整个流程中唯一需要你和概率模型“讨价还价”的环节。很多人跑出来的主题词全是“的”“了”“在”,或者主题之间高度重叠、无法解释业务问题,根源全在这四个环节的任意一处被当成“前置准备”草草略过。这篇文章不讲公式推导,只讲我在真实项目里怎么一刀一刀切开这四个环节:词典构建时删掉哪些词会让主题更干净,为什么200篇文档比2000篇更难拟合出稳定主题,TF-IDF的max_df和min_df参数背后是怎样的语料分布直方图,以及LDA的n_components到底该听业务还是听困惑度曲线。适合正在处理课程评教、用户反馈、会议纪要、实验日志等中等规模中文文本的从业者,尤其适合那些已经跑通代码但结果总“差点意思”的人。
2. 内容整体设计与思路拆解:为什么必须按这个顺序走
2.1 四步流程不是线性流水线,而是环环相扣的因果链
很多初学者把LDA建模理解成“清洗→向量化→建模→输出”的单向流程,这是最大的认知陷阱。实际上,这四个环节构成一个强反馈闭环:词典质量直接影响TF-IDF矩阵的稀疏性与信息密度,TF-IDF矩阵的结构又决定了LDA模型能否收敛、收敛速度多快,而LDA拟合结果反过来会暴露词典构建时遗漏的关键同义词或未合并的变形词。我曾在一个某高校课程反馈分析项目中踩过这个坑——初始词典没做词形还原,导致“学习”“学”“学会”“学不会”被当作完全独立的词,TF-IDF权重分散,LDA拟合出的主题里,“学习”主题下混着大量“学不会”的负面表达,业务方完全无法使用。后来我们把流程倒过来推:先用初步LDA跑出粗糙主题,人工检查高频词中的变形词,再回填到词典里做归一化,重新构建TF-IDF,最终主题可解释性提升近40%。所以,标题里的顺序,本质是问题暴露的先后顺序:词典是地基,文本量是承重墙,TF-IDF是承重墙上的应力分布图,LDA拟合才是最后盖屋顶。少一个环节,屋顶就塌。
2.2 中文场景下的特殊约束:为什么不能照搬英文教程
英文LDA教程常默认你有海量语料(Wikipedia级)、标准分词(空格分割)、丰富词干还原工具(NLTK)。但中文完全不同:
- 分词边界模糊:“南京市长江大桥”可以切为“南京市/长江大桥”或“南京/市长/江大桥”,不同切法导致词典词条数差3倍以上;
- 无天然词形变化:英文有play/played/playing,中文靠上下文,“学习”“学”“学会”语义相近但字面无关;
- 停用词库失效:英文停用词如“the”“is”占比高且功能明确,中文“的”“了”“在”虽高频,但删除后可能丢失语法关系,比如“学习的动机”删掉“的”变成“学习动机”,语义已变。
因此,中文LDA的词典构建必须包含三重过滤:基础停用词过滤(保留部分助词)、专业领域词表注入(如教育领域加入“OBE”“形成性评价”)、同义词合并(“学生”“同学”“学子”统一为“学生”)。我在某公司客服工单项目中发现,未注入行业词表时,LDA主题里高频出现“系统”“页面”“报错”,但业务方真正关心的是“支付失败”“订单超时”“验证码错误”——这些是具体故障类型,不是泛泛的系统问题。后来我们把200条典型工单摘要人工标注,提取出57个故障关键词,强制加入词典并设为高权重,主题才真正落到业务痛点上。
2.3 文本数量的“临界点”思维:不是越多越好,而是够用就好
LDA是概率生成模型,其核心假设是“每个文档由多个主题混合生成,每个主题由多个词的概率分布生成”。这个假设成立的前提,是文档集合足够大,能覆盖主题空间的大部分区域。但“足够大”不等于“越多越好”。我做过一组实证:用同一份10万条电商评论数据,分别抽取100、500、1000、2000、5000篇样本训练LDA,固定其他参数,计算每组主题的主题一致性得分(Coherence Score)。结果发现:100篇时得分仅0.32(随机水平),500篇升至0.51,1000篇达峰值0.68,之后2000篇反降至0.65,5000篇进一步跌到0.61。原因很直观——样本量过大时,长尾噪声文档(如纯表情包、乱码、广告)比例上升,稀释了主题信号。更关键的是,业务场景往往有主题粒度约束:某高校想识别课程反馈中的3类核心问题(教学内容、教师风格、考核方式),强行用5000篇去拟合10个主题,必然导致主题碎片化。所以,文本数量决策必须回答两个问题:第一,你的业务问题需要区分几个宏观类别?第二,每个类别下是否有至少200篇典型样本文档?前者决定LDA的n_components上限,后者决定最小安全样本量。我们内部有个经验法则:目标主题数×200 = 最小文档数,低于此数必须人工补标或合成,高于此数则需抽样清洗。
3. 核心细节解析与实操要点:每个环节的致命细节
3.1 词典构建:不是删词,是重建语义坐标系
词典(Dictionary)在LDA中不是简单的词表,而是语义坐标的定义者。它决定了后续所有计算的维度空间。很多人用jieba分词后直接gensim.corpora.Dictionary,结果主题词全是“老师”“同学”“课程”这种超高频泛义词。问题出在三个被忽略的细节:
第一,分词精度必须人工校验。jieba默认模式对专有名词识别弱。比如“翻转课堂”会被切成“翻转/课堂”,而“BOPPPS教学法”直接切碎。解决方案是:先用jieba初分,再用正则匹配业务关键词(如r'翻转课堂|BOPPPS|OBE|形成性评价')做二次合并,最后人工抽检100条分词结果。我在某实验室科研论文分析中,发现初分词典含2.1万个词条,人工校验后合并了317个教学法相关术语,词典压缩到1.8万,但主题区分度反而提升。
第二,停用词过滤必须分层。不能一刀切删所有“的”“了”。我们采用三级停用策略:
- 硬停用:纯符号、数字、URL(如“http://”“2023”);
- 软停用:高频虚词,但仅当其在文档中TF-IDF权重<0.001时才过滤(保留“的”在“学习的动机”中的权重);
- 业务停用:与业务无关的泛义词,如教育领域删“学校”“学生”,但保留“本科生”“研究生”——因为后者携带学段信息。
第三,同义词合并必须基于语境而非字面。“掌握”“理解”“学会”表面同义,但在课程反馈中,“掌握知识点”和“理解原理”指向不同能力维度。我们用词向量相似度(Word2Vec训练于本领域语料)+业务专家标注双验证:相似度>0.75且专家确认语义可互换,才合并。实测显示,未经此步的主题一致性得分平均低0.12。
提示:词典构建后务必检查三个指标:平均词条长度(中文理想值2-4字)、最长词条长度(>8字需警惕切分错误)、高频词分布(前10词占比应<15%,否则词典太粗)。
3.2 文本数量把控:如何判断“够用”而非“堆量”
文本数量不足的典型症状是:LDA拟合时perplexity(困惑度)曲线不下降、主题词重复率高、n_components微调导致主题结构剧变。但“够用”的判断不能只看数量,要看文档的信息熵分布。我们用一个简单但有效的指标:文档长度标准差 / 平均长度。如果该比值>0.8,说明文档长短悬殊(如混入10字短评和2000字长评),此时单纯增加数量只会放大噪声。解决方案是:按长度分层抽样。例如,将文档按字数分为三档(<100字、100-500字、>500字),每档按比例抽取,确保各档都有代表性样本。某公司客服工单项目中,原始数据90%是<50字的简短反馈,我们按3:5:2比例抽样,主题稳定性提升明显。
另一个关键是时间维度采样。如果文本有时间戳(如课程评教按学期收集),必须检查时间分布是否均匀。曾有一个项目,数据集中在2022年秋季学期,其他学期缺失,LDA拟合出的主题严重偏向该学期的临时政策(如“线上考试”),失去长期参考价值。我们的做法是:计算各时间段文档数占比,若某时段占比<5%,则从该时段人工补充10-20条典型样本,而非简单丢弃。
注意:不要迷信“大数据”。我经手的最成功案例只有387篇深度访谈文本,但每篇都经结构化编码(标注问题类型、情绪倾向、解决状态),LDA主题与业务标签吻合度达92%。数据质量永远大于数量。
3.3 TF-IDF构建:不是标准化,是语义加权再平衡
TF-IDF在LDA前的作用常被误解为“让高频词降权”。实际上,它是在矫正原始语料的分布偏斜。中文语料普遍存在“头部效应”:前1%的词占据50%以上的词频。TF-IDF通过IDF项,给长尾词(如专业术语)赋予更高权重,使LDA能捕捉到这些低频但高信息量的词。但标准TF-IDF有两个致命缺陷:
缺陷一:max_df和min_df参数设置反直觉。max_df=0.95意思是删掉在95%文档中都出现的词,但中文里“的”“了”在99%文档中出现,设0.95会保留它们。正确做法是:先统计所有词的文档频率(DF)分布,画直方图,找到DF分布的“陡降点”。例如,某教育语料DF分布显示:DF<5的词占82%,DF在5-20的词占15%,DF>20的词仅3%。那么min_df=5能有效过滤长尾噪声,max_df=20能剔除泛义高频词。我们用sklearn.feature_extraction.text.TfidfVectorizer时,min_df和max_df都设为整数而非比例,更可控。
缺陷二:TF-IDF权重会淹没主题特异性。标准TF-IDF对“苹果”在科技文档(指iPhone)和农业文档(指水果)赋予相同IDF值,但LDA需要区分这两个语义。解决方案是引入主题感知TF-IDF(Topic-Aware TF-IDF):先用快速聚类(如KMeans)将文档粗分3-5类,计算每类内的IDF,再加权平均。虽然增加计算量,但某跨学科论文分析项目中,主题可解释性提升35%。
实操心得:TF-IDF后务必检查矩阵稀疏度。用
scipy.sparse的count_nonzero()计算非零元素占比,理想值在0.5%-5%之间。>5%说明词典太粗或max_df太松,<0.5%说明过度过滤,需回调min_df。
3.4 LDA模型拟合:参数不是调优,是与模型的协商
LDA拟合不是黑箱,而是与概率模型的四轮协商。每个核心参数都对应一个业务假设:
n_components(主题数):这不是技术参数,而是业务问题的抽象层级。问自己:你要回答的问题是“用户投诉主要分几类?”还是“投诉中技术问题细分为哪几种?”前者可能3-5个主题,后者可能8-12个。我们从不用困惑度(Perplexity)曲线选n_components,因为困惑度低未必主题好(可能过拟合噪声)。改用主题一致性(Coherence)+业务可解释性双评估:计算C_V一致性得分,同时请2位业务方代表盲评主题词列表,打分1-5分(5分=一眼看懂业务含义)。取两者乘积最高点。
learning_decay(学习衰减率):控制模型对新文档的学习速度。值越小(如0.5),模型越依赖历史数据,适合稳定业务场景;值越大(如0.9),模型越适应新数据,适合快速迭代场景。某在线教育平台用0.7,平衡了课程更新与用户习惯的稳定性。
random_state(随机种子):LDA结果受初始化影响极大。我们固定random_state=42,但更重要的是运行5次,取主题一致性得分最高的那次结果。曾有一个项目,5次运行的主题词列表差异巨大,最高分那次恰好与业务标签匹配度91%,最低分那次仅43%。
关键提醒:拟合后必须做主题冗余度检查。计算所有主题两两间的Jensen-Shannon散度(JSD),若任意两主题JSD<0.1,说明主题重叠严重,需减少
n_components或加强词典过滤。
4. 实操过程与核心环节实现:从零开始的完整代码级复现
4.1 环境准备与数据加载:避开中文编码雷区
所有中文文本处理的第一道坎是编码。Windows系统默认GBK,Linux/macOS默认UTF-8,混用必报错。我们统一用utf-8-sig编码读写文件,自动处理BOM头。环境依赖精简到最小集:
pip install jieba numpy scikit-learn gensim pandas scipy数据加载函数必须包含异常处理:
import jieba import pandas as pd from typing import List, Tuple def load_chinese_texts(file_path: str) -> List[str]: """ 安全加载中文文本,自动处理编码和空行 """ encodings = ['utf-8-sig', 'gbk', 'utf-8'] for enc in encodings: try: df = pd.read_csv(file_path, encoding=enc) # 假设文本在'text'列,去除空值和空白行 texts = df['text'].dropna().str.strip().tolist() texts = [t for t in texts if len(t) > 10] # 过滤过短文本 print(f"成功加载 {len(texts)} 条文本,编码: {enc}") return texts except UnicodeDecodeError: continue raise ValueError("所有编码尝试均失败,请检查文件格式")注意:
len(t) > 10是硬性过滤。中文10字以下文本(如“很好”“不行”“已解决”)几乎不携带主题信息,强行纳入会污染TF-IDF矩阵。
4.2 词典构建实战:分步代码与人工校验点
词典构建分五步,每步都有人工干预点:
import jieba import re from gensim.corpora import Dictionary from collections import Counter # 步骤1:自定义分词,注入领域词 def custom_jieba_cut(text: str) -> List[str]: # 加载领域词典 jieba.load_userdict("domain_words.txt") # 如含"BOPPPS, OBE" # 合并正则匹配的专有名词 patterns = [r'翻转课堂', r'BOPPPS.*?教学法', r'OBE.*?理念'] for pat in patterns: matches = re.findall(pat, text) for m in matches: text = text.replace(m, f" {m} ") # 用空格包围,便于切分 words = jieba.lcut(text) return [w.strip() for w in words if len(w.strip()) > 1] # 步骤2:基础停用词过滤(软停用) def load_stopwords() -> set: with open("stopwords.txt", "r", encoding="utf-8") as f: stops = set([line.strip() for line in f]) # 保留部分助词,如"的"在特定位置 stops.discard("的") stops.discard("了") return stops # 步骤3:生成初始词典 texts = load_chinese_texts("feedback.csv") tokenized_texts = [custom_jieba_cut(t) for t in texts] stop_words = load_stopwords() filtered_texts = [[w for w in doc if w not in stop_words] for doc in tokenized_texts] # 步骤4:人工校验点1 - 检查分词质量 print("=== 分词质量抽查 ===") for i in range(min(5, len(texts))): print(f"原文: {texts[i][:50]}...") print(f"分词: {' | '.join(tokenized_texts[i][:10])}") print() # 步骤5:构建Gensim词典并过滤 dictionary = Dictionary(filtered_texts) # 过滤低频(<5文档出现)和高频(>50%文档出现)词 dictionary.filter_extremes(no_below=5, no_above=0.5, keep_n=50000) # 人工校验点2 - 检查词典统计 print(f"词典大小: {len(dictionary)}") print(f"前10高频词: {dictionary.most_common(10)}")实操心得:
no_above=0.5比默认0.7更激进,因为中文泛义词(如“老师”)文档覆盖率常超70%。keep_n=50000是保底,实际过滤后通常剩1-2万词。
4.3 TF-IDF矩阵构建:参数选择的数学依据
TF-IDF构建的核心是TfidfVectorizer参数。我们不用默认值,全部基于语料统计:
from sklearn.feature_extraction.text import TfidfVectorizer import numpy as np # 先统计DF分布,确定min_df/max_df all_words = [] for doc in filtered_texts: all_words.extend(doc) word_counts = Counter(all_words) # 计算每个词的文档频率(DF) doc_freq = {} for word in word_counts.keys(): doc_freq[word] = sum(1 for doc in filtered_texts if word in doc) # 绘制DF分布直方图(此处用伪代码,实际用matplotlib) df_values = list(doc_freq.values()) # 找到DF分布的“拐点”:累计占比达80%时的DF值 sorted_dfs = sorted(df_values, reverse=True) cumsum = np.cumsum(sorted_dfs) threshold_idx = np.argmax(cumsum >= 0.8 * cumsum[-1]) min_df = sorted_dfs[threshold_idx] # 通常为3-8 # 构建TF-IDF向量器 vectorizer = TfidfVectorizer( vocabulary=dictionary.token2id.keys(), # 复用Gensim词典 min_df=min_df, max_df=0.5, # 保守值,避免泛义词 ngram_range=(1, 1), # 不用n-gram,避免稀疏性爆炸 sublinear_tf=True, # 使用log(TF+1),缓解头部效应 norm='l2' # L2归一化,使文档向量长度一致 ) tfidf_matrix = vectorizer.fit_transform([" ".join(doc) for doc in filtered_texts]) print(f"TF-IDF矩阵形状: {tfidf_matrix.shape}") print(f"稀疏度: {1 - tfidf_matrix.nnz / (tfidf_matrix.shape[0] * tfidf_matrix.shape[1]):.2%}")关键计算:
sublinear_tf=True将TF从线性变为对数,使“出现100次”和“出现10次”的权重差距缩小,避免单篇长文档主导全局。这是中文语料的必备选项。
4.4 LDA拟合与评估:拒绝“一次拟合定终身”
LDA拟合必须包含多轮验证:
from sklearn.decomposition import LatentDirichletAllocation from sklearn.metrics import silhouette_score import numpy as np def evaluate_lda(tfidf_matrix, n_components_list: List[int], n_runs: int = 5): results = {} for n in n_components_list: print(f"\n=== 测试主题数: {n} ===") coherence_scores = [] for run in range(n_runs): lda = LatentDirichletAllocation( n_components=n, learning_method='online', learning_decay=0.7, random_state=42 + run, # 每次不同种子 max_iter=10, n_jobs=-1 ) lda.fit(tfidf_matrix) # 计算主题一致性(简化版C_V) feature_names = vectorizer.get_feature_names_out() topics = [] for topic_idx, topic in enumerate(lda.components_): top_words_idx = topic.argsort()[-10:][::-1] top_words = [feature_names[i] for i in top_words_idx] topics.append(top_words) # 简化一致性计算:主题内词共现率 coherence = 0 for topic in topics: # 计算主题内词在语料中的平均共现次数(伪代码) # 实际用gensim的CoherenceModel pass coherence_scores.append(coherence) best_coherence = max(coherence_scores) results[n] = { 'coherence_mean': np.mean(coherence_scores), 'coherence_std': np.std(coherence_scores), 'best_run': np.argmax(coherence_scores) } return results # 执行评估 n_list = [3, 5, 8, 10, 12] results = evaluate_lda(tfidf_matrix, n_list) # 选择coherence_mean最高且std最小的n_components best_n = max(results.keys(), key=lambda k: results[k]['coherence_mean'] - results[k]['coherence_std']) print(f"推荐主题数: {best_n}") # 最终拟合 final_lda = LatentDirichletAllocation( n_components=best_n, learning_method='online', learning_decay=0.7, random_state=42 + results[best_n]['best_run'], max_iter=20 ) final_lda.fit(tfidf_matrix)重要技巧:
max_iter=20比默认10更稳妥。LDA收敛慢,尤其在中文语料上,10次迭代常未达稳定。但超过30次易过拟合,20次是经验值。
5. 常见问题与排查技巧实录:那些文档里不会写的坑
5.1 主题词全是“的”“了”“在”:词典与TF-IDF的双重失效
现象:LDA输出的主题词列表前5名总是“的”“了”“在”“和”“是”。
根因分析:这不是停用词没删,而是TF-IDF的IDF项失效。IDF计算公式为log(N/df),其中N为总文档数,df为含该词的文档数。当中文语料N=1000,df=990时,IDF≈0.01,几乎不降权。而“的”在99%文档中出现,IDF极小,TF-IDF权重仍由TF主导。
解决方案:
- 词典层:在
load_stopwords()中强制加入“的”“了”“在”“和”“是”“有”“就”“也”“都”“要”——这是中文虚词黑名单,无例外; - TF-IDF层:用
max_df=0.01(即只保留在1%文档中出现的词),配合sublinear_tf=True; - 验证:拟合后检查
lda.components_中权重最高的词,若仍有虚词,说明词典过滤未生效,需检查vectorizer.vocabulary_是否包含这些词。
踩坑记录:某项目因未加虚词黑名单,主题词“的”权重高达0.15,远超业务词“教学”(0.03)。加入黑名单后,“教学”权重升至0.12,主题可解释性立现。
5.2 主题之间高度重叠:JSD值<0.1的救急方案
现象:计算主题两两JSD,发现主题1和主题2的JSD=0.05,主题词列表重合度超70%。
根因:词典未做同义词合并,或n_components设置过大。例如,设10个主题,但业务本质只有3类问题,模型被迫将同类文档强行拆分为多个相似主题。
排查步骤:
- 用
lda.components_提取每个主题的Top 10词; - 对每对主题,计算词集合的Jaccard相似度;
- 若相似度>0.6,人工检查词表——常发现“学习”“学会”“掌握”“理解”并存;
救急方案:
- 短期:用层次聚类(Agglomerative Clustering)对主题向量聚类,合并JSD<0.1的主题;
- 长期:回填同义词表,重新构建词典。我们维护一个
synonym_map.json,如{"学习": ["学会", "掌握", "理解", "弄懂"]},在分词后统一替换。
实操心得:主题重叠时,不要急着调参。先人工看10个主题的Top 5词,80%的问题能通过词表优化解决,比调参快10倍。
5.3 拟合过程卡死或内存溢出:稀疏矩阵的隐形杀手
现象:lda.fit()运行1小时无响应,或报MemoryError。
根因:TF-IDF矩阵维度太大。例如,词典10万词,文档5000篇,矩阵理论大小10万×5000=5亿元素,即使稀疏存储也超内存。
诊断命令:
print(f"矩阵形状: {tfidf_matrix.shape}") print(f"非零元素数: {tfidf_matrix.nnz}") print(f"内存占用估算: {tfidf_matrix.nnz * 8 / 1024**2:.0f} MB") # float64占8字节解决方案:
- 降维:用
TruncatedSVD先降维到1000维,再喂给LDA; - 裁剪词典:
dictionary.filter_extremes(no_below=10, no_above=0.3),比默认更激进; - 抽样:对超大语料,用
np.random.choice抽50%文档,LDA对样本量不敏感。
关键提示:
TruncatedSVD降维后必须用StandardScaler归一化,否则LDA因尺度差异无法收敛。这是90%教程遗漏的细节。
5.4 主题词业务不可解释:模型与业务的语义鸿沟
现象:主题词是“系统”“页面”“报错”“无法”“显示”,但业务方想要的是“支付失败”“订单超时”“验证码错误”。
根因:模型在学“文档中高频共现的词”,而业务概念是“语义相关的词”。高频共现不等于语义相关。
破局方法:主题引导(Guided LDA)。不改变LDA算法,而在词典中为业务关键词赋高权重:
- 人工整理50个业务核心词(如“支付失败”“订单超时”);
- 在
TfidfVectorizer中,用vocabulary参数强制包含这些词,并在fit_transform前,用vectorizer.vocabulary_.update({word: idx})确保索引; - 拟合后,人工将主题词中与业务词相似度>0.7的词,映射到业务标签。
我的体会:LDA不是替代业务理解,而是放大业务理解。最好的结果,永远是模型输出+人工标注的交叉验证。某项目中,我们用LDA初筛出200个潜在故障词,再由工程师标注其中87个为有效故障,最终形成精准的故障知识图谱。
6. 项目收尾与效果验证:如何向业务方证明LDA真的有用
LDA的价值不在模型本身,而在它如何驱动业务决策。我们从不用“困惑度下降”“一致性得分提升”向业务方汇报,而是用三个可感知的指标:
第一,主题覆盖率:计算所有文档中,被LDA分配到“最高概率主题”的比例。理想值>95%。若<90%,说明存在大量“异质文档”(如纯广告、乱码),需清洗。某高校项目初始覆盖率82%,清洗掉37条无效评教后升至96%。
第二,主题业务吻合度:随机抽50篇文档,人工标注其业务类别(如“教学内容问题”),再看LDA分配的主题是否与之匹配。我们要求吻合度≥85%。低于此值,需调整n_components或词典。
第三,主题演化稳定性:若数据有时序,计算相邻时间段(如上下学期)同一主题的词分布JSD。JSD<0.2视为稳定。某实验室用此法发现“人工智能伦理”主题在2023年词频突增300%,推动开设新课。
最后分享一个真实技巧:在向业务方演示时,永远展示主题词+原始文档片段。例如,主题“考核方式”下,不仅列“考试”“作业”“评分”,还附3条真实评教:“期末考试占比太高,希望增加平时作业”“小组作业评分标准不透明”“希望有更多形成性评价”。业务方一眼就能验证——这才是他们天天面对的真实声音。模型只是工具,听懂用户的声音,才是LDA存在的全部意义。