這篇就說乙個資訊檢索裡面理解最簡單的乙個東西吧,它就叫做倒排表或者倒排索引。但是這只是個名字,我想大家都知道它是什麼就行了,不必糾結於名稱。先說說倒排表張什麼樣子吧!
倒排表以詞做索引,內容為包含該詞的文件編號。對於上圖可知,文件1、3、5、7、9包含詞"cat",文件2、5、8、10包含詞"dog"。你可能問這麼簡單的東西能幹啥?其實他就是搜尋引擎中的最關鍵的核心資料結構。那麼搜尋引擎如何根據使用者的查詢來找到相關的文件呢?如果使用者查詢「cat」,那麼只要順著cat鏈把文件1、3、5、7、9返回給使用者就行了。如果使用者想得到同時包含「cat」與「dog「的文件怎麼辦?這個過程就類似於我們歸併排序時合併兩個有序段的過程,利用兩個指標分別指向cat鏈的第乙個元素和dog鏈的第乙個元素,之後通過比較兩個指標處文件編號的大小進行相應的移動,找到兩個鏈中共同的文件。整個過程的時間複雜度是線性的。上面介紹的是一種簡化版的倒排表,實際搜尋引擎中使用的倒排表要比這個複雜一些,也有可能使用多個不同的倒排表來完成不同的搜尋任務,但是本質上都差不多。
那麼如何建立這個倒排表呢?其實大概過程很簡單:提出文件中的每乙個詞,並把該文件編號插入到該詞索引的鏈上。這裡的主要問題在於提取詞上,英文文件詞與詞之間是由空格以及標點符號隔開的,但是漢語裡面沒有這麼明顯的分割標誌,所以有一門學問叫做自然語言處理,裡面專門研究了漢語的分詞方法,現在的大多數分詞方法都能夠達到90%多的正確率。
對於邏輯上這麼容易理解倒排表,在實際上實現並不容易。除了分詞外,不容易就不容易在這個倒排表的規模將是相當之大,以至於一台計算機的記憶體空間甚至一台計算機的磁碟空間都不足以存下整個倒排表。實際中的搜尋引擎索引的網頁數目可達到百億,以每個網頁平均1000個詞來計算,每個文件編號按照4位元組整數來儲存,那麼粗略算下來倒排表也至少需要10000000000*1000*4b=40tb的儲存空間,那麼對於怎麼儲存這個倒排表確實是乙個棘手的問題。
解決大資料儲存的形式有兩種,一種是分布式儲存,一種是壓縮。前一種方式很好理解,意思就是一台機器存不下的東西,那麼就把它存在多台機器上,這裡面也需要有一些複雜的技術。當然,如果倒排表儲存在多台機器上,對使用者的請求的處理也就變得複雜了一些。後一種壓縮技術就是把資料的規模變小,用更加緊湊的表現形式對源資料進行表示,達到內容不變但是儲存空間變小的目的,實際中我們常用的壓縮軟體就是這個道理。比如linux下的gzip利用的就是lz77演算法和哈夫曼曼編碼來對任意的二進位制資料進行壓縮的。
分布式儲存本人不太了解,所以這些技術的介紹就得大家自己找找園子裡的牛人的部落格了。而資料壓縮相對比較簡單,本文就介紹一下倒排表的壓縮演算法。有人會說,那用現成的壓縮工具對倒排表壓縮不就可以了嗎?雖然可以減少倒排表的儲存空間,但是這種平時用的壓縮工具壓縮出的資料的訪問效率比較低。
例如:「我是中國人」在gzip壓縮之後,在壓縮資料中找是否有「中」字,你就不得不把所有的資料解壓之後才能得到。如果是在壓縮之後的倒排表中去找乙個文件,那麼不得不把倒排表全部解壓,而這個解壓過程本身就是乙個費時的過程,所以不划算。
現在回到倒排表的壓縮問題上來,解決乙個問題必須理論聯絡實際才能得到令人滿意的效果。
在介紹倒排表資料壓縮演算法之前,先介紹幾個常用的技術,也能夠有效的減少倒排表的大小。
這裡先從實際應用背景作為切入點來優化倒排表。這個系統是給人用的,那麼乙個人會輸入什麼樣的查詢詞呢?
還有乙個技術叫做詞幹化。這個技術貌似只對歐洲的文字才有作用,對漢字作用不大。這裡也介紹一下。比如單詞「cars」是「car」的複數形式,但是對於我們來說這兩個詞的意思都一樣,所以把「cars」用「car」代替是乙個好方法。「car」可以認為是「cars」的詞幹。實際上乙個詞的單複數、時態等都能夠進行詞幹化。這種方法甚至比去除停用詞的效果還要好。大家也可以試試隨便找一篇文章,之後把所有的詞都詞幹化看看還有多少個不同的詞。和上面的技術一樣,也有人專門研究英文單詞的詞幹化,提供詞幹化的服務。
以上兩個技術聯合起來用就可以很大程度上的減少倒排表的大小,雖然這兩個技術也對檢索帶來些負面的問題,但是始終認為利大於弊。
現在回到正題,如果利用了上面兩個方法後,倒排表還是很大怎麼辦?那麼壓縮演算法開始上場了。這裡我們不使用gzip等複雜的演算法,由於倒排表的形式簡單,所以對簡單的問題有著簡單的解決方法。
文件數目必須用4位元組整數表示,但是乙個索引之中的文件編號相鄰間隔不會太大,可以用少於4位元組表示。例如,如果我們確定文件編號間隔不會超過兩個位元組表示的範圍,那麼對於乙個倒排表我們只把第乙個文件編號用4位元組表示,其它的用2位元組間隔來表示,這種方法可以使倒排表的大小為原來的一半。如本文一開始給的數字來說,倒排表大小可以由40tb變成20tb。上面給這個思想可行也很誘人,只不過還存在乙個必須解決的問題:文件間隔有可能和文件編號是乙個量級的,用兩位元組無法表示。
下面介紹一種可變位元組編碼方式:利用整數個位元組對文件間隔進行編碼。每個位元組的第1個位元代表延續位,後7個位元代表編碼位元。如果第乙個位元位1,代表這個位元組是編碼的最後乙個位元組,否則不是最後乙個位元組。
例如:5表示成可變位元組編碼二進位制形式為: 10000101
214577表示成可變位元組編碼二進位制形式為: 00001101 00001100 10110001。
對於第二個例子給出其還原方式:拿出每個位元組的低七位組合得到乙個21位元二進位制數,這個數字就是214577。這種編碼方式的編譯碼過程都非常簡單,而且時間開銷很小,相比於gzip這種方法要好的多。
除了可變長編碼,還有諸如γ編碼等等,這些編碼方式操作儲存單元的粒度要比乙個位元組要小,所以編碼方式比可變長編碼複雜,能得到更好的理論壓縮效率和實際壓縮效率。但是同樣在這800000文件機上構建倒排表,編碼使倒排表的大小變為101mb,僅僅比可變長編碼少13%。
假設通過詞幹化,去除停用詞能夠使倒排表大小降低1/10,之後可變長編碼又使倒排表大小降低1/2,那麼現在我們的倒排表大小就為18tb左右了。雖然這麼大的資料還是得需要分布式儲存的方法,但是這樣可以減少對機器數量的需求,是比較節省成本的。而對於乙個程式設計師來說,想要做乙個單台機器索引幾百萬網頁的搜尋引擎來說,也是一件可能的事了。
新手學資訊檢索3 詞頻 逆文件頻
首先,什麼是詞頻?詞頻就是一篇文件包含乙個詞的次數。舉個例子,如果一篇文件d中 cat 這個詞出現了5詞,那麼我們就說 cat 的詞頻為5,記做tf cat 5。那麼,什麼是文件頻?這個概念也是對於乙個詞來說的。通俗來說文件頻就是包含乙個詞的文件數目。那麼什麼叫做逆文件頻呢?idf表示逆文件頻,檢索...
新手學資訊檢索6 談談二值獨立模型
介紹乙個概率檢索模型 二值獨立模型。這個模型我自認為比較扯淡,如有大神在可以指點一下。這個模型用了n多個假設。假設1 詞項之間的出現是相互獨立的。這樣文件和查詢都可以向量化,如下 當詞項t出現在文件或查詢中,則xt或qt的值為1,否則為0。由於我們假設詞項出現是相互獨立的,並且向量取值只取0,1兩個...
資訊檢索導論2
5.索引壓縮 有失真壓縮 大小寫轉換,詞幹還原 停用詞剔除 向量空間模型 lsa 隱性語義分析 等 無失真壓縮 下面介紹的壓縮方法 heaps定律 詞項數目的估計 m kt b m 詞項數,t 文件集合中詞條個數,30 k 100,b 0.5 zipf定律 詞項在文件中分布的估計 排名第i多的詞項的...