' z: ?6 S; @# V! w $ b6 b+ v" z& g7 V" T + T! G9 c) d1 c上面显示了 M2M2 矩阵的情况,它是一个 K∗VK∗V 维的 topic - term矩阵,KK 指主题的数量,VV 指词汇表的大小。M2M2 中每一行都是一个 ϕϕ 分布,也就是主题 ϕkϕk 在 mm 个词上的多项式分布情况,可以通过学习得到。 6 }9 ~) M/ L4 C C- w8 J4 n0 F6 P& A1 y& R$ X6 w b. y
LDA 文档生成流程. b4 S [8 J# l$ }
LDA 假设文档是由多个主题的混合来产生的,每个文档的生成过程如下: / ~, D$ F" H0 r1 Q3 B/ b v1 Z* e4 `3 X& {7 w0 k
从全局的泊松分布参数为 ββ 的分布中生成一个文档的长度 NN( i1 b4 r% y* G! y4 ?
从全局的狄利克雷参数为 alphaalpha 的分布中生成一个当前文档的 θθ/ E; \3 f( z) |8 R7 a2 |3 n6 u
对当前文档长度 NN 的每一个字都有3 ~. i! X. I* _0 D8 H0 i7 z. | F
从 θθ 为参数的多项式分布生成一个主题的下标 znzn3 [9 C9 D6 n( Y( t
从 θθ 和 zz 共同为参数的多项式分布中,产生一个字 wnwn6 b6 B+ r7 k( A/ p
这些主题基于词的概率分布来产生词,给定文档数据集,LDA 可以学习出,是哪些主题产生了这些文档。( p% m; P8 a, X3 p! Z" q' c
2 M; E5 ~, a" w l- k3 G* _
对于文档生成过程,则有,首先对于文档 nn 中的每一个字,都先从文档矩阵 M1M1 中的 θiθi 中产生一个下标,告诉我们现在要从主题矩阵 M2M2 中的哪一行 ϕmϕm生成当前的字。' D. i0 ?1 Z- G* f( @
& ]: @& P$ ^6 ^/ q3 C8 U0 c5 @/ _( c1 E
训练过程(吉布斯采样)3 }2 i9 \9 ^( J! U
吉布斯采样 (Gibbs Sampling) 首先选取概率向量的一个维度,给定其他维度的变量值当前维度的值,不断收敛来输出待估计的参数。具体地8 G: K+ C" t& F* F4 x- V
{/ h; e! a' H' ]
随机给每一篇文档的每一个词 ww,随机分配主题编号 zz ; y' P2 P+ x* C+ c0 t1 m9 t3 P统计每个主题 zizi 下出现字 ww 的数量,以及每个文档 nn 中出现主题 zizi 中的词 ww的数量/ k6 ^- p5 N y& N
每次排除当前词 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 收敛。6 x2 j. L- e, u; [
最后输出待估计参数,θnθn 和 ϕkϕk ,每个单词的主题 zn,kzn,k 也可以得到。 ( |6 y/ b% f P( U- h2 t1 ?" O' t2 q, c9 O* A& o* i
" R Z* ^2 J& w2 F3 U5 RLDA 对于每个文档的每一个字都有一个主题下标。但从文档聚类的角度来说,LDA 没有一个文档统一的聚类标签,而是每个字都有一个聚类标签,这个就是主题。LDA 每个字都有可能属于不同的类别,每个文档都有可能属于不同的类别。在大量的迭代后,主题分布和字分布都比较稳定也比较好了,LDA 模型收敛。 % A, U1 r8 t5 K* ]1 F) o 3 y* Y' S/ w; R& ]+ P+ D/ L% r A7 a4 Y; c5 A; T
+ n$ Z' F! p9 j# Y3 U5 X7 k; U: ` j
三、LDA 的参数 N' F- D7 V) k; n5 z. I4 g4 c2 D
αα :表示 document-topic 密度, αα 越高,文档包含的主题更多,反之包含的主题更少* |' |! X3 `# q0 [2 @) C* {
- \9 I* i& t, a z
ββ :表示 topic-word 密度, ββ 越高,主题包含的单词更多,反之包含的单词更少 3 ^* H0 o/ l! q" O# U1 ]# @8 c- Z. v$ ^$ g; p) s: h
主题数量:主题数量从语料中抽取得到,使用 Kullback Leibler Divergence Score 可以获取最好的主题数量。8 h3 H+ m* g: e4 |
U5 ~/ U2 |$ f' R
主题词数:组成一个主题所需要的词的数量。这些词的数量通常根据需求得到,如果说需求是抽取特征或者关键词,那么主题词数比较少,如果是抽取概念或者论点,那么主题词数比较多。) `# i- y5 z0 `: U4 _4 h
8 C; k% @7 P- Q* o
迭代次数:使得 LDA 算法收敛的最大迭代次数7 `8 L# @3 b1 @/ g- x
8 H7 _4 x4 t' s8 _$ ^1 a . H8 h8 {# y1 Q $ [! f- I8 r, V0 h7 n# H9 L8 ^8 s- i四、Running in Python$ I" j, j6 ]+ ?7 Y6 ]
准备文档集合 6 j/ N' m4 J5 P% d; Gdoc1 = "Sugar is bad to consume. My sister likes to have sugar, but not my father."( i& X& @, {" R
doc2 = "My father spends a lot of time driving my sister around to dance practice."0 x9 c( y& k8 `( ^* c
doc3 = "Doctors suggest that driving may cause increased stress and blood pressure."$ X- V9 V- |8 N2 K# r# I. L& O" P
doc4 = "Sometimes I feel pressure to perform well at school, but my father never seems to drive my sister to do better.", T8 b" T' C( b2 Z
doc5 = "Health experts say that Sugar is not good for your lifestyle.": u5 }# C& [' ^2 K
0 H! f% _; g2 B+ C A$ W) n# 整合文档数据4 w4 _8 `4 j/ E; j0 i7 f) x' ?
doc_complete = [doc1, doc2, doc3, doc4, doc5]0 w2 p1 d6 T F9 m$ r$ r: h
, j% g' T0 O* i% L9 E+ f$ z
数据清洗和预处理 & Q: B7 }. @* M0 B2 C1 Q! O% z数据清洗对于任何文本挖掘任务来说都非常重要,在这个任务中,移除标点符号,停用词和标准化语料库(Lemmatizer,对于英文,将词归元)。* Z/ P% e$ Q2 q. o' M( H
' Y0 [$ V: V F- A2 a3 w
from nltk import stopwords 8 N5 _% ~; y( M; nfrom nltk.stem.wordnet import WordNetLemmatizer # H. U' m" ~% y0 P" U+ Wimport string ' g4 j6 n1 B% Z. h2 G : R/ A) y% g# z- b2 [stop = set(stopwords.words('english')) j8 `! d7 Q0 @
exclude = set(string.punctuation)2 O7 q" |% q; @3 A
lemma = WordNetLemmatizer() / f# |* m- A. n. b @( f5 [7 T2 w4 m# K; w4 w8 g8 T' k
def clean(doc): 1 n; R S( q3 P/ W: }8 ~ stop_free = " ".join([i for i in doc.lower().split() if i not in stop])+ ^. d+ M0 D9 O( c( o& V
punc_free = ''.join(ch for ch in stop_free if ch not in exclude)- t- A& C5 J4 D- F7 N1 n: y
normalized = " ".join(lemma.lemmatize(word) for word in punc_free.split()) * O$ Q( F2 g8 T! u& z: f return normalized 9 d# c* V. S" C# ]% h3 a4 h! R6 a) b. M! b
doc_clean = [clean(doc).split() for doc in doc_complete] 8 \2 |5 f6 ?- Z% e j* C) y$ d- o5 |! N: M准备 Document - Term 矩阵 # f: g2 ?; Y4 r( N r; V语料是由所有的文档组成的,要运行数学模型,将语料转化为矩阵来表达是比较好的方式。LDA 模型在整个 DT 矩阵中寻找重复的词语模式。Python 提供了许多很好的库来进行文本挖掘任务,“genism” 是处理文本数据比较好的库。下面的代码掩饰如何转换语料为 Document - Term 矩阵:) [! x% @6 J3 p4 \1 @( |
# y, f0 t6 {3 s! J: K7 {$ T2 l- `
import genism3 r: P: y$ S' X3 I' O; F' k
from gensim import corpora * n% }5 J1 H7 O/ Q4 A7 n8 _; Y( @ s4 ?6 U. v6 B$ p9 I
# 创建语料的词语词典,每个单独的词语都会被赋予一个索引 ! |' g9 }* A1 v$ {dictionary = corpora.Dictionary(doc_clean) 2 u; b, l: I( z/ I, z/ K ! j0 {1 y9 P7 O, Y X! m- K# 使用上面的词典,将转换文档列表(语料)变成 DT 矩阵 ; M* u" N2 v8 _/ ^+ ]& ^) Tdoc_term_matrix = [dictionary.doc2bow(doc) for doc in doc_clean] ' |0 f; }0 r+ V' b! S6 u$ \# \' M, S6 w+ @- b' Y
构建 LDA 模型 - P, m5 [5 S- C, [- x/ d- H; c5 ?创建一个 LDA 对象,使用 DT 矩阵进行训练。训练需要上面的一些超参数,gensim 模块允许 LDA 模型从训练语料中进行估计,并且从新的文档中获得对主题分布的推断。 - Q9 H! Y( ]. D8 ~* Q4 S6 d1 F 9 g4 H2 M6 x0 {9 o! H# 使用 gensim 来创建 LDA 模型对象 ( n9 `9 i% y# h% OLda = genism.models.ldamodel.LdaModel- P. |( Y4 Z" G; ?