用Golang寫一個搜尋引擎(0x05)--- 文字相關性排序

吳YH堅發表於2017-01-16

上面我們已經說過了一些倒排索引的東西,並且也知道了如何來實現一個倒排索引完成檢索功能,那麼檢索完了以後如何排序呢,這一篇簡單的說一下倒排索引的文字相關性排序,因為排序實在是太複雜了,我們這裡就說說文字的相關性排序,而且是最簡單的TD-IDF排序,之後有機會可以再說說整個搜尋的排序演算法有些什麼。

文字相關性排序

首先明白幾個概念:

  • Term,分詞以後最小的單位,比如用Golang寫一個搜尋引擎,分詞以後就是golang一個搜尋引擎,那麼每一個詞就是一個Term。
  • TF(Term Frequency),Term在文章中出現的頻率,就是當前term在文章中出現的頻率,就是term次數/總term數,比如上文中的搜尋引擎這個term的TF就是1/5,TF越高那麼這篇文章中的這個詞就越重要。
  • DF(Document Frequency),文件頻率,就是某個Term在總文件中出現的頻率,比如總共有100個文件,其中搜尋引擎這個term在10個文件中出現了,那麼他的IDF就是5/100=0.5。
  • IDF(Inverse Document Frequency),逆文件頻率,聽名字就知道是和上面的DF是反的,用總文件數除以包含term的文件數,再求對數即可,上面的搜尋引擎的IDF是log(100/5)

如何在一堆文章中找到包含關鍵詞的文章,倒排索引技術已經幫我們解決了,只要分詞分得準確,那麼找文章沒什麼問題了。問題是找到一堆文章以後怎麼進行排序,讓最重要的文章排在最前面,這裡介紹一下相關性排序。

TF-IDF相關性排序

上面我們看到TF和IDF的概念,TF明顯作用就是表示一個term在文章中的重要程度,TF越高那麼這個詞在文章中的重要程度越明顯,IDF呢,IDF主要用來描述term在整體文章中的重要程度(也就是區分程度),IDF越高,那麼這個term的整體重要性越高,也就是區分度越大,越能體現這個term的重要性。

為什麼用log呢?其實我個人覺得啊,用不用log其實區別沒那麼大,TF-IDF只是一種計算文字相關度的思想,並不是一個有嚴格證明的公式,所以用不用log區別不大,不過從資訊理論的角度看的話,妖人夏農提出的資訊量的公式就是logX的樣子,值越大資訊量就越大,正好可以套在我們這,IDF越大,資訊量也越大。

資訊量是什麼大家可以自己去百度,簡單描述起來就是某一件事情發生的概率的,如果某件事情發生的概率是P,那麼他的資訊量就是 -logP,注意有個負號,比如中國隊男子足球隊和巴西隊男子足球隊打比賽,假設中國隊贏的概率是 0.01(可能高估了),但如果巴西隊贏了,根據公式算出來資訊量幾乎沒有,因為誰都知道巴西會贏,但如果(我是說如果)最後中國隊贏了,那麼資訊量算出來就是巨大的,肯定上各個頭版了,這也和我們的直覺比較一致,在IDF中,就是用的這個公式,不過吧負號放裡面去了,變成了log(1/P),而P就是DF,term在總文件中出現的頻率。

TF和IDF合起來表示這個term的相關性,就是把這兩個值乘起來。

為什麼要把這兩個概念合起來呢,第一個TF已經可以描述term的重要性了,為什麼還要用IDF呢,主要可以解決兩個問題。

  • 去掉高頻詞的噪音,既然IDF可以簡單理解為term的資訊量,那麼它主要就是為了去掉噪聲,也就是去掉那些個資訊量很小的term的影響。比如這個詞,它的TF非常高,但實際上沒什麼含義,但是你一算他的IDF,基本是0,所以如果用TF*IDF的話,結果還是0,可以比較有效的去掉這類通用詞的干擾。
  • 同時IDF還可以更好的區分重要的詞,如果一個term的IDF越高,證明帶這個term的文章的更加能用這個term來表示,這個很好理解,如果一個term只在某一篇文章中出現,那麼這個詞更能代表這篇文章的內容。

最後,多個term聯合檢索的時候,他們的相關性就是每一個term的TF-IDF加起來,

OK,TF-IDF就是這些了,實現的時候,如果是最初做全量索引的話,由於整體文件數是已知的,那每個term的TF-IDF一般是建立索引的時候就把它算好了,檢索的時候按這個一排序就行了,我實現的時候由於沒有全量索引的概念,所以只是在每新增一個文件的時候算好這個文件的TF存起來,檢索的時候通過term倒排召回的文件數來確定IDF的值,實時算出TF-IDF的,如果是非常巨大的文件數量,那麼實時算還是很吃虧的,所以說全量索引還是非常必要的,只是我這沒有完整實現全量索引建立而已,但後面接下來我會說說全量索引如何建立。

詞距

除了TF-IDF來進行相關性排序以外,還有一些其他的文字因素也可以用在排序上,一是term的距離,也就是詞距,如果檢索關鍵詞是小米手機,那麼明顯的,如果一篇文章中這兩個term(小米,手機)挨在一起,比如小米手機是一款很熱門的手機手機應用中有很多關於健康的文章,比如吃小米有什麼好處這兩篇文件,明顯第一篇的相關度比第二篇要高。

所以,為了保持詞距的資訊,我們在儲存倒排的時候還需要將每個term的位置資訊儲存下來,檢索的時候用過這些個位置資訊計算各個詞直接的詞距,從而和TF-IDF合在一起來表述文字相關性。

位置資訊

同時,除了詞距以外,還有一個因素也影響相關度的排序,那就是term的位置,這個也很好理解,如果在標題摘要命中的話明顯應該比在正文中命中term的權重高,一般這種情況是把標題摘要命中的TD-IDF乘以一個係數來擴大影響,從而影響最後的相關度計算結果。

其他模型

除了直接使用TF-IDF以外,現在還有很多其他的文字相關性的排序模型,比如BM25這種以概率為基礎的排序模型,這裡就不展開了,如果大家有興趣,寫完這些篇以後可以專門寫幾篇怎麼排序的,包括文字排序,以及文字之後的重要性排序啊,怎麼離線利用機器學習計算文件重要性來排序之類的,在說排序的時候我們會說一下如何將這些個所有的東西【文字相關性,詞距,位置,重要性,銷量,點選等】合起來進行打分

下面一篇文章會再講講倒排索引儲存的一些我沒有實現的東西,比如索引壓縮之類的,然後會講講如何建立倒排,如果進行增量新增文件,如何進行索引合併。

如果你覺得不錯,歡迎轉發給更多人看到,也歡迎關注我的公眾號,主要聊聊搜尋,推薦,廣告技術,還有瞎扯。。文章會在這裡首先發出來:)掃描或者搜尋微訊號XJJ267或者搜尋西加加語言就行

用Golang寫一個搜尋引擎(0x05)--- 文字相關性排序

相關文章