自然語言處理之 LDA 主題模型
話題模型
話題模型是為發現文件集合中的 話題 而開發出來的一種統計方法。常見的話題模型有LSA、PLSA、LDA,其中LDA(Latent Dirichlet Allocation)是表現最好的話題模型。LDA也被稱為三層貝葉斯概率模型,包含詞語、話題和文件三層結構。我們認為一篇文章的產生是服從概率分佈的,即每個詞都是通過“以一定概率選擇了某個話題,並從這個話題中以一定的概率選擇了某個詞語”。
LatentDirichletAllocation
在sklearn.decomposition.LatentDirichletAllocation提供了LDA的實現,LatentDirichletAllocation常用的需要設定的引數包括:
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也將這四個文字準確的分為兩類。
長按小程式碼 即可獲取本文的jupyter notebeook下載連結
精選文章
ofollow,noindex">現階段“有趣”對我很重要的
360ec25da7cd8&chksm=f1f76d18c680e40e1a891400d8a56c896d3f92a0995922d8a2bddf76475750e8a5b888b49ad8&scene=21#wechat_redirect" target="_blank" rel="nofollow,noindex">文字資料標註工具-YEDDA