← 返回教程目录
第 4 章 · 第 2 节 LDA 主题分析

训练 LDA:困惑度选 K 值

Train LDA: Choosing K via Perplexity

LDA 主题数 K 选多少,是老板们问得最多的问题。答案是没有"标准答案" — 但有 2 个客观指标可以参考:困惑度(perplexity)主题一致性(coherence)

1. 准备语料(接着上一节)

import pandas as pd


import gensim


from gensim import corpora





df = pd.read_pickle('comments_processed.pkl')


texts = df['tokens'].tolist()





# 1. 词典


dictionary = corpora.Dictionary(texts)


dictionary.filter_extremes(no_below=10, no_above=0.5)





# 2. 语料(词袋)


corpus = [dictionary.doc2bow(t) for t in texts]





print(f'词典: {len(dictionary)} 个词,语料: {len(corpus)} 篇文档')

2. 训练 LDA 模型

from gensim.models import LdaModel





lda = LdaModel(


    corpus=corpus,


    id2word=dictionary,


    num_topics=10,        # 主题数(先猜一个)


    passes=15,            # 训练轮数(15-20 即可)


    iterations=200,


    random_state=42,


    alpha='auto',


    eta='auto',


)





# 看主题


for i in range(10):


    print(f'主题 {i}: {lda.print_topic(i, topn=8)}')

3. 困惑度(perplexity)选 K

import matplotlib.pyplot as plt





perplexities = []


K_range = range(2, 21)





for K in K_range:


    lda = LdaModel(corpus=corpus, id2word=dictionary, num_topics=K, passes=10, random_state=42)


    p = lda.log_perplexity(corpus)


    perplexities.append(p)


    print(f'K={K}, perplexity={p:.2f}')





# 画图


plt.plot(K_range, perplexities, 'o-')


plt.xlabel('主题数 K')


plt.ylabel('困惑度(越低越好)')


plt.title('困惑度选 K')


plt.savefig('perplexity.png', dpi=150)
困惑度陷阱:困惑度会随 K 增大持续下降,选 K 大的困惑度永远最小。实际中要找"拐点" — 困惑度下降速度变缓的位置。

4. 主题一致性(coherence)— 更推荐的指标

from gensim.models import CoherenceModel





coherences = []


for K in K_range:


    lda = LdaModel(corpus=corpus, id2word=dictionary, num_topics=K, passes=10, random_state=42)


    cm = CoherenceModel(model=lda, texts=texts, dictionary=dictionary, coherence='c_v')


    c = cm.get_coherence()


    coherences.append(c)


    print(f'K={K}, coherence={c:.3f}')





plt.plot(K_range, coherences, 'o-', color='red')


plt.xlabel('主题数 K')


plt.ylabel('一致性 c_v(越高越好)')


plt.title('一致性选 K')


plt.savefig('coherence.png', dpi=150)

5. 双指标对比,取交叉点

fig, axes = plt.subplots(1, 2, figsize=(14, 5))


axes[0].plot(K_range, perplexities, 'o-')


axes[0].set_title('困惑度(越低越好)')


axes[1].plot(K_range, coherences, 'o-', color='red')


axes[1].set_title('一致性(越高越好)')


for ax in axes:


    ax.set_xlabel('主题数 K')


    ax.grid(True, alpha=.3)


plt.tight_layout()


plt.savefig('k_selection.png', dpi=150)





# 找最佳 K


best_K = list(K_range)[coherences.index(max(coherences))]


print(f'推荐 K = {best_K} (一致性最高)')

选好 K 值,下一节我们把它可视化 — 主题气泡图 + 主题词云。

选 K 值还要看一致性?LDA 软件自动算困惑度 + 一致性两条曲线

配套软件内置案例数据 + 模板,导入即出图,无需写代码

查看淘宝软件 →