1. 前言
推薦系統分為兩種,一種是基於使用者的,根據某個使用者的特性推薦一些東西,還有一種是根據內容,推薦一些相似的內容,或者是兩種的結合,任何推薦系統,仔細分析下來,都屬於這兩種情況的組合。
今天我們說一下基於內容推薦中的一個分支,也是使用得比較多的內容推薦方式,那就是基於文字相似性的推薦,我們說文字相似性的計算,文字相似性應用範圍是比較廣的:
- 普通的閱讀文章,底下的相關文章推薦可以用
- 論文查重也可以用
- 過濾相似度很高的新聞,或者網頁去重
本系列我們會寫三篇。
- 前兩篇是模型化,分為上和下,這兩篇是重點,開篇會用說人話的方式說說計算文字相似性的一些思想和套路,對文字相似性有個感性的瞭解,然後會把人話變成數學化的東西,只有數學化了才能計算,才有計算機能做的文字相似性,當然不會出現大量數學公式,只會有一些數學概念。
- 第三篇是工程化,這篇是非重點,會介紹一下相關的工程的工具包或者程式碼片段,相當於區域性實戰吧,沒有理解第一篇說的直接看這篇沒什麼含義。
2. 直觀理解
假如我們有以下這麼些篇文件
- 用Golang寫一個搜尋引擎
- 搜尋引擎的實現
- 推薦系統的技術要點
- 常用的推薦演算法總結
- 廣告系統是一個搜尋引擎和推薦引擎的組合
- 計算廣告中都有哪些數學原理
有個一個小朋友,他叫小明,但是他還在上學前班,你讓他來說這些文章中哪幾篇比較相似,他現在字都認不全,更別說理解這些文章中的概念了,如果他特別聰明,那麼他很可能說1和5比較相似,因為都有個長得一樣的東西一個搜尋引擎。
又過了一些年,小明已經讀初中了,你再讓他來看哪幾篇比較相似,他可能會告訴你1和2比較相似,然後和5也比較相似,因為他現在已經學會了主謂賓定狀補的語法,知道第一條的主要表述的是搜尋引擎,第二篇主要表述的也是搜尋引擎,第五篇雖然主要不是說的搜尋引擎,但賓語的定語也是搜尋引擎,也是相關的。所以會給出1和2相似,5和他們也比較相似。
再過一些年,小明已經大學畢業了,學的就是計算機專業,這時候你再來看,他會給出6個都比較相似,因為他已經知道了搜尋,推薦,廣告三個領域的基礎技術都差不多,如果對一個感興趣,那麼對另外的主題也會比較感興趣,只不過相似性有高有低而已。
上面的三個階段,實際上也是文字相似性計算髮展的三個階段,從最開始的字面的匹配相似,到第二階段的詞彙的匹配相似,再到第三階段的語義的相似,我們一個一個來說說每個階段使用的數學方法和原理,每個階段都會有數學原理,但我們對數學公式不做深入討論,感興趣的可以自己查閱具體的數學原理。
下面,我們再用計算機和數學的思想來看看計算機如何在上述三個階段中進行文字相似性的計算的。
4. 前期準備
在開始三個階段之前,我們先準備一些必要的知識。
4.1 分詞
分詞也叫切詞,因為文件的最小單位是詞,所以我們預設都是討論分詞過的情況,為了方便,我們把每個詞都分配一個唯一id,我們叫這個詞的token。後面出現token這個概念,就是表示切詞後的唯一id
4.2 詞袋模型
維基百科解釋 :Bag-of-words model是個在自然語言處理和資訊檢索下被簡化的表達模型。此模型下,像是句子或是檔案這樣的文字可以用一個袋子裝著這些詞的方式表現,這種表現方式不考慮文法以及詞的順序。
通俗的說就是把一個文件分詞得到的一堆token放到一個袋子裡,用這個袋子來表示這個文件,這是一種簡化的文字描述方法。
5. 學前班階段
學前班階段也叫直接計算相似的階段,我們其實不關心這篇文章到底講什麼,用計算機的理解就是,分詞完成以後,我們找到一種方法,來計算各個token集合之間的相似性就行了。
5.1 JaccardSimilarity方法
分詞以後,我們得到的一堆token,按照學前班的小明的思想,找到兩兩之間相似性即可,JaccardSimilarity方法可以滿足這個條件,JaccardSimilarity說起來非常簡單,容易實現,實際上就是兩個集合的交集除以兩個集合的並集,所得的就是兩個集合的相似度,直觀的看就是下面這個圖。
數學表示式是:
很明顯,我們可以很容易的把上面的那幾個文件兩兩進行上述計算,然後得到每兩個文件的相似性,再一排,就知道每個文件和其他每個文件的相似性了。
即便新來一個文件,按照上面的公式計算一下,就知道它和每個文件的相似性了,完全沒有難度,當然,你會發現算出來真的就像個學前班的學生弄出來的,完全沒有可用性。
6. 初中階段
學前班階段實在是太Low了,我們看看初中階段都出現了一些什麼新東西?
6.1 數學化
要將表達意思的文字變成可計算相似度的東西,首先,必須將文字數字化,並且數字化以後還能保留文字的一些基本資訊,只有數字化以後才有可計算性,只有保留了基本資訊,這個可計算性才有可信度。
線性代數給我們提供了一個數學工具叫向量,向量看上去特別簡單,就是一串數字,別看它看上去非常簡單,但卻是非常強大的數學工具,有多強大呢?我們從側面來說說,我們知道無論哪個程式語言,都有一個最基本的資料結構,是內嵌在語言中的,那就是陣列,而陣列就是向量,陣列有多強大不用我說了吧?誰敢說他沒用過?它都已經強大到我們感覺不到他的強大了,就像空氣一樣,重要到我們不覺得他重要了(北京除外,呵呵)。
如果我們能將一個文字變成一個向量,那麼我們就將一篇複雜的文章變成了一個可以用陣列描述的數學概念了。
囉嗦了這麼多,如果有一個向量了會怎麼樣?再往上一步,線性代數還給了我們一個概念,就是空間,任何向量都可以表示為某一個空間上的一個點。
所以說,先有了文字,文字變成了向量,再有了空間,向量變成了空間的點,那麼我們通過求兩個點之間的距離,就求得了兩個文件的相似性。
至此,數學化完成了,文字相似性的計算就變成了空間中兩個點的距離的計算,就像下圖一樣。
6.2 向量化
6.2.1 最簡單的向量化
我們先來看看如何進行向量化,前期準備部分我們已經說了,每個詞都可以表示為一個唯一的token,那麼最簡單的向量化,我們拿這個token來向量化,比如下面兩個文件,每個詞用一個id表示(搜尋引擎這個詞重複出現了,所以id一樣,都是5)
文件內容 | token集合 |
---|---|
用/Golang/寫/一個/搜尋引擎/ | 1,2,3,4,5 |
搜尋引擎/的/實現/ | 5,6,7 |
這兩個向量不一樣長,不好對映到同一個空間中,於是我們這麼處理一下,編號1到7為所有的token,用陣列的下標表示,如果這個編號上有詞,那麼設為1,否則設為0,這樣一來,兩個文件向量化以後就變成了
用Golang寫一個搜尋引擎 ===> [1,1,1,1,1,0,0]
搜尋引擎的實現 ===> [0,0,0,0,1,1,1]複製程式碼
這樣,兩個文件就都向量化了,雖然這種向量化是最簡單的,但不管怎樣,我們至少把文字變成了數學符號了。
6.2.2 TF-IDF向量化
文字處理中,還有一種非常常見的向量化方法,就是TF-IDF方法,關於TF-IDF方法,可以參見我之前的一篇文章,已經說得比較清楚了,這裡就不贅述了,可以點選連結開啟看。
總之,通過TF-IDF的向量化方法,我們可以將每個詞向量化成一個表示權重的小數,而不是上面的0,1向量了,它已經帶有了文字的資訊了,通過TF-IDF計算,兩個文件向量化以後就變成了下面這樣
用Golang寫一個搜尋引擎 ===> [0.5, 0.8, 0.2, 0.15, 0.9, 0, 0]
搜尋引擎的實現 ===> [0, 0, 0, 0, 0.8, 0.4, 0.3]複製程式碼
這樣向量化以後,每個詞都帶上了TF-IDF資訊了,而TF-IDF的作用就是保留詞在文件中的權重資訊,這就相當於保留了文字的資訊,於是我們通過token的概念和TF-IDF方法,就把一個文字向量化了,並且向量化完了以後還保留了文字本身的資訊,每一個向量就是一個前面提到的詞袋。
6.3 向量空間模型
向量化完了以後,需要提供一個空間來進行計算,我們把這個叫做向量空間(VSM),這沒啥好說的,比如向量是一個二維向量,那麼空間就是一個平面,如果是個三維向量,那麼空間就是一個立體空間,上文中的向量是一個7維向量,那麼空間就是一個七維空間了。
這樣,每一篇文件向量化以後都是一個7維向量,都可以表述為這個向量空間中的一個點了。
6.4 向量相似度計算
有了向量空間和向量本身了,計算兩個向量的相似度就簡單了,一般有兩種方法
6.4.1 歐式距離
不是說每個向量就是這個空間中的一個點麼?那麼相似性就是直接計算這兩個點的歐式距離,歐式距離公式初中就學了哦
把上面那兩個向量用這個距離公式一帶入,就求出兩篇文件的相似度了。
6.4.2 餘弦相似度距離
除了歐式距離,還有一種方法求相似度,就是求兩個向量之間的夾角,這個叫餘弦相似性,這也是初中數學的內容,不過初中我們學的是二維向量,如果是N維呢?是一樣的,假設兩個向量是A和B,那麼公式是,n表示維度
照樣帶入,就能求出兩個文件相似度了。
7. 中學畢業
至此,文字相似性計算的最基本的概念和模型都介紹完了,中學已經畢業了,你可以按照上面的方法自己試著計算計算文件的相似性,應該不會太離譜,後面一篇會介紹一些更加高階的東西,但是整體的思想不會有太大的變化,還是向量化文件,然後計算向量間的相似度來表述為文字之間的相似度。
這篇我們看到的東西都還是淺層的文字相似性計算,但是其實一個TF-IDF向量化模型,一個餘弦相似性夾角計算已經可以處理一大部分的文字相似性計算了,而且效果還湊合吧,但後面出來的各種語義模型才是文字推薦的未來。
歡迎關注我的公眾號,主要聊聊搜尋,推薦,廣告技術,還有瞎扯。。文章會在這裡首先發出來:)掃描或者搜尋微訊號XJJ267或者搜尋西加加語言就行