自然语言处理之 LDA 主题模型

话题模型

 

话题模型是为发现文档集合中的 话题 而开发出来的一种统计方法。常见的话题模型有LSA、PLSA、LDA,其中LDA(Latent Dirichlet Allocation)是表现最好的话题模型。LDA也被称为三层贝叶斯概率模型,包含词语、话题和文档三层结构。我们认为一篇文章的产生是服从概率分布的,即每个词都是通过“以一定概率选择了某个话题,并从这个话题中以一定的概率选择了某个词语”。

 

LatentDirichletAllocation

 

在sklearn.decomposition.LatentDirichletAllocation提供了LDA的实现,LatentDirichletAllocation常用的需要设置的参数包括:

 

n_topics: 文档集中隐藏的话题数目K。

 

random_state: 随机状态码,保证每次程序运行都能得到相同的随机,使得每次程序之间可以比较运行效果。

 

LatentDirichletAllocation实际上还有很多参数可供选择,具体可以参考sklearn的文档学习,本文只提供基本参数的学习。

 

实验数据

 

下面我们准备了四段文本,分别存放在 test1.txt, test2.txt, test3.txt 和 test4.txt 。我们打开看看这四段文本的内容:

 

test1.txt

 

“红色联合”对“四·二八兵团”总部大楼的攻击已持续了两天,他们的旗帜在大楼周围躁动地飘扬着,仿佛渴望干柴的火种。“红色联合”的指挥官心急如焚,他并不惧怕大楼的守卫者,那二百多名“四·二八”战士,与诞生于l966年初、经历过大检阅和大串联的“红色联合”相比要稚嫩许多。他怕的是大楼中那十几个大铁炉子,里面塞满了烈性炸药,用电雷管串联起来,他看不到它们,但能感觉到它们磁石般的存在,开关一合,玉石俱焚,而“四·二八”的那些小红卫兵们是有这个精神力量的。比起已经在风雨中成熟了许多的第一代红卫兵,新生的造反派们像火炭上的狼群,除了疯狂还是疯狂。

 

test2.txt

 

大楼顶上出现了一个娇小的身影,那个美丽的女孩子挥动着一面“四·二八”的大旗,她的出现立刻招来了一阵杂乱的枪声,射击的武器五花八门,有陈旧的美式卡宾枪、捷克式机枪和三八大盖,也有崭新的制式步枪和冲锋枪——后者是在“八月社论”发表之后从军队中偷抢来的(注:1967年8月《红旗》杂志发表“揪军内一小撮”的社论,使冲击军区、抢夺军队枪支弹药的事件愈演愈烈,全国范围的武斗也进入高·潮。)

 

test3.txt

 

话说天下大势,分久必合,合久必分。周末七国分争,并入于秦。及秦灭之后,楚、汉分争,又并入于汉。汉朝自高祖斩白蛇而起义,一统天下,后来光武中兴,传至献帝,遂分为三国。推其致乱之由,殆始于桓、灵二帝。桓帝禁锢善类,崇信宦官。及桓帝崩,灵帝即位,大将军窦武、太傅陈蕃共相辅佐。时有宦官曹节等弄权,窦武、陈蕃谋诛之,机事不密,反为所害,中涓自此愈横。

 

test4.txt

 

时巨鹿郡有兄弟三人,一名张角,一名张宝,一名张梁。那张角本是个不第秀才,因入山采药,遇一老人,碧眼童颜,手执藜杖,唤角至一洞中,以天书三卷授之,曰:“此名《太平要术》,汝得之,当代天宣化,普救世人;若萌异心,必获恶报。”角拜问姓名。老人曰:“吾乃南华老仙也。”言讫,化阵清风而去。角得此书,晓夜攻习,能呼风唤雨,号为“太平道人”。中平元年正月内,疫气流行,张角散施符水,为人治病,自称“大贤良师”。

 

LDA分析步骤:

 

 

读取数据,并分词

 

去除停用词

 

构建Tfidf矩阵,每一行代表一个test的文档,每一列代表一个词语的tfidf值

 

LDA分析(fit和transform),输出结果

 

 

实验

 

1.读取数据与分词

 

实验数据存放在data文件夹中,test1.txt, test2.txt, test3.txt和test4.txt。

 

import jieba
filepaths = ['data/test1.txt', 'data/test2.txt', 'data/test3.txt', 'data/test4.txt']
docs = [open(f).read() for f in filepaths]
docs = [jieba.lcut(doc)
        for doc in docs]
docs

 

2.去除停止词

 

实际操作中需要自己构建停用词表,然后剔除掉这些无意义的词语,在本文中去停止词操作比较简单粗暴了点,只保留词语长度大于1的。

 

docs = [[w 
         for w in doc 
         if len(w)>1]
         for doc in docs]
#sklearn默认分析的语言是英文,我们要组织成类似英文那样以空格间隔的语言形式。
#corpus现在是一个列表,列表中有四个字符串。
#每个字符串就是一个文档
corpus = [' '.join(doc) 
          for doc in docs]
corpus

 

运行

 

['红色 联合 二八 兵团 总部 大楼 攻击 持续 两天 他们 旗帜 大楼 周围 躁动 飘扬 仿佛 渴望 干柴 火种 红色 联合 指挥官 心急如焚 惧怕 大楼 守卫者 二百多名 二八 战士 诞生 l966 年初 经历 过大 检阅 大串联 红色 联合 相比 稚嫩 许多 大楼 十几个 大铁 炉子 里面 塞满 烈性 炸药 用电 雷管 串联 起来 看不到 它们 感觉 它们 磁石 般的 存在 开关 一合 玉石俱焚 二八 那些 红卫兵 这个 精神力量 比起 已经 风雨 成熟 许多 第一代 红卫兵 新生 造反派 火炭 狼群 除了 疯狂 还是 疯狂',
 '大楼 顶上 出现 一个 娇小 身影 那个 美丽 女孩子 挥动 一面 二八 大旗 出现 立刻 招来 一阵 杂乱 枪声 射击 武器 五花八门 陈旧 美式 卡宾枪 捷克 机枪 八大 崭新 制式 步枪 冲锋枪 后者 八月 社论 发表 之后 军队 中偷 抢来 1967 红旗 杂志 发表 军内 一小撮 社论 冲击 军区 抢夺 军队 枪支弹药 事件 愈演愈烈 全国 范围 武斗 进入 连同 那些 梭标 大刀 冷兵器 构成 一部 浓缩 近现代史 二八 前面 多次 玩过 这个 游戏 楼顶上 出来 除了 挥舞 旗帜 有时 喇叭筒 口号 向下 传单 每次 他们 弹雨 全身而退 自己 挣到 崇高 荣誉 这次 出来 女孩儿 显然 相信 自己 还有 那样 幸运 挥舞 战旗 挥动 自己 燃烧 青春 敌人 火焰 化为灰烬 理想 世界 明天 沸腾 热血 诞生 陶醉 鲜红 灿烂 梦幻 直到 一颗 步枪 子弹 洞穿 胸膛 十五岁 少女 胸膛 那幺 柔嫩 那颗 子弹 穿过 基本上 没有 减速 身后 空中 发出 一声 年轻 红卫兵 旗帜 一起 楼顶 落下 轻盈 身体 落得 甚至 旗帜 还慢 仿佛 小鸟 眷恋着 天空',
 '巨鹿郡 兄弟 三人 一名 张角 一名 张宝 一名 张梁 张角本 秀才 因入 采药 遇一 老人 碧眼 童颜 手执 唤角 一洞 天书 三卷 此名 太平 要术 汝得 当代 宣化 救世 若萌 异心 必获 恶报 角拜 姓名 老人 南华 老仙 化阵 清风 角得 此书 晓夜 攻习 呼风唤雨 太平 道人 中平 元年 正月 疫气 流行 张角 散施 符水 治病 自称 贤良 角有 徒弟 五百余 云游四方 能书符 念咒 次后 徒众 日多 角乃立 三十六方 大方 万余 六七千 立渠帅 称为 将军 讹言 苍天 已死 黄天 当立 甲子 天下 大吉 令人 各以 白土 甲子 二字于 家中 大门 豫八州 家家 侍奉 贤良 张角 名字 角遣 其党 马元义 金帛 结交 封谞 以为 内应 二弟 商议 难得 民心 民心 已顺 乘势 天下 诚为 可惜 一面 私造 黄旗 约期 一面 弟子 唐周 书报 封谞 唐周 乃径 告变 帝召 大将军 何进 调兵 马元义 次收 封谞 一干人 下狱 张角 闻知 事露 星夜 举兵 自称 天公 将军 张宝称 地公 将军 张梁 人公 将军 申言 于众 今汉运 大圣 人出 皆宜 顺天 以乐 太平 四方 百姓 黄巾 张角 反者 四五十万 贼势 浩大 官军 望风而靡 何进 奏帝 火速 各处 备御 讨贼 立功 一面 中郎将 卢植 皇甫嵩 各引 精兵 三路 讨之',
 '天下 大势 分久必合 合久必分 周末 分争 并入 秦灭 之后 分争 并入 于汉 汉朝 高祖 白蛇 起义 一统天下 后来 光武 中兴 传至 献帝 分为 三国 推其致 始于 二帝 桓帝 禁锢 善类 崇信 宦官 及桓帝 灵帝 即位 大将军 窦武 太傅陈 辅佐 时有 宦官 曹节 弄权 窦武 陈蕃 机事不密 反为 所害 自此 愈横 建宁 二年 四月 帝御 温德殿 升座 殿角 狂风 骤起 只见 一条 青蛇 梁上 下来 蟠于 椅上 帝惊 左右 急救 入宫 百官 俱奔避 须臾 不见 忽然 大雷 大雨 加以 冰雹 落到 半夜 方止 房屋 无数 建宁 四年 二月 洛阳 地震 海水 泛溢 沿海居民 大浪 卷入 元年 雌鸡化雄 六月 十余丈 飞入 温德殿 七月 有虹 现于 玉堂 五原 山岸 崩裂 种种 不祥 非止 一端 帝下 群臣 灾异 郎蔡邕 以为 鸡化 乃妇 干政之 所致 切直 帝览奏 叹息 因起 更衣 曹节 窃视 宣告 左右 陷邕 放归 田里 后张 赵忠 封谞 曹节 侯览 程旷 夏恽 郭胜十人 朋比为奸 十常侍 帝尊 信张 呼为 阿父 朝政 日非 以致 天下人 心思 盗贼 蜂起']

 

3. 构建Tfidf矩阵

 

每一行代表一个test的文档,每一列代表一个词语的tfidf值。学过的sklearn的都知道fit和transform的意义,如果对tfidf不懂的可以查看咱们之前分享的文章。

 

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.decomposition import LatentDirichletAllocation

tfidf = TfidfVectorizer()
tfidf_matrix = tfidf.fit_transform(corpus)
tfidf_matrix

 

运行

 

<4x496 sparse matrix of type '<class 'numpy.float64'>'
    with 513 stored elements in Compressed Sparse Row format>

 

tfidf_matrix是 4x496 ,即4行496列,其中

 

4行指的是四个文档

 

496列是496个词语(也就是语料中一共出现了496个词语)

 

4. LDA分析(fit和transform)

 

同上,这里也分为fit和transform,由于我们有预先的知识,知道这四个文档来源于三国和三体,所以话题数K天然的等于2,即 n_topics=2

 

由于LDA属于聚类分析的一种,而聚类分析过程中会随机初始化,为了保证你也能得到与大邓一样的运行结果,我设置了random_state=123456。当然设置成别的数字也可以,这里的random_state相当于口令,咱们两个口令一致才能得到相同的答案。如果你换了random_state,那幺咱们两个得到的结果可能会有出入。

 

lda = LatentDirichletAllocation(n_topics=2,
                                random_state=123456)
docres = lda.fit_transform(tfidf_matrix)
docres

 

运行

 

array([[0.91159844, 0.08840156],
       [0.93385048, 0.06614952],
       [0.06859599, 0.93140401],
       [0.06916256, 0.93083744]])

 

得到的结果是 4*2 的矩阵。行表示文档,列表示话题。我们将第一列认定为话题1,第二列认定为话题2

 

test1.txt 对应着[0.91159844, 0.08840156], 属于话题1
test2.txt 对应着[0.93385048, 0.06614952], 属于话题1
test3.txt 对应着[0.06859599, 0.93140401], 属于话题2
test4.txt 对应着[0.06916256, 0.93083744], 属于话题2

 

矩阵中的值是隶属于某一话题的概率,比如test1.txt隶属于话题1的概率为0.91159844,隶属于话题2的概率为0.08840156,所以我们选择最大的值所属的概率。最终判断test1.txt是话题1.

 

大家都明白文言文与现代文区别是很大的,test1.txt和test2.txt是现代文,而test3.txt和test4.txt是文言文,而sklearn也将这四个文本准确的分为两类。

发表评论

电子邮件地址不会被公开。 必填项已用*标注