* g! L2 W' J1 r( A) _' `LDA 文档生成流程 6 v( E t- d; o) CLDA 假设文档是由多个主题的混合来产生的,每个文档的生成过程如下: 2 l2 ?4 k% J% {* t5 R C5 n5 [! [5 o 7 s* M8 y# |0 I. R) f; U4 k从全局的泊松分布参数为 ββ 的分布中生成一个文档的长度 NN # p' {1 f3 X% K. ?9 w从全局的狄利克雷参数为 alphaalpha 的分布中生成一个当前文档的 θθ 4 i3 {5 ]$ q/ |: K" a. h: P对当前文档长度 NN 的每一个字都有 4 y6 W$ k( `, z" \从 θθ 为参数的多项式分布生成一个主题的下标 znzn1 E+ [6 B- v b" |5 \
从 θθ 和 zz 共同为参数的多项式分布中,产生一个字 wnwn; _$ ]7 r: p \ p B8 j
这些主题基于词的概率分布来产生词,给定文档数据集,LDA 可以学习出,是哪些主题产生了这些文档。' u) v6 M% ]: y: ^9 ~# n
- p1 j% V, u+ \" g对于文档生成过程,则有,首先对于文档 nn 中的每一个字,都先从文档矩阵 M1M1 中的 θiθi 中产生一个下标,告诉我们现在要从主题矩阵 M2M2 中的哪一行 ϕmϕm生成当前的字。 " ]# @" T+ q1 ?3 M 6 t' I5 ~( x7 O- M' s" ~7 Z8 L- S* H: y! ~
训练过程(吉布斯采样) - X* L9 u4 S, q. K! p2 q; i+ O吉布斯采样 (Gibbs Sampling) 首先选取概率向量的一个维度,给定其他维度的变量值当前维度的值,不断收敛来输出待估计的参数。具体地 R2 P/ p0 ]) R. i5 [/ D" y 1 {5 a d. x, e8 P/ k: U随机给每一篇文档的每一个词 ww,随机分配主题编号 zz 0 O$ @7 I9 P1 m% s' `3 e0 R' ^统计每个主题 zizi 下出现字 ww 的数量,以及每个文档 nn 中出现主题 zizi 中的词 ww的数量 ( ^; S& w6 {8 U4 y' M每次排除当前词 ww 的主题分布 zizi,根据其他所有词的主题分类,来估计当前词 ww 分配到各个主题 z1,z2,…,zkz1,z2,…,zk 的概率,即计算 p(zi|z−i,d,w)p(zi|z−i,d,w) (Gibbs updating rule))。得到当前词属于所有主题z1,z2,…,zkz1,z2,…,zk 的概率分布后,重新为词采样一个新的主题 z1z1。用同样的方法不断更新的下一个词的主题,直到每个文档下的主题分布θnθn 和每个主题下的词分布 ϕkϕk 收敛。 9 s2 a& {6 E$ a% F. c最后输出待估计参数,θnθn 和 ϕkϕk ,每个单词的主题 zn,kzn,k 也可以得到。 , |. C: P" l0 c) L, m. l( |$ o. T ) O5 B6 ~" G o2 ? # i8 A9 E- |" n- CLDA 对于每个文档的每一个字都有一个主题下标。但从文档聚类的角度来说,LDA 没有一个文档统一的聚类标签,而是每个字都有一个聚类标签,这个就是主题。LDA 每个字都有可能属于不同的类别,每个文档都有可能属于不同的类别。在大量的迭代后,主题分布和字分布都比较稳定也比较好了,LDA 模型收敛。 . j: z7 q% S! k6 [9 f+ Y, b" k4 l2 {. d% [" U
6 o4 H) m$ n- u: X: a
1 `: ^5 ]" ~* `7 B9 Q% B& B
三、LDA 的参数' \0 C) i. s) ^0 B
αα :表示 document-topic 密度, αα 越高,文档包含的主题更多,反之包含的主题更少 3 j' C, h4 s9 C; Y" b 1 `+ Z D/ P4 d: c: Hββ :表示 topic-word 密度, ββ 越高,主题包含的单词更多,反之包含的单词更少9 u9 E5 ~- L( l e) N
?1 [- i8 f* l6 P( A/ f4 j" b" t
主题数量:主题数量从语料中抽取得到,使用 Kullback Leibler Divergence Score 可以获取最好的主题数量。 # u+ N8 Z/ n5 V' N( ^, _: o& w$ L$ B' W
主题词数:组成一个主题所需要的词的数量。这些词的数量通常根据需求得到,如果说需求是抽取特征或者关键词,那么主题词数比较少,如果是抽取概念或者论点,那么主题词数比较多。 / Z- P) _+ x. B5 l1 n* @, x$ {2 `7 U) F2 ~$ h+ J0 X
迭代次数:使得 LDA 算法收敛的最大迭代次数; i" W3 F7 C7 E4 g( D& t" x
u/ Z; r' h' f& S% D" ?8 B2 t2 |" r8 g) M& i# A
7 ]. q& S7 y- n/ a; `1 @/ M* S, E5 P
四、Running in Python6 w! v, w v3 z4 P" p) V4 D
准备文档集合. F2 I/ g" L" Q0 e9 d7 m) @
doc1 = "Sugar is bad to consume. My sister likes to have sugar, but not my father."1 G% f. d+ H/ D
doc2 = "My father spends a lot of time driving my sister around to dance practice." ( P( B w8 c3 c4 K+ b" S4 ]" gdoc3 = "Doctors suggest that driving may cause increased stress and blood pressure." 5 b+ o( s! I |1 W: Vdoc4 = "Sometimes I feel pressure to perform well at school, but my father never seems to drive my sister to do better." / n/ b$ `9 i1 {+ w) w, N0 qdoc5 = "Health experts say that Sugar is not good for your lifestyle." 4 R# I( i1 F7 t, u, J, ` - u/ Q4 W2 R; _+ P# 整合文档数据' J, W6 _0 @; ~1 S
doc_complete = [doc1, doc2, doc3, doc4, doc5] \* H/ y% r% d- i& ?6 r% V3 g( Q% e# K1 `
数据清洗和预处理9 G" X. U$ b, u/ n: d9 ^- s
数据清洗对于任何文本挖掘任务来说都非常重要,在这个任务中,移除标点符号,停用词和标准化语料库(Lemmatizer,对于英文,将词归元)。 - B; q5 Z0 }8 a7 S4 ]$ Q" B, `/ l2 f/ j
from nltk import stopwords : [' u/ q3 Y8 n: B4 t ?from nltk.stem.wordnet import WordNetLemmatizer 8 ^4 y( {$ ]( rimport string 3 K5 w9 T% O1 K- b5 u: e6 n9 o3 Z, h7 b. ~* |5 r$ E4 G
stop = set(stopwords.words('english'))$ \! `9 [- H% G3 x: X
exclude = set(string.punctuation) ( m4 v9 f! x+ I. H8 rlemma = WordNetLemmatizer() 4 i8 s( x6 V- O0 ~7 }3 J) D. M3 \" u2 e
def clean(doc):8 `) S; u x K- Z/ {0 t. H
stop_free = " ".join([i for i in doc.lower().split() if i not in stop])% Z- W: W* z8 Y, j4 o* ~' d+ ~4 L/ r
punc_free = ''.join(ch for ch in stop_free if ch not in exclude) % V# I8 S) A4 L. K6 d U/ U, b' } normalized = " ".join(lemma.lemmatize(word) for word in punc_free.split())7 z3 V/ z# M: A/ v/ ^
return normalized # D! l& |2 Q P* ?% g& c/ \% P# x x: M
doc_clean = [clean(doc).split() for doc in doc_complete] ; [5 g: l3 G ?3 Y9 [5 F+ s- v( X1 i9 T
准备 Document - Term 矩阵 7 C; a7 T/ _* @8 W. D语料是由所有的文档组成的,要运行数学模型,将语料转化为矩阵来表达是比较好的方式。LDA 模型在整个 DT 矩阵中寻找重复的词语模式。Python 提供了许多很好的库来进行文本挖掘任务,“genism” 是处理文本数据比较好的库。下面的代码掩饰如何转换语料为 Document - Term 矩阵: 3 s) ^" ^& X+ B8 p. D ' I4 L4 h, C, s6 n' o7 R0 Pimport genism1 d( \0 P( r9 [
from gensim import corpora 6 D* d5 v' A# i: V , Z' X% L6 P! f0 P* f' A4 t# 创建语料的词语词典,每个单独的词语都会被赋予一个索引! h# J9 R* H5 ^2 U4 i- V: {
dictionary = corpora.Dictionary(doc_clean) - M$ q5 U8 v9 h* U " E5 [. V/ n( j3 e# 使用上面的词典,将转换文档列表(语料)变成 DT 矩阵 6 [* X( c. l# c' E. t" s" ?; vdoc_term_matrix = [dictionary.doc2bow(doc) for doc in doc_clean]8 ]5 [% O8 c. \4 R A s$ q' p& U- R5 B