:::

發掘文件中的主題:Weka分群應用於文本探勘 / Discover the Topic of Text Collection: Text Mining based on Weks's Clustering

5-Weka_Discover_the_Topic_of_Text.png

在以文字撰寫的大量文件中發掘這些文件所共同描述的主題,這類型的技術稱之爲「主題塑模」(Topic Modeling),而資料探勘中的分群就是實作主題塑模的其中一種做法。本篇就來說明如何用開放原始碼資料探勘工具Weka中的層疊式K平均法分群演算法來找出文件中的主題。


主題模型 / Topic Model

在2017年出版的「機器學習與資料探勘百科全書」(Encyclopedia of Machine Learning and Data Mining)中,Chen與Liu對主題模型的定義如下:

主題模型(topic model)是一種統計的機器學習方法(statistical machine learning methods),用於發掘文件集合(document collection)或語料庫(corpus)中的潛在語義主題(latent semantic topics)。

在傳統的主題模型中,一份文件會被塑模成潛在主題的混合體(an admixture of latent topics),而這些主題則是由許多字詞構成的機率分佈(probability distribution)。不同主題會以特定條件產生各種文字,而主題又是來自於某個預先定義分佈中的抽樣結果。換句話說,主題模型就是呈現「高共現」(higher-order co-occurrence)的結果,例如某些字詞時常會在不同情境下一起共同出現(co-occur)。

當文件數量夠大、能夠代表足夠信度的共現統計時,主題模型的表現通常會很不錯。

2019-0705-082324.png

(圖片來源:pixabay)

舉例來說,如果某些文件一直提到「sport」(運動)和「player」(球員),那麼那些文件可能是在談論「運動」這項主題。另一方面,如果文件一直提到「rain」(下雨)和「cloud」(雲),那這些文件可能是在談論「天氣」。

主題模型的建立,也就是主題塑模,這是一種探索性的研究方法,適合用於研究者對這些文件不甚瞭解、沒有預期假設的時候使用。透過主題塑模所找出的主題,可以幫助研究者瞭解這些文件大致上是在說什麼內容,建構研究者的見解(insight)。

舉一個常見的例子來說,以訪談爲主的質性研究通常會產生大量的逐字稿,但是每位受訪者的逐字稿到底在說些什麼,通常得要研究者花上大量時間閱讀和來回比對,甚至還需要用些神祕的第六感或直覺來找出受訪者之間隱涵的模式:

「B受訪者提到的事情......好像A受訪者也有提到過......對了,C受訪者也有講過類似的話!他們之間一定有什麼關聯!」

這種直覺通常需要大量經驗累積,新手研究者通常很難一蹴而成。這時候,我們可以換個角度,透過資料探勘的技術來幫我們發掘出這些訪談資料的隱含模式,也就是本文所要談的主題塑模。

主題塑模的相關技術 / Technologies of topic modeling

實作主題塑模的方法很多,最流行的作法是隱含狄利克雷分佈(latent Dirichlet allocation, LDA)以及機率隱含語義分析(pLSA),但也有些研究採用了分群來實作主題塑模。

隱含狄利克雷分佈 / Latent Dirichlet allocation (LDA)

2019-0705-083844.png

(圖片的資料來源:Lettier)

LDA是一種「生成性的機率模型」(generative probabilistic model),其中狄利克雷分佈是指每個主題中對文件和字詞的分佈。LDA適用於轉換成詞袋模型(bag-of-words model)的文件集合,使用者必須先指定三個參數:

  • 主題數量:主題數量是由使用者指定。
  • alpha:影響狄利克雷分佈,alpha越小,各主題越分散。alpha越大,各主題越混雜。
  • beta:影響各主題包含的字詞數量。beta越小,每個主題可能包含的字詞越少。beta越大,每個主題可能包含的字詞越大。

2019-0705-085525.png

(圖片的資料來源:Lettier)

最後LDA可以產生每個主題對應的字詞與文件的機率分佈表格,機率越大的字詞和文件,越能代表該主題。

許多人在介紹LDA的時候都會從公式開始講起,不過實務使用時,大概就是只要知道上面這些元件就能開始用它了。

分群 / Clustering

Fig._2._Galaxy.png

(圖片來源:Whiting, M. A., & Cramer, N. (2002). WebThemeTM: Understanding Web Information through Visual Analytics. In I. Horrocks & J. Hendler (Eds.), The Semantic Web — ISWC 2002 (pp. 460-468). Springer Berlin Heidelberg.)

在LDA之前,主題塑模的研究用的是分群的作法。以WebTheme的研究來說,他會先計算文件與文件之間的相似度,建構出文件與文件相似度的二維矩陣,然後再將之繪製於二維地圖上,呈現上圖視覺化的結果,該研究將這種文本視覺化技術稱為文件星系(galaxy)。星系較為密集的數個文件即成為群集(cluster),而計算群集中心文件的標題中最常出現的字詞,就是該群集的主題。

2019-07-05_211025.jpg

(圖片來源:Lin, X., Soergel, D., & Marchionini, G. (1991). A Self-organizing Semantic Map for Information Retrieval. In Proceedings of the 14th Annual International ACM SIGIR Conference on Research and Development in Information Retrieval (pp. 262–269). New York, NY, USA: ACM. doi:10.1145/122860.122887)

另一個用於主題塑模早期的作法是自我組織語義地圖(self-organizing semantic map),這是第一個將類神經網路的分群演算法自我組織地圖(self-organizing maps, SOM)應用於文件分析上的研究。SOM是由使用者先指定一個網子,網子上有長乘以寬的格子(node)數量。接下來再用類神經網路的迭代法,讓網子去學習由文件轉換成的詞袋模型的特性,然後再讓網子轉換成二維地圖呈現。當網子中的格子與格子之間時常共同出現相同單字時,格子與格子就會合併為一個區域(area)。最後區域上標示該區域最常出現的單字,就完成了這個自我組織語義地圖。

開放原始碼的資料探勘工具:Weka / Weka: an open source data mining tool

weka_logo_2_.gif

(圖片來源:Weka鳥的動圖)

Weka是紐西蘭懷卡托大學機器學習實驗室(Machine Learning Group at the University of Waikato)發展的資料探勘工具,以GUN授權發佈,是資料探勘領域中重要的自由軟體。雖然跟現在的Python、R相比,Weka的演算法只有少數經典的資料探勘演算法。但經典永不退流行,Weka仍然能幫我們從文本中發掘有用的見解(insight)。

安裝層疊式K平均分群演算法 / Install Cascade K-Means package 

2019-0708-045638.png

Weka預設並沒有本文所要使用的層疊式K平均分群法(Cascade K-Means),但我們可以透過Weka提供的「Package Manager」(套件管理器)來安裝額外的套件。層疊式K平均分群法的名稱為「cascadeKMeans」,請參考「Weka下載與套件安裝教學」這篇的作法來安裝。

讀取中文設定 / Chinese compatibility: UTF-8 configuration

2019-0708-050427.png

在Windows的環境中特別要注意亂碼的問題。由於在Windows中安裝的Weka並非以萬國碼UTF執行,這會讓讀取中文的時候變成亂碼。

要解決這個問題,必須要修改Weka的設定檔,設定「fileEncoding=utf-8」,讓Java以UTF-8編碼運作。詳細做法請參考我之前寫的「如何在Weka中顯示中文:調整檔案編碼為UTF8」這篇。

2019-0708-050839.png

當然,你要讀取的檔案也必須是要以UTF-8 (Unicode)編碼才行。這點Windows底下使用Microsoft Excel的使用者必須格外注意,最好不要使用Excel來進行以下操作。這是因為Excel預設使用的是Big-5編碼,用它開啟以UTF-8編碼的檔案時,常常會變成亂碼。

推薦作法:使用Linux跟LibreOffice Calc / Recommendation: Use Linux and LibreOffice Calc

2019-0629-100354.png

如果不使用Excel的話,那還有什麼選擇呢?有的,你還可以使用LibreOffice Calc和Google試算表。除此之外,在Linux、Mac作業系統中使用的Weka,預設也是以UTF-8編碼運作,不需要特別再調整設定。

有興趣的使用者可以來體驗看看:

以下操作中,只會使用Google試算表與LibreOffice Calc。想要一起操作的讀者,可以先把LibreOffice Calc準備好哦。


操作步驟說明 / Guide

以下我們操作分成四大步驟:

  1. 文件資料集:下載練習用的資料來源。
  2. 資料前處理 斷詞:使用線上中文斷詞工具Jieba-JS來進行斷詞前處理。
  3. Weka分群操作:使用Weka進行分群。
  4. 解讀Weka分群結果:用Weka分群結果分析器來看看分群結果找出的主題。

Step 1. 文件資料集 / Data set:  Abstracts of academic papers collection

2019-0708-082342.png

本次的資料集是從臺灣博碩士論文加值系統中取出90篇論文的摘要彙集而成。這些論文所談論的研究議題各不相同,我們能從這裡面歸納出一些主題嗎?就讓我們以這個資料集作爲例子,用Weka的分群演算法來實作主題塑模吧。

1-1. 建立副本 / Make a copy

2019-0708-082410.png

喔,對了。這份資料集是作爲示範使用,並不開放大家直接編輯。想要實作的話,請開啓上面的「建立副本」連結,它會協助你建立一份副本到你的Google雲端硬碟。請用這份副本來練習吧。


Step 2. 資料前處理:斷詞 / Preprocess: Tokenization

2019-0708-054104.png

(圖片來源:非結構化資料分析:文本分類)

Weka判斷主題的方式是以「關鍵字」爲基本單位,「關鍵字」可能是「單字」或「單詞」。在中文自然語言處理中,從一連串的文字中分辨出有意義的「單字」或「單詞」,這一項發展已久的研究議題稱之爲「斷詞處理」(tokenization)。

以下面這段文字爲例子:

籃球運動是以投籃上籃和扣籃為中心的對抗性室內體育運動之一

經過斷詞處理成爲單字或單詞之後,再以空格合併,就會呈現下面的樣貌:

籃球運動 投籃 上籃 扣籃 中心 對抗性 室內 體育運動 之一

你可以注意到這個斷詞處理並不是只靠單純的規則,背後需要應用複雜的演算法和大量的專家詞典。Weka裡面只能做到以空格為基礎的斷詞處理,大多時候僅能用於英文文本。如果要做中文的斷詞處理,那我們得仰賴其他工具,其中一個知名的工具就是結巴(Jieba)。還好,我之前已經做了結巴線上版本:線上中文斷詞工具Jieba-JS

2-1. 中文線上斷詞工具:Jieba-JS / Online Chinese Tokenization Tool: Jieba-JS

2019-0709-091319.png

(圖片來源:線上中文斷詞工具Jieba-JS)

有了這個結巴線上斷詞工具,我們要進行中文斷詞處理就變得簡單許多了。

Jieba-JS

操作說明 / Tutorial 

讓我們來看看要怎麼使用Jieba-JS。

2019-0709-091425.png

先開啓結巴工具,等待工具初始化完成。

2019-0709-091455.png

再按下Stop Words旁邊的「example」按鈕載入停用詞表。

放在停用詞表中的字詞將不會出現在斷詞結果中。預設的停用詞表中包含了標點符號、單一數字、以及常見的正體中文、簡體中文以及英文單字。也就是說,設定了預設停用詞表之後,斷詞結果就不會標點符號、單一數字、以及各種常見的中英文單字。

2019-0708-082508.png

再來回到試算表,我們來複製這些摘要。因為Google試算表一次能複製、貼上的資料量有限,所以我們得要分批操作。一次大概處理30份左右的文件是沒問題的,讓我們選取這些摘要,然後複製它吧。

2019-0709-091611.png

回到結巴工具,讓我們在「Raw Text」欄位貼上剛剛複製的摘要,然後按下「開始斷詞」按鈕。

2019-0709-091652.png

在「Processed Text」欄位就會出現斷詞結果。我們再按右上角的複製按鈕來複製斷詞結果。

2019-0708-082616.png

接著再將斷詞處理完的結果貼回資料表中「tokenization」這一欄,我們就完成了一部分斷詞處理。

2019-0708-082659.png

再來重複幾次操作,讓每個摘要都經過斷詞處理。

2019-0708-082725.png

然後我們要選取「tokenization」這一欄,並且複製它。

2019-0708-082808.png

切換到「tokenization」工作表。這是我預先建立好的工作表,只是一個空的資料表。

2019-0708-082832.png

把「tokenization」欄位資料貼上過去,這樣就完成了。

2-2. 斷詞結果 / Result of tokenization

2019-0708-083105.png

這份檔案是已經斷詞處理完的結果,讓我們來看看斷詞前與斷詞後有什麼變化。

第一份論文的摘要原本如下:

本論文主要針對各種標準時間協定與時間同步架構介紹其原理,進而瞭解跨系統間交互通訊協定及精確度誤差。利用量測儀器取得各通訊間的誤差,並重新建構設計誤差容許值,使不同系統能進一步取得時間同步且誤差值視為可接受且不影響精度,亦可提供系統在分析與維護時的後端有效數據。

在經過斷詞處理後,第二份論文的摘要變成如下結果:

論文 主要 標準 時間 協定 時間 同步 架構 介紹 原理 瞭解 跨 系統 間 交互 通訊 協定 精確度 誤差 利用 量 測儀 器 取得 通訊 間 誤差 重新 建構 設計 誤差 容許 值 不同 系統 進一步 取得 時間 同步 誤差值 視 接受 影響 精度 亦可 提供 系統 分析 維護 端 有效 數據

你可以注意到,原本是一連串的中文字,現在在單字與單詞之間加入了空格,就很像是英文以空格隔開單字一樣。這樣子Weka就有辦法分辨這些論文中的關鍵字,進而以這些關鍵字找出主題了。

除此之外,標點符號「,」、「。」被拿掉了,一些常見的字詞,像是「本」、「針對」、「各種」也被拿掉了。這樣子這些字詞就不會被當作是主題的一部分,減少解讀主題時的困擾。

2-3. 下載CSV檔案 / Download in CSV Format

接下來我們要把Google試算表上的資料下載到本機端,這樣才能讓Weka讀取。或著你也可以點選下面的連結下載:

2019-0708-091720.png

將Google試算表下載成CSV格式的作法很簡單,請按左上角的「File」,然後進入「Download as」,按下「Comma-separated values (.csv, current sheet)」即可。

2019-07-08_211931.png

瀏覽器就會跳出另存新檔選擇位置的對話視窗。

2019-07-08_212145.png

請記得這個CSV檔案的存放位置。接下來我們會以這個CSV檔案來進行Weka的分群操作喔。


Step 3. Weka分群操作 / Clustering in Weka

資料準備好之後,接下來就是輪到Weka上場了。

3-1. 開啓探索器 / Open Weka's Explorer

2019-0708-092306.png

開啓Weka之後,一開始會出現上圖的選單。我們要選擇其中的「Explorer」,開啓初學者專用的探索器。

2019-07-08_212601.png

這就是Weka的探索器,接著讓我進行下一步。

3-2. 讀取檔案 / Load CSV

2019-0708-092712.png

接著按下「Open file...」(開啟檔案),開啓選擇檔案視窗。

2019-0708-092911.png

因爲我們的檔案是CSV格式,所要我們要在「Files of Type:」(檔案類型)選擇「CSV data files (*.csv)」(CSV資料檔案(*.csv))。

2019-0708-093047.png

接著移動到CSV所在的檔案位置,選擇CSV檔案,開啓它。

2019-07-08_213114.png

我們成功讀取檔案了,這個檔案裡面只有一個變項「tokenization」,那就是我們剛剛設定的斷詞結果。可是我們在進行分群之前,還有一些前處理要進行。

3-3. 類別轉換成字串 / Apply nominal to string

2019-0708-093449.png

在CSV讀取進來的時候,這個欄位的資料類型預設是「Nominal」(類別),但如果要作文本探勘,我們需要把轉換成「String」(字串)。要將「Nominal」轉換成「String」,作法如下:

2019-0708-093549.png

首先按下「Filter」(過濾器)底下的「Choose」(選擇)按鈕。

2019-07-08_213753.png

2019-0708-093708.png

依序進入「weka」 >「filters」 > 「unsupervised」 > 「attribute」 > 「NominalToString」,這個過濾器就是將類別轉換成字串的工具。

2019-0708-093948.png

然後按下「Apply」(套用)。

2019-0708-094017.png

你可以注意到原本是「nominal」(類別)資料類型的欄位已經轉換成「String」(字串),這樣我們就可以進行下一步了。

3-4. 字串的文字向量轉換 / Apply string to word vector

接下來我們要把字串轉換成「文字向量模型」(word vector model)中的「詞袋模型」(bag-of-words model)。一樣是在這個畫面操作。

2019-0708-094351.png

我們要按下「Filter」(過濾器)底下的「Choose」(選擇),然後依序選擇「weka」 >「filters」 > 「unsupervised」 > 「attribute」 > 「StringToWordVector」,這個過濾器就是將字串轉換成文字向量模型的工具。

2019-0708-094542.png

接著我們還要設定「StringToWordVector」過濾器工具。請在粗體字的「StringToWordVector」上面按滑鼠左鍵。

2019-07-08_221125.png

這裡有很多值得設定的地方,不過目前我們先不做任何設定,採用預設值的「詞袋」(bag-of-words model)模型即可。按下「OK」離開這個設定畫面。

2019-0708-101334.png

然後按下「Apply」(套用)。

2019-07-08_221400.png

你可以注意到下面資料的欄位突然變出了很多欄,這就是Weka把字串以空格拆開,然後轉換成「該文件是否包含該文字」的詞袋模型。

2019-0708-101624.png

舉例來說,第一份論文摘要裡面有包含「時間」,那它在「時間」欄位的數值就是1,表示該文件有包含「時間」這個詞彙。另一方面,第一份論文摘要裡面沒有包含「晶片」,那它在「晶片」欄位的數值就是0,表示該文件沒有包含「晶片」這個詞彙。

將文件轉換成文字向量模型之後,我們終於可以進入分群這個步驟了。讓我們繼續作下去吧。

3-5. 層疊式K平均分群 / Apply Cascade K-Means cluster

2019-0708-101845.png

套用分群的作法一樣要按下「Filter」(過濾器)底下的「Choose」(選擇),然後依序選擇「weka」 >「filters」 > 「unsupervised」 > 「attribute」 > 「AddCluster」。這是套用分群演算法的過濾器工具。

2019-0708-102248.png

這邊我們要進一步設定「AddCluster」。

2019-0708-102933.png

我們要設定分群演算法,請按下clusterer旁邊的「Choose」(選擇)。

2019-0708-103100.png

選擇「CascadeSimpleKMeans」(層疊式K平均分群法)。

2019-0708-103142.png

再來我們要設定CascadeSimpleKMeans,請滑鼠左鍵點下粗體字的「CascadeSimpleKMeans」。

2019-0708-103344.png

這邊我們主要是要設定「maxNumClusters」跟「minNumClusters」。層疊式K平均分群法是計算不同分群數量的CH指標 (Caliński-Harabasz),該指標反映了分群的品質,也就是兼顧「群內差異越小」以及「群外差異越大」。指標的計算方式請參考「自動決定最佳化分群數量:層疊K平均分群法」這篇。層疊式K平均分群法會找出CH指標最大的分群數量,也就是最佳的分群數目。其中「minNumClusters」就是最少可能的分群數量,預設值爲2,「maxNumClusters」就是最多可能的分群數量,預設值爲10。照預設的設定,層疊式K平均分群演算法就會從2到10個分群中,找出一個最佳的分群數量出來作爲最後的結果。

實務上,我會建議把分群數量設爲3至7群之間。太少不好解釋、太多你也很難解釋。因此我們在這裡要把「minNumClusters」設爲3、「maxNumClusters」設爲7。

設定完成後,就再按下「OK」確定,離開CascadeSimpleKMeans跟AddCluster的設定視窗。

2019-0708-104140.png

回到探索器的主視窗,我們再來要設定「class」的欄位。請將「Visualize All」左邊的下拉式選單設成「No class」。

2019-0708-104317.png

到這邊為止,我們已經設定好層疊式K平均分群法了,接下來按下「Apply」(套用)按鈕,開始進行分群的群集分析。

2019-0708-104430.png

分群完成後,你可以注意到資料的最後多出了一個欄位「cluster」,這就是分群結果。在右邊的類別欄位分佈中可以看到,層疊式K平均法把這些文件分成了4個分群,各自命名為cluster1、cluster2、cluster3以及cluster4。從Count (個數)欄位可以看到,最多的是cluster4,總共有46筆資料;最少的是cluster1,僅有7筆資料。

3-6. 儲存成CSV檔案 / Save as CSV format

2019-0708-105053.png

接著我們要把分群完的結果儲存成CSV格式的檔案。請按下右上角的「Save...」。

2019-0708-105422.png

在「Files of Type:」(檔案類型)的欄位裡,選擇「CSV file: comma separated files (*.csv)」。

2019-0708-105523.png

決定好要儲存的資料夾和檔案名稱後,按下「Save」。

2019-0708-105605.png

這就是我們的分群結果了。雖然它是個CSV檔案,不過因為欄位太多了,我們沒辦法用一般的試算表工具開啟,需要藉助特殊的分析工具來檢視分群結果。


Step 4. 解讀Weka分群結果 / Analyze the result of cluster

2019-0708-112540.png

接下來的操作讓我們回到瀏覽器,以下將使用「Weka分群結果分析器」來看看分群結果。

Weka分群結果分析器 / Weka cluster result analyzer

4-1. 載入分群結果 / Read Cluster Result

2019-0709-024015.png

請在「選擇檔案」處選擇剛剛Weka分群完的CSV檔案。

2019-0709-024155.png

下面就會看到剛剛分群完的結果已經載入了。剛剛層疊式K平均法分群結果找出了4個分群,數量個別是:

  • 第1群:7筆
  • 第2群:18筆
  • 第3群:19筆
  • 第4群:46筆

這表示這四個分群可能各自代表了4個不同的主題,不過這些主題內容到底是什麼呢?讓我們繼續看下去。

4-2. 下載詞頻統計結果 / Download word frequency statistic of cluster

2019-0709-024300.png

在表頭的各群名稱上有個「下載」按鈕,點它可以下載該群的詞頻統計結果。讓我們一一來看各群前20個最常出現的詞彙是什麼吧。

第一群的主題 / Topic from cluster 1

第一群僅有7筆資料,數量最少。最常出現的詞彙前20名如下,其中數字表示該詞彙有出現的文件筆數:

7 研究
7 護理人員
7 資料
6 之間
6 使用
6 內容
6 分析
6 取樣
6 問卷
6 對象
6 平均
6 建議
6 探討
6 教育
6 方法
6 相關
6 結構式
6 評估
6 護理
6 進行

因為這些摘要是來自於論文本身,所以「研究」、「資料」這些詞彙應該是每一份摘要都會共同擁有的文件。但這7份中都有提到「護理人員」,而且「護理」和「教育」都在其中6份被提及,而研究方法看起來應該大多採用「問卷法」。

綜合以上來看,這些研究的主題可能是「醫護」。

第二群的主題 / Topic from cluster 2

第二群有18筆資料,最常出現的詞彙前20名如下:

17 文學
15 探討
13 不同
13 作品
13 創作
13 成
13 發展
11 作
11 出
11 論文
8 主要
8 作家
8 價值
8 內容
8 呈現
8 形成
8 影響
8 文化
8 文學作品
8 文本

在18筆摘要中,有17筆都提及了「文學」,也時常提及「作家」、「文化」、「文本」。這些詞彙有著明顯共同的主題,那就是「文學」。

第三群的主題 / Topic from cluster 3

第三群有19筆資料,最常出現的詞彙前20名如下:

19 研究
14 發展
13 分析
13 探討
13 相關
11 作
11 透過
11 進行
10 台
10 工業
10 差異
10 提升
10 方式
10 灣
10 能力
9 出
9 方法
9 產業
7 不足
7 主要

這19筆摘要的主題著重於「工業」與「產業」,因此這個分群的主題可能是在談「工業」。

第四群的主題 / Topic from cluster 3

第四群有46筆資料,數量最多,最常出現的詞彙前20名如下:

21 影響
21 提出
18 性
18 資料
16 問題
16 設計
16 關係
16 需求
14 化
14 建議
13 具有
13 問卷
13 工業
13 應
13 採用
13 提供
13 最後
13 機構
13 環境
13 發現

這46筆摘要提及的詞彙相當發散,看起來也有提到「問卷」和「工業」,不過份數13份,僅佔13/46=28%。而看了下其他詞彙,大多會跟前面第一群和第三群所呈現的主題類似,因此我將這一分群視為「其他」,不給予明確的主題。

4-3. 製作文字雲 / Word cloud

2019-0709-022016.png

前面下載的詞頻統計,可以直接到WordClouds.com中匯入產生文字雲。讓我們來看看怎麼操作。

2019-0709-022318.png

開啟WordClouds.com網頁後,先按下「Word list」按鈕。

2019-0709-022532.png

把詞頻統計貼到文字欄中,按下右下角的「Apply」(套用),再按「Close」(關閉) 關閉對話視窗。

2019-0709-022631.png

雖然下面圖片的文字替換成我們輸入的文字了,不過形狀跟顏色看起來怪怪的。讓我們先來調整形狀,請按下「Shape」按鈕。

2019-0709-022751.png

選擇「圓形」,然後按下「Close」(關閉) 關閉對話視窗。

2019-0709-022921.png

形狀雖然看起來變成比較容易閱讀的圓形了,不過顏色看起來很奇怪。接下來我們來調整顏色,請按下「Theme」。

2019-0709-023041.png

我偏好選擇白底、五種顏色左右的主題顏色。

2019-0709-023149.png

看起來好像比較順眼了,讓我們來吧這個文字雲下載下來。請按下左上角的「File」。

2019-0709-023237.png

選擇「Save as PNG」。

2019-07-09_023302.png

它會先請你輸入一個檔案名稱。輸入完成後再按下「OK」。

2019-07-09_023351.png

這樣就可以將文字雲儲存到你的電腦上。

各分群的文字雲 / Word clouds from clusters

再來我們用這個方法,來看看上述四個分群的文字雲是什麼。

wordcloud.png

上圖就是第一群的詞彙文字雲,有沒有更能看出「醫護」這個主題呢。

wordcloud_1_.png

上圖是第二群的詞彙文字雲,裡面的用詞都能反映出「文學」這個主題。

wordcloud_2_.png

在第三群的詞彙文字雲中,我們又可以看到像是「產業」、「廠」、「競爭力」等詞彙,看來這的確是符合「工業」這個主題呢。

wordcloud_3_.png

再來是第四群的詞彙文字雲。除了「工業」一詞比較明顯之外,其他詞彙看起來都是很常在研究中會使用的普通詞彙,並沒有明顯的主題出現。

4-5. 查看文件所屬分群 / Add cluster to abstract

前述的詞頻統計和文字雲都只是一種「遠讀」(distant reading)的分析法,如果可以的話,我們還是需要回到原始文件上來檢視分析的結果,也就是「近讀」(close reading)。

2019-0709-024551.png

那我們要怎麼取得分群結果呢?請找到上面的「Cluster result」(分群結果),按下右邊的「COPY」,複製分群結果。

2019-0709-024807.png

選擇旁邊一個空的欄,貼上它。

2019-0709-024927.png

這樣就可以看到每一篇摘要對應的分群結果了。

2019-0709-025058.png

我們來看看第二份摘要,它被分成cluster3,也就是「工業」主題。它的摘要第一句話就是「隨著工業4.0 的熱潮正席捲全球之際,智慧化與自動化工廠已蔚然成為各大製造公司建構的必然趨勢。」是不是很符合主題呢?

4-6. 主題 / Topics

透過上述的方法,我們大致上可以在這90份論文摘要中找出三個主題:

  • cluster1 醫護
  • cluster2 文學
  • cluster3 工業

這就是我們最後的結果囉。


延伸應用 / Application

上述使用層疊式K平均分群法所找出的主題中,其實有很多細節可以調整。如果你覺得分群結果不太容易解讀,可以試著調整斷詞規則、不仰賴斷詞規則、文字向量模型、層疊式K平均分群法的設定細項,也許會得到不同的結果。

設定斷詞規則 / Tokenization rules

主題塑模最常見的問題都會在構成主題的關鍵字上。以下說明停用字詞典、斷詞詞典、對應詞典的設定。

停用字詞典 / Stop words

頻繁出現的關鍵字有時候並不是我們想要找出的主題。例如在一堆學術論文的摘要中,「研究」和「資料」這些詞彙必然會很常見,但它不會是我們想要從這些摘要中找到的主題。

2019-0709-032518.png

這時候我們可以在Jieba-JS右下角的「Stop words」裡面,加上我們想要過濾掉的關鍵字,一行一個字。這些字詞不會出現在斷詞結果中,也自然不會成為最後構成主題的關鍵字。

斷詞詞典 / Dictionary

2019-0709-032832.png

另一個問題是,斷詞的結果可能有錯誤。例如「台灣」,在預設的Jieba-JS中會被斷詞處理視為兩個字:「台」以及「灣」。這時候我們可以在下方的「User Dictionary」新增設定:

台灣,9999999,n

這一行設定包含三個欄位,以逗點隔開各個欄位。第一個欄位「台灣」表示要斷詞的詞彙;第二個欄位「999999」表示斷詞的優先權重,值設的越大,越會優先被視為一個詞彙;第三個欄位「n」是詞性標記,我們這篇並沒有用到詞性標記的功能,詳細請看「彙整中文與英文的詞性標註代號:結巴斷詞器與FastTag」這篇的說明。

有了斷詞詞典的設定,「台灣」就不會被斷開來,而成為一個獨立的詞彙「台灣」。

對應詞典 / Word remap

不同的文件可能會在同一件事情上使用不同的用詞,例如「台灣」和「臺灣」就是兩個時常混用的詞彙。Weka並不會事先知道這兩個詞彙是在指同一件事情,因此我們必須要設定對應詞典,將不同的詞彙轉換成同一種詞彙,這樣子Weka在分群的時候就可以知道它們兩個是指同一件事情。

2019-0709-033451.png

要設定對應詞典的方法,請在左下角的「Word Remap」加入一行設定:

台灣,臺灣

這一行設定包含了兩個欄位,以逗點隔開。第一個欄位「台灣」表示要被取代的字詞;第二個欄位「臺灣」表示取代後的字詞。

設定對應詞典後,最後輸出的斷詞結果就不會有「台灣」,而只會有「臺灣」了。

長詞優先的問題 / Drawback of multi-word term first tokenization

2019-01-19_192740.png

(圖片來源:非結構化資料分析:文本分類)

Jieba-JS的斷詞採用了「長詞優先」的規則。舉例來說,如果文中出現了「文學理論」,則這四個字會被優先視為「文學理論」一個詞彙,而不會被當成「文學」以及「理論」兩個詞彙。這樣的缺點在於,Weka會把「文學理論」和「文學」視為兩個不同的詞彙,而不會發現其實「文學理論」裡面也包含了「文學」兩個字。

1.png

(圖片來源:簡單易用的中英文斷詞和詞性標註:Python-Jieba)

為了克服這個問題,我另外以Python-Jieba製作了能夠產生混合模式的斷詞工具。這個工具就可以將「文學理論」斷詞處理後產生「文學理論」、「文學」、「理論」這些結果。有興趣的話,請去看看「簡單易用的中英文斷詞和詞性標註:Python-Jieba」這篇吧。

單純數字的斷詞:N元語法 / Simple sequence analyse: n-gram 

 在中文斷詞成熟之前,大家會採用更簡單、也更確實的斷詞規則:N元語法(n-gram)。這個N表示我們會將連續N的字元作為一個詞彙,最常見的N就是2,又稱為2字詞語法(bigram)。舉例來說,「文學理論」在二字詞語法中會被視為「文學」、「學理」、「理論」三種字詞的組合。儘管二次詞語法並不能找到「文學理論」這樣的長詞,但有時候也可以跳脫既有斷詞規則的框架,找出意料之外的二字詞詞彙。

2019-0709-043902.png

如果要使用N元語法來斷詞,那就請在「開始斷詞」的左邊選項中,選擇「-gram」,並在前面的數字選擇要斷詞的字元長度。

wordcloud.png

使用二字詞語法、文字向量模型設定中「minTermFreq = 3」之後,可以找出4個分群,其中第一個分群結果的文字雲圖片如上。你有發現了什麼嗎?

不同的文字向量模型:詞袋、詞頻到TF-IDF / Configuration of StringToWordVector

2019-07-08_221125_-_.png

在StringToWordVector工具中有許多設定項目,在Weka的StringToWordVector說明中有詳細的解釋。讓我們來看看裡面比較值得一提的內容。

反文件頻率轉換 / IDFTransform 

此關鍵字如果越少出現在其他文件裡面,則表示該關鍵字越罕見,權重越高。轉換公式如下:

fij*log(num of Documents/num of documents containing word i) 

fij是指文字i在第j份文件裡面的頻率。

詞頻轉換 / TFTransform

此關鍵字出現在文件中的頻率,轉換公式如下:

log(1+fij)

fij是指文字i在第j份文件裡面的頻率。

屬性名稱前置詞 / attributeNamePrefix

預設轉換後會以該單字作為屬性名稱,但這可能會造成混淆。例如裡面有個單字叫做「cluster」,那就會跟後面分群結果「cluster」相互衝突。

這時候你可加入前置詞,例如「word_」,而「cluster」詞彙的屬性名稱就會變成「word_cluster」,這樣就不會影響後面的分群結果了。

變成小寫文字 / lowerCaseTokens

原本英文的大小寫文字被視為不同的詞彙,將lowerCasetokens調整成True之後,英文字全部會被調整成小寫。

過濾掉鮮少出現的詞彙 / minTermFreq

預設minTermFreq為1,表示詞彙只要出現1次,就可能會收錄到最後結果。如果文件數量龐大,各種鮮少使用的詞彙可能會變成最後的結果。我們可以試著把minTermFreq調高,僅留下比較常出現的詞彙。舉例來說,將minTermFreq設成3,表示只留下出現3次以上的詞彙。

以文件長度標準化調整 / normalizedDocLength

如果文件中包含的詞彙很多,那該文件會出現的詞彙可能會相當多、同一詞彙中出現的頻率也相當高。如果不想要讓少數比較長的文件影響到你的最後結果,我們可以將normalizedDocLength設定為「Normalize all data」看看。

計算詞頻 / outputWordCounts

在outputWordCounts為False的時候,最後輸出結果只會看文字有沒有出現在該文件中。如果有出現,則是設為1。如果沒有,則設為0。這就是詞袋模型。

如果將outputWordCounts設為True,那最後輸出結果就可以看到該詞彙在文件中的數量。

詞幹處理器 / stemmer

英文的不同時態會有不同的寫法。舉例來說跑步的「run」有「running」、「runs」、「runned」或是「runly」不同形態。詞幹分析(stemming)就是將文字的句尾過濾掉,僅保留該詞彙的詞幹。如果有套用詞幹處理器,那不同形態的「run」都會被還原成「run」。在Weka中,我們可以設定「LovinsStemmer」詞幹分析器,它在很多時候表現的都很好。

保留詞彙數量 / wordsToKeep

2019-0709-082147.png

最後一個欄位設定wordsToKeep是指最後會取出的詞彙數量接近值,預設是1000。在前面二字詞語法中,Weka最後挑選了1053個字,就是受到wordsToKeep的影響。超過這個數量的字詞會被捨棄。

層疊式K平均分群法的設定細項 / Configuration of Cascade K-Means cluster

2019-0709-082345.png

再來要說的是層疊式K平均分群法的設定內容,細節可以在CascadeSimpleKMeans看到,這裡面值得一提的是距離算法和是否使用K平均法++兩個設定。

距離算法 / distanceFunction

層疊式K平均分群法支援兩種距離計算方式:

320px-Manhattan_distance.svg.png

(圖片來源:維基百科)

以兩個黑點為例子,距離的計算方法有兩種:

起始使用K平均法++ / initializeUsingKMeansPlusPlusMethod

initializeUsingKMeansPlusPlusMethod欄位預設是False,你可以把它改成True以啟用K平均法++功能。K平均法++改善了K平均法初始決定種子位址的問題,有效決定分群的起始點,使得分群結果較為穩定、不易受到極端值的影響。關於K平均法++的說明,可以參考維基百科或是「浅入浅出:从Kmeans到Kmeans++」。


結語:不盡人意的結果 / Wrap up: Unacceptable result

這篇介紹了使用Weka中的分群演算法:層疊式K平均分群法來從中文文件中找出主題。除了基本的作法之外,我也說明了對於斷詞規則、文字向量模型、層疊式K平均分群法的一些值得注意的設定。

不過,這樣子就能找出容易理解的主題嗎?

持續探索 / Trial and error

2019-0709-083529.png

上圖是我用二字詞語法,將許多設定都開啟之後,最後分群所得到的結果。第一群cluster1佔了88份文件,cluster2和cluster3都只有1份,這顯然不是一個很好的分群結果。這樣的結果很容易出現在我將文字向量模型StringToWordVector的wordsToKeep設得相當大的時候。也就是,收錄的文字越多,各文件之間看起來就越相近,越難找出文件與文件之間的差異。

這樣的現象應該違背了很多人所信仰的「大數據思維」,資料越多、反而越看不清楚現象本身。在文本分析時,這是很常見的情況。因為我們在使用語言敘述事物時,很多文字本來就會彼此共用。即使我們在講不同的事物,但大部分的文字卻都相同,這就讓Weka難以分辨他們之間的差異。

這時候,用「停用字詞典」來過濾掉那些過於常見的字詞,以及用「對應詞典」來合併多詞一義的狀況,那就變得非常重要。

文本探勘本身比較像是一個探索的過程。我們需要不斷地觀察分析的結果、調整設定、然後再次分析看看,直到出現我們比較容易解釋的結果為止。實務上,我們不會在一開始就得到完美、容易理解的結論,而是需要不斷摸索,直到出現一個可以接受的結果。

為什麼不要用分群找尋主題? / Why not extract topics by clustering

1_tWaaZX75oumVwBMcKN-eHA.png

(圖片來源:Towards Data Science)

最後必須要說明的是,本篇所描述的以分群找尋主題的方法,存在著先天上的缺陷,它用在發掘主題上,並不是一種很好的方法。

K平均法的本質是將文件依其屬性(有提到這個字、沒提到這個字)來將文件歸屬成不同的分群。然而,文件的主題本身往往並不能如此一目瞭然地切割,一份文件可能會有部分內容描述「護理」,但也可能會有部分內容在描述「工業」。K平均法最後只能強制將該文件歸為其中一類,這種就是所謂的「硬分群」(hard-clustering)。

figure_1._the_intuitions_behind_latent_Dirichlet_allocation.png

(圖片來源:Blei, D. M. (2012). Probabilistic Topic Models. Commun. ACM, 55(4), 77–84. doi:10.1145/2133806.2133826)

實務上,我會建議大家使用的是隱含狄利克雷分佈(Latent Dirichlet allocation, LDA)。LDA是以機率分佈的方式呈現構成主題的單字,一份文件會隸屬於多個主題、但是隸屬的程度並不相同。舉例來說,一份論文摘要可能比較偏「護理」,但它同時也有部分「工業」的主題概念,而這的確比較符合我們對文本的認知概念。LDA並不是強硬地將文件切開成不同分群,而是以模糊數學(fuzzy)的機率形式,也就是以「軟分群」(soft-clustering)來描述各個文件和主題。

在Lettier的Your Guide to Latent Dirichlet Allocation後面有對這點做些討論,這篇也是學習LDA的一個很好的起點,有興趣的人可以再深入閱讀、瞭解LDA。

儘管以分群來找出主題的方法並不完美,但是它也是分析非結構文字資料的一種方法,而且Weka只能做到這個而已。如果你只是想要簡單地分析看看這些文件裡面有什麼主題的話,不妨先從這個方法嘗試看看吧。


閒聊 / Off-topic talk

2019-07-09_212104.png

因為我很好奇我到底每次花多久時間在寫這一篇文章,所以這次在Blogger Editor加入了計時功能。結果截至剛剛,我撰寫這篇文章的時間,已經來到了23小時21分。實際上還會更多,這當然,我還在繼續寫啊。

這篇文章的作法我很久以前就知道了,不過直到現在,才好好認真把一連串作法寫下來。最主要是「延伸應用」那邊,我想跟大家說的是,文本探勘有很多背後的參數可以做調整,唯一的「黃金標準」,就在於你能不能解讀這個結果。

為了說明這篇的作法,我又回頭去改了Jieba-JSWeka分群結果分析器。以前還不知道使用MVVM框架的程式碼,寫起來實在是難看到不堪入目,嗚呼哀哉。

2019-07-09_151442.png 2019-07-09_155323.png 2019-07-09_165701_1.png

因為流程一再調整,我有些圖片也必須在修改後重新截取。左邊是Jieba-JS一開始的畫面,到了最右邊又添加了許多功能。因為這寫程式都是我可以自己手動控制,當我覺得難以用文字說明的時候,就會覺得回頭去改程式比較快。畢竟我可能是花三十分鐘幫程式加上一些功能,卻可以省下使用者的更多時間啊。

2019-0709-094726.png

最後就是來講講Blogger Editor的功能。這次改善了大綱瀏覽器,加入了註解提示的功能。這樣我就可以先在筆電上寫下部分草稿,使用註解提示標亮,提醒自己這裡有未完成的內容。然後回到電腦的時候就能把註解改完,補上圖片或連結,這功能做起來真的很深得我心。不過使用的時候又遇到了許多bug,看來離完美之路還有段距離。

2019-07-09_214821.png

此外,我也強化了「插入預設範本」的功能。這個功能變成了一種「剪貼簿」,我可以把想要刪掉、但未來又可能會用到的文字轉換成「預設範本」。如果寫著寫著真的又會用到,那就可以從「插入預設範本」裡面插入。我本來以為這功能做完應該不太容易用到,沒想到這篇寫到後面,我真的會回頭使用之前寫的草稿,還好有把它加入到「預設範本」呢。

加入這兩個功能之後,Blogger Editor越來越順手了呢。不過撰寫過程中又發現了許多Blogger Editor的bug跟需要加入的功能,我可能先把這些功能完成,再來繼續寫下一篇吧,希望每次寫Blog都能越來越好用。


那這次對於使用Weka的分群來實作文本探勘中的主題分析就寫到這裡了。那寫到最後,我有些問題想問問大家:

  • 你有處理非結構化文字資料的經驗嗎?像是訪談、逐字稿、文字記錄。
  • 你都是怎麼找尋這些文件的主題呢?
  • 找出這些文件的主題後,你會用來做什麼呢?

歡迎在下面的留言處跟我們分享你的想法。大家的意見是我繼續分享的動力喔!如果你覺得我這篇閒聊算是有趣的話,請幫我在AddThis分享工具按讚、將這篇分享到Facebook等社群媒體吧!

感謝你的耐心閱讀,我是布丁,讓我們下一篇見。

總共5 則留言 ( 我要發問 , 隱藏留言 顯示留言 )

  1. To Scott Chu,

    他原始的問題在這串:
    http://blog.pulipuli.info/2005/12/blogger_113544406852218769.html#c1537326887520775055

    因為這個問題的內容顯然是跟這篇主題模型有關,所以我把回答放在這篇來講。

    --------

    問題1:對於50年的大型資料,是否有批次5年之類的建立主題模型的方法?

    我沒有研究過大型資料建立主題模型的方法,但這方面的關鍵字通常會包括「incremental」增量,意思是可以處理逐步增加資料的技術。

    我在資料庫中找到了一篇2019刊登在Knowledge-Based Systems的期刊論文
    https://www.sciencedirect.com/science/article/pii/S0950705119302874

    Wang, M., Yang, L., Yan, J., Zhang, J., Zhou, J., & Xia, P. (2019). Topic model with incremental vocabulary based on Belief Propagation. Knowledge-Based Systems, 182, 104812. doi:10.1016/j.knosys.2019.06.020
    這篇論文提出了兩個方法ivLDA-PMI跟ivLDA-Perp,看起來是可以解決增量資料的問題
    不過Google搜尋了一下,我找不到相關工具

    --------

    問題2:能不能每次跑5年的結果再來合併?這樣準嗎?

    在談到怎麽樣算準的這件事情之前,我們要先來定義什麼叫做「主題模型很準」Laura Dietz的投影片介紹了數學評估的Held-out Log Likelihood與Perplexity、人為評估的HUMAN-IN-THE-LOOP、分類評估的CLASSIFICATION TEST SET、以及依照你的任務自行定義的評估方式http://topicmodels.info/ckling/tmt/part4.pdf  

    我還沒深入研究,所以不太確定要怎麼進行主題模型的評估在這件事情還沒確定之前,也很難說到底每跑5年再來合併這件事情是否叫做「準」
    --------

    問題3:主題塑模有工具嗎?

    我只有用Weka的分群來跑個簡單的主題塑模過。http://blog.pulipuli.info/2019/07/weka-discover-topic-of-text-collection.html 
    實務運作上,大家普遍採用的技術是LDA。
    我之前在介紹時有用過LDA-Based Topic Modelling in Javascript來做說明https://awaisathar.github.io/lda.js/  
    不過它只是個簡單的應用,也沒辦法處理過大的資料

    應該還可以找得到更簡單使用的工具就是
    但我就沒研究了
    必須要注意的是,對中文來說,主題建模之前需要進行斷詞。大部分主題建模工具都是以空格作為判斷單詞的依據。
    --------

    問題4:50年的資料會跑很久很久嗎?
    我不確定50年裡面到底有多少的文字量,如果可以的話,請用資料檔案的大小來問這個問題。主題建模的效率會受到資料量、採用的演算法、使用的程式語言、機器運算能力的影響。
    我對主題塑模的實務經驗不多,所以很難回答什麼樣的情況才是「很久很久」不過因為LDA的計算量並不是很大,對主題塑模這個任務來說,通常不會很困難吧
    要試試看才知道了

    回覆刪除
  2. 感謝,任何回覆都有幫助。

    回覆刪除
  3. 您好:
    我是政大圖檔所的學生,在使用Weka的時候操作到步驟4-2. 下載詞頻統計結果時,點選表頭各群名稱上的「下載」按鈕,下載後的txt檔是空的,txt檔裡面沒有任何東西,請問是怎麼回事呢?

    回覆刪除
    回覆
    1. 您好,

      由於現在事務繁雜,我可能近兩年都無法處理這個問題。
      https://github.com/pulipulichen/Weka-Cluster-Result-Analyzer
      建議您fork專案來debug,可能比較快。
      可以的話改完後記得開pull request,其他人會感激你的貢獻。

      刪除