题目:从给定的语料库中均匀抽取 200 个段落(每个段落大于 500 个词), 每个段落的标签就是对应段落所属的小说。利用 LDA 模型对于文本建模,并把每个段落表示为主题分布后进行分类。验证与分析分类结果。
背景:
一篇文档可以包含多个主题,所以会有主题分布这个概率. 可以这么理解一篇文章的生成:先以一定的概率选取某个主题,然后再以一定的概率选取该主题下的某个词,不断重复这两步,直到完成整个文档。**LDA 解决的问题就是,分析给定的一篇文章都有什么主题,每个主题出现的占比大小是多少。**LDA 对短文本的主题分类效果比较差。
从宏观上来看,在 LDA 模型中,以 topic 作为中间层,问题可以用如下形式进行表示: P(单词|文档) = P(单词|主题) × P(主题|文档),即 P(w|d) = P(w|t)×P(t|d),其中的 P(单词|文档) 是已知的,直接从给定的文档中就可以计算得出的,P(单词|主题)和 P(主题|文档)是用来进行拟合的,调整这两个分布,直至符合单词文档的实际分布。也就是说,最终需要求的是 P(单词|主题)和P(主题|文档)这两个分布,而真正对文档主题分布有用的,是 P(主题|文档)这个分布,即 P(t|d)。
LDA 模型生成文档步骤:
在 LDA 模型中,一篇文档的生成方式如下:
-
从迪利克雷分布α中取样生成文档 i 主题分布θi;
-
从主题的多项式分布θi 中取样生成文档i 第j 个词的主题 zi,j;
-
从迪利克雷分布β中取样生成主题 zi,j 对应的词语分布Φzi,j;
-
从词语的多项式分布Φzi,j 中采样最终生成词语 wi,j。
题解
解题路线:
我们将全部 16 篇金庸小说作为语料进行 LDA 模型构建,在 16 篇小说中随机均匀抽取长度不小于 500 的 248 个片段,将每个小说名作为片段标签。利用已经构筑好的 LDA 模型得到片段的主题分布。利用片段的主题分布与标签,划分训练集和测试集,选择 SVM 模型进行分类任务。
LDA 模型构建:
首先进行数据预处理。将原 16 篇文档整理合并,按行划分,形成合并文档process.txt,接着进行分词并去掉停用词,分词这里使用 jieba 工具包,停用词表这里使用GitHub - goto456/stopwords: 中文常用停用词表(哈工大停用词表、百度停用词表等) 中的中文停用词表。
接着利用 gensim 进行 LDA 模型构建。读取文本数据 59423 条, 利用corpora.Dictionary() 进行词典构建, 利用 doc2bow() 计算文本向量。 利用gensim.models.TfidfModel()进行模型构建,选择构建的主题数量为 20,最后利用gensim.models.ldamodel()进行模型的训练。训练参数设置如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BISRO59A-1685494692606)(20512318.png)]
空间限制,这里列举某 4 个主题前 10 个主要词概率分布。
主题1 | 孩儿 | 解药 | 门派 | 西域 | 二哥 | 道人 | 经脉 | 食指 | 不该 | 真气 |
---|---|---|---|---|---|---|---|---|---|---|
主题1 | 0.01356217 | 0.00776301 | 0.00596932 | 0.00596429 | 0.00588608 | 0.00504877 | 0.00492453 | 0.00473175 | 0.00459261 | 0.00418687 |
主题2 | 少林 | 少林寺 | 大师 | 方丈 | 弟子 | 赵钱孙 | 下山 | 敝 | 糊涂 | 蒙古 |
主题2 | 0.01163895 | 0.01116088 | 0.01039371 | 0.00825011 | 0.00789407 | 0.00647364 | 0.00500936 | 0.0044;57 | 0.00439796 | 0.00437793 |
主题3 | 师兄 | 刀法 | 较量 | 恶 | 落下 | 打听 | 苍老 | 惊讶 | 不忍 | 岩石 |
主题3 | 0.02051514 | 0.01500916 | 0.00787329 | 0.00592551 | 0.00577093 | 0.00554486 | 0.00523014 | 0.00493958 | 0.00479358 | 0.00467229 |
主题4 | 壁上 | 各派 | 老前辈 | 崖 | 毒 | 伯伯 | 人均 | 殿下 | 奔到 | 六个 |
主题4 | 0.00882462 | 0.00580436 | 0.00528313 | 0.00514028 | 0.00456607 | 0.00445411 | 0.00406776 | 0.00405323 | 0.00402811 | 0.00400323 |
片段主题分布生成:
由于 LDA 对短文本的主题分类效果比较差。所以摘取的片段不宜过短。我们首先将各个文档分别进行预处理,再进行长段落选择。发现并不是每一个小说都有足够数量的 500 词以上的段落,因此我们将部分小说段落进行合并。共摘取 248 个片段。代码如下
quanji_x=[] quanji_y=[] we10=0 for we in range(len(ttext0)): jj=0 for we1 in range(len(ttext0[we])):#每一篇 temp=[] if len(jieba.lcut(ttext0[we][we1])) >=40 and we1>we10+40:#某一段大于 10 for juju in range(40): cd_100=[] cd_99=jieba.lcut(ttext0[we][we1+juju]) for dd in cd_99: if dd not in stop_words: cd_100.append(dd) temp+=cd_100 assert len(temp)>700 quanji_x.append(temp) quanji_y.append(we) jj+=1 if jj>30:#大于 20 就下一篇 we10 = we1 break
所得到的 248 个片段,其中片段最短长度为 50795,最短为 884,平均长度为。可见我们每个片段的词数较多,主题特征相应应该也较多,应该更加有利于后续分类的效果。
依建立片段的词袋模型并输入 LDA 模型得到各个片段的主题分布概率值。将其作为特征值,将片段的所属小说名作为标签,得到总数据集。数据集特征以及标签见 Test.xlsx
SVM 分类:
进行数据集随机划分,代码如下:
X_train, X_test, y_train, y_test = model_selection.train_test_split(X, y, test_size = 0.2, random_state = 1234)
用 sklearn 的 SVM 包进行训练预测,由于测试集合数量不多,这里不一一按照类别进行召回率与精确率计算,直接按照预测正确除以总数计算分类效果。测试集标签以及最终预测结果如下:
1.在 test_size=0.2,random_state=1234 时候,准确率为 96%;
2.在 test_size=0.1,random_state=4231 时候,准确率为 100%。
结论分析:
结果验证了所构建 LDA 模型的有效性,通过对于片段的主题分布进行分类, 可以较为准确的识别出属于哪一篇小说。
通过本次实验,我掌握了构建 LDA 模型的流程,更加熟练得掌握了文档的数据预处理,并且可以利用LDA 模型进行一些简单的文字片段分类任务。
代码汇总:
详细工程文档见。这里展示文档功能划分:
-
pre.py 文档预处理
-
exp3.py 片段生成与 LDA 模型构建以及数据集主题分布生成
-
svm.py 支持向量机分类
?? 资源
大小: 10.8MB
?? 资源下载:https://download.csdn.net/download/s1t16/87503854
注:如当前文章或代码侵犯了您的权益,请私信作者删除!