淺談文字探勘 - 轉換非結構化文字

我們在分析時,都習慣將資料整理成Tidy Data,以便我們建模來解釋或是預測所關注的事情。但在整理成Tidy Data之前,這些資料基本上都已經是結構化的。所以當我們試圖去分析文字、影像這種非結構化資料時,第一個會碰到的困難點就是如何將這些資料變成我們熟悉的結構化數據。凡通則必有例外,尤其是牽涉到人的時候,那大概只有例外這件事是通則了。與人貼身相關的語言就更不用說了,要能從千變萬化的語言中提煉出「結構化」的型態本身就不是一件容易的事。尤其《Ethnologue: Languages of the World》指稱語言在這世界上起碼有7,102種,即便是同一種語言隨時間、地點的不同也都可能各自發展,就像「擦子」跟「擦布」之類的。

那麼在提取結構化的文字資料之前,可能得先問問文字探勘想要做到的事情是什麼?最基本的不外乎就是從一段文字或一篇文章中,找到他真正想要表達的事情。我們可以看看下面的句子:

我想在這裡表達的是,我過去學了很多東西,但我現在想要分享…欸…等等,我想要分享什麼?喔!對了!是那個嘛!就是文字探勘真的很有意思哦!你可以去學一下!

先不要火大XD,我知道這句話很多贅字,讓人摸不著你到底想幹嘛。但這句話最重要的其實只有一句話,就是「文字探勘很有意思」。也就是說,只要我們能將這句話具代表性的詞彙標記出來,我們就能大略知道這句話到底想表達的意思是什麼。(雖然也是有很多話不明所以啦!)

那麼首先在文字探勘中,最首要的就是把字切出來。上面那段話我們可以切成下面這個樣子:

“我” “想” “在” “這裡” “表達” “的” “是” “我” “過去” “學” “了” “很多” “東西” “但” “我” “現在” “想” “要” “分享” “欸” “等等” “我” “想” “要” “分享” “什麼” “喔” “對了” “是” “那個” “嘛” “就” “是” “文字探勘” “真的” “很” “有意思” “哦” “你” “可以” “去” “學” “一下”

將這些字按照出現次數排列之後,就可以形成以下表格:

詞彙 次數
3
分享 2
2
一下 1
什麼 1
文字 1
1
有意思 1
那個 1
東西 1
表達 1
1
很多 1
真的 1
文字探勘 1
1
現在 1
這裡 1
1
過去 1
對了 1

依「想」跟「分享」出現的頻率,就可以知道這段話到底有多想分享東西給別人了。不過仔細看會發現,我們剛剛認為最重要的「文字探勘」卻被排在相當後面。這段話若單純用次數來挖掘意義,就只會知道他想分享東西而已。所以關鍵在於,次數雖可以挖掘出一定的代表性,卻不見得能表達出整句話真正的含意。因此,另一個用來取代次數的方法就出來了,它也是現在搜尋引擎相當常用的方法 - TF-IDF(Term Frequency - Inverse Document Frequency)

TF-IDF

在剛剛的例子中,我們知道「文字探勘」會是這句話的主軸,而不是「對了」、「欸」之類比較沒有意義的字。主要在於「文字探勘」在其他的文章或談話內容中,沒有「對了」或是「欸」這麼頻繁地出現。也因此一旦出現,就很容易成為那句話的焦點。所以我們要將「文字探勘」的重要性標記出來,單看這句話是不夠的。必須跟其他話語或文字做比較,才能知道「文字探勘」真的比較少出現。

假設我們比對了許多文章,將出現次數整理出以下表格:

詞彙 文章一 文章二 文章三
對了 13 17 12
真的 14 17 13
文字探勘 7 0 0

不難發現雖然「文字探勘」在文章一中出現的次數不及其他詞彙,但它跟其他文章比卻具有它的代表性在。順帶一提,這個表格所呈現的形式也就是文字探勘中常會用到的表格型態Term-Document Matrix(TDM) 或是 它的轉置矩陣 Document-Term Matrix(DTM)。

原理

因此,在分析文件時,假設文件當成一向量PP,而其可能出現的詞彙共有N種,則向量就可以表示成 P=<P1,P2,...,PN>P = < P_1, P_2 ,... , P_N >,其中 PiP_i 就是個詞彙在這篇文章 PP 的權重。不過這 PiP_i應該要是什麼東西呢?有些人會用這個詞彙在文章中出現的次數作為權重,這種做法很直觀,但卻有一點不妥,如同剛剛所說,在這裡就不多做解釋。因此,TF-IDF考量詞彙在該文章中出現的頻率TF(Term Frequency),以及詞彙在其他文章中出現的頻率IDF(Inverse Document Frequency)兩部分,TF代表 PiP_iPP 出現的頻率,可以表示成下列式子:

tf(i,j)=ni,jknk,jtf_{(i,j)} = \frac{n_{i,j}}{\sum_kn_{k,j}}

如同我們之前所說,ni,jn_{i,j}代表詞tit_i在文件djd_j出現的次數,而上述公式則代表詞組tit_i跟其他詞組相比後的佔比是多少。而這僅能顯示他在文章中出現的次數,無法顯示這個詞組僅在這篇出現的獨特性。因此,引入了IDF來做考量的因子:

idfi=logDj:tidjidf_i = \log \frac{|D|}{|{j:t_i\in d_j}|}

這個因子是考量總文件數DD除以出現過詞tit_i的文件數所得的商,再取對數。將文件的獨特性考量進來。而同時考量TF-IDF的指標,就出來了:

tfidfi,j=tfi,j×idfitfidf_{i,j} = tf_{i,j} \times idf_i

有了這個指標後,我們就可以利用文字雲的方式,將重要的詞彙呈現出來,也更能顯露出文章的特性。另一方面,在應用上的層面也較為廣泛。像現在的搜尋引擎很多都採用此種權重計算方式。

應用

相似文件以及搜尋引擎

除了找出文章主要闡述的內容外,我們想找有相似主題的文章也可以利用此種方式。我們都學過線性代數,當中的內積很適合拿來作為相似與否的媒介。假設我們把目標文章的詞彙完整轉換成一個向量代表是 p=<p1,p2,...,pn>p = < p_1, p_2, ..., p_n >,比對的文章則是 q=<q1,q2,...,qn>q = < q_1, q_2, ..., q_n >,則可以透過角度大小來判斷兩向量是否接近,因 cosθ=pqpq\cos\theta = \frac{p\cdot q}{\|p\|\|q\|},當 cosθ\cos\theta 越接近1,則代表兩文章越相近。而這種評估方式也被稱作為Cosine Similarity

此種方式也很適合應用在搜尋引擎上,當我們使用倒排索引來紀錄資料,可以輕鬆計算出每份文件中每個詞的TF-IDF指標,作為該文件的向量指標。便可進一步用cosθ\cos\theta來評估文件,並將搜尋的關鍵字作為一向量指標來判定最高相關的文章。

關鍵字判別及文章摘要

除此之外,TF-IDF還可以應用在關鍵字的判定上,只要將該文章TF-IDF最高的前幾名挑出來,就可以自動生成文章的關鍵字詞組。不僅如此,還可應用在文章摘要,將文章內包含重要字詞的句子給挑出來。

其他應用

其實除了單純的意義提取外,這些結果都可以當作建立預測或解釋型模型很好的養分。譬如藉由爬蟲抓取PTT的資料,就可以關聯習慣逛那些文章類型的人會喜歡看什麼電影,藉此應用在電影推薦預測上。又或者是從文章找出企業跟時事的關聯,以作為投資股票的評估等等。在這個資訊爆炸的年代,已經不是只有人家準備好的結構化資料能夠拿來建模了,越孰悉將非結構化資料轉換成有用的資訊,就越能在這變動快速的時代抓緊先機。一起加油吧!

參考資料

  1. 從搜尋引擎到文字探勘
  2. 文字探勘的快思慢想與遐想_Text Mining_Text Analytics_TF-IDF