機器學習基礎——詳解自然語言處理之tf-idf


今天的文章和大家聊聊文本分析當中的一個簡單但又大名鼎鼎的算法——

TF-idf。說起來這個算法是自然語言處理領域的重要算法,但是因為它太有名了,以至於雖然我不是從事NLP領域的,但在面試的時候仍然被問過好幾次,可見這個算法的重要性。


好在算法本身並不困難,雖然從名字上看疑惑重重,但是一旦理解了其中的原理,一切都水到渠成,再也不怕面試的時候想不起來了。廢話不多說,我們進入正題。


算法原理


TF-idf名字的中間用分隔號進行了分割,並且TF和idf都不像是人名,所以它其實是表明了這個算法是由TF和idf兩個部分構成的。我們先來看TF的部分。


TF的解釋


TF的英文全稱是Term Frequency,Frequency很好理解就是頻次、頻率。而這個Term硬翻譯是項的意思,聯繫上下文,它其實是指的文本當中的單詞或者短語。所以結合起來,Term Frequency就是短語的頻率。其實如果你明白了它的意思,剩下的光憑猜測都可以猜測出一個大概。


它的意思很樸素,就是字面意思,即一個單詞在本文當中的重要性和它出現的頻率有關。


這個觀點很直觀,比如我們在網頁搜索”TechFlow“,出來的網站當中通篇連一個”TechFlow“都沒有,顯然這次搜索的質量很差。如果一個網站當中包含的”TechFlow“很多,那說明很有可能搜索正確,這個網站就是我們想要的。


除此之外,它還可以反映單詞的重要程度。如果在同一個文本當中,一個Term的出現頻率比另一個大,那麼一般情況下,顯然它的重要程度也更大。


據說早期的搜索引擎就是用的這個策略,它衡量用戶搜索的關鍵詞在各個網頁文本當中出現的頻率。傾向於將出現頻率高的網頁排在前面,由於排名靠前的網頁能夠獲得大量的流量。所以由於利益的驅動,後來越來越多的網頁傾向於在內容當中嵌入更多的搜索熱詞,以此來獲得更高的排名和更多的流量。相信大家也都有過類似的體會,當我們使用搜索引擎輸入某個關鍵詞,搜索出來的網頁號稱有相關的匹配,但是當我們真正點擊進去卻什麼也沒有發現,或者是滿屏的廣告。


在早期的互聯網當中存在大量這樣的網頁,它們以囊括更多的搜索熱詞為生。以此還衍生出了一個技術工種——SEO,即search engine optimization搜索引擎優化,專門用各種手段來替各大網頁優化搜索引擎當中的排名。


很快搜索引擎的工程師也都發現了這個問題,也正是為了解決這個問題,才引入了IDF的概念。


IDF的概念


IDF的英文是Inverse Document Frequency,即逆文檔頻率。這個概念很難翻譯,也很難直白地解釋,所以往往我們還是使用它的英文縮寫。它表達的意思也很簡單,就是越廣泛存在的Term越不重要,也就是Term的重要性和出現的廣泛性成反比。


舉個例子,最常用的”的“,”了“,”是的“這些單詞肯定廣泛出現在各個文章當中,而像是“搜索”,“機器學習”這些短語會出現的文章可能就要少得多。顯然對於搜索引擎或者是一些其他模型而言,這些出現更少的單詞的參考意義更大,因為往往意味著更加精準的導向。所以IDF可以簡單理解成出現廣泛程度的倒數,它的定義也很簡單:


機器學習基礎——詳解自然語言處理之tf-idf


其中|D|是所有文檔的數量,t_i是第i個短語,|{j:t_i ∈ d_j }|表示包含第i個短語的文檔的數量。為了防止它為0,我們為它加上一個常數1。同樣,我們也可以寫出TF的公式:


機器學習基礎——詳解自然語言處理之tf-idf


分母的TN_t表示文章t當中包含的所有Term的數量,分子TF_i表示Term_i在文檔中的數量。


我們回顧一下這兩個概念可以發現,TF衡量的是短語和文檔的關係,而idf衡量的是短語和所有文檔的關係。也就是說前者衡量的是短語對於某一個具體文檔的重要性,而idf衡量的是短語對於所有文檔的重要性。這兩者有點像是局部和整體的關係,我們將兩者相乘就可以得到一個Term兼容兩者最終得到的重要性,也就是說TF-idf是用來計算短語在某個文檔中重要性的算法


TF-idf的算法也很簡單,我們直接將TF和idf計算得到的取值相乘即可。


算法的原理理解了之後,我們可以自己動手寫一個計算TF-idf的算法,並不複雜,整個過程不超過40行:


機器學習基礎——詳解自然語言處理之tf-idf


其中SimpleTextPreprocessing是我自己開發的一個進行文本預處理的類,包括分詞、去除停用詞以及詞性歸一化等基本操作。這些內容在之前樸素貝葉斯分類的文章當中曾經提到過,感興趣的同學可以點擊下方的鏈接進行查看。


我們來實驗一下代碼:


機器學習基礎——詳解自然語言處理之tf-idf


我們自己創建了一些無意義的文本進行調用,我們計算第一條文本當中go和jurong單詞的重要程度。根據TFidf的定義,go出現在了第一條和第二條文本當中,它出現的次數更多,所以它的idf更小,並且兩者在第一條文本當中出現的詞頻一致,所以應該jurong的TFidf更大。


最後的結果也符合我們預期,jurong的TFidf是0.345,而go的TFidf是0.143。


深度思考


TFidf的原理我們都理解了,代碼也寫出來了,看似圓滿了,但其實有一個關鍵的點被我們忽略了。有一點很奇怪,為什麼我們計算idf的時候需要對擬文本頻率這個值求log呢?雖然從結果上來看求了log之後的結果看起來更加正常,並且分佈也更加合理。但這是結果不是原因,而從原理上來說,這個log出現的原因是什麼呢?


其實在TFidf這個理論出現的早期,並沒有人想過這個問題,可以說是誤打誤撞。後來有大神從香農信息論的角度給與瞭解釋,這一切才完美的自圓其說。


在之前關於交叉熵的推導文章當中,我們曾經討論過,如果存在一個事件A,它包含的信息量是

-log(P(A)),即它發生概率的對數。也就是說發生概率越小的事件,它的信息量越大。這個log的出現是有玄機的,信息論的本質是將信息量化。信息量化的結果是bit,也就是二進制位。我們都知道一個二進制位能夠表示0和1兩個數字,代表了2分量的信息。隨著bit的增多,我們能表示的信息量也在增大,但是信息量不是線性增長的,而是指數增長的。


舉個簡單又經典的例子,32支球隊挺近了世界盃,這其中只有一支球隊能夠獲勝。假設最終獲勝的是法國隊、西班牙隊,我們知道消息的時候並不會驚訝。而如果獲勝的是日本隊,估計所有人會大吃一驚。這背後的原因就和信息量有關,我們都知道雖然從表面上來看32支球隊是平等的,哪一支都有獲勝的可能,但是實際上各個球隊獲勝的概率是不同的。


假設法國隊、西班牙這種勁旅獲勝的概率是1/4,

-log(1/4)=2那麼我們只需要2個bit就可以表示。假設日本隊獲勝的概率是1/128,那麼我們需要7個bit才能表示,顯然後者的信息量大得多。


到這裡,大家也就明白了,我們取對數的本質是計算信息量對應的bit的數量。bit的數量是線性的,信息量是指數級的,也就是說我們將一個指數級的信息量轉化成了線性的bit。對於大多數模型而言,線性的特徵更加容易擬合,這也是TFidf效果出色的本質原因。


最後,我們從信息論的角度解釋一下idf,假設互聯網世界當中所有的文檔有 2^30。現在用戶搜索中美貿易戰,其中包含中國和美國的文檔數量都是 2^14 ,那麼中國和美國這兩個詞包含的信息量就是log(2^30/2^14)=16,而如果包含貿易戰這個詞的文檔數量只有2^6,那麼貿易戰這個詞包含的信息量就是log(2^30/2^6)=24,那麼顯然,貿易戰這個詞的信息量要比中國和美國大得多,那麼它在文檔排序當中起到的作用也就應該更大。


如果你能從信息論的角度對TFidf的原理進行解釋,而不只是簡單地瞭解原理,那我覺得這個知識點才是真正掌握了,那麼當你在面試當中遇到自然也就能遊刃有餘了。


今天的文章就是這些,如果覺得有所收穫,請順手點個關注或者轉發吧,你們的舉手之勞對我來說很重要。


分享到:


相關文章: