咱們平常使用的搜索引擎源自現代信息檢索系統學術界對現代信息檢索的定義通常是: 從大規模非結構化數據的集合中找出知足用戶信息、需求的資料的過程。數據庫
這裏的「非結構化」實際上是針對經典的數據庫而言的數據庫裏的記錄都有嚴格的字段定義(Scheme),是「結構化」數據的典型表明例如每道菜都有名字,想要吃魚時,查詢「水煮魚」就很是高效。數據結構
相反,「非結構化」沒有這種嚴格的定義,計算機世界存儲的大量文本就是一個典型的表明一篇文章若是沒有進行特殊處理,對於其描述的菜叫什麼名字、須要準備哪些食材等信息,咱們是一無所知的,天然咱們也就沒法將其中的內容和已經定義好的數據庫字段進行匹配,這也是數據庫在處理非結構化數據時很是乏力的緣由之一。搜索引擎
此時,信息檢索的技術能夠極大地幫助咱們非結構化數據的特性是沒有嚴格的數據格式定義,這點決定了信息檢索的以下兩個核心要素:設計
假設我很是喜歡吃川菜中的水煮魚,其香辣的味道使人難忘那麼,若是我想看一篇介紹川菜文化的文章,最簡單的方法莫過於看看其中是否提到關鍵詞「水煮魚」了。若是有(返回值爲真),那麼我認爲就是相關的;若是沒有(返回值假),那麼我就認爲其不相關。3d
就是最基本的布爾模型若是將本次查詢轉換爲布爾表達式也很簡單,就一個條件:cdn
水煮魚blog
固然,你會以爲,中華飲食源遠流長,川菜經典怎麼會只有水煮魚呢?沒錯,我還很是喜好粉蒸排骨,它是小時候逢年過節的必備菜餚 那麼,將條件修改一下排序
水煮魚 OR 粉蒸排骨索引
哈哈,這下,不只僅是水煮魚,談到「粉蒸排骨」的文 也會認定爲其與川菜文化相關 若是想看看在上海哪家店能夠吃到這些美食呢?再修改下:文檔
(水煮魚 OR 粉蒸排骨) AND 上海
這裏,「上海」是必要條件,而水煮魚或粉蒸排骨,有同樣就能夠啦。最後,咱們能夠看看哪些文章提到了上海的餐館經營川菜,並且至少提供水煮魚和粉蒸排骨兩味佳餚中的一道只要理解了布爾表達式,就能理解信息檢索中的布爾模型 近些年,除了基本的 AND、OR NOT 操做,布爾模型還有所擴展。
其中,最多見的是鄰近操做符(Proximity),用於確保關鍵詞出如今必定的範圍以內。其假設就是不一樣的搜索關鍵詞,若是它們出現的位置越近,那麼命中結果的相關性就越高。
整體上來看,布爾模型的優勢是簡單易懂,系統實現的成本也較低。不過,它的弱點是對相關性刻畫不足。相關與否是個模糊的概念,有的文章和查詢條件關係密切,很是符合用戶的信息需求,而有些不盡然。僅僅經過「真」和「假」2個值來表示,過於絕對,也沒有辦法體現其中的區別 那麼,有沒有更好的解決方案呢?
爲了加強布爾模型,須要考慮如何爲匹配上的文檔來打分。相關性越高的文檔其得到的分數就越高。第一個最直觀的想法就是:每一個詞在不一樣文檔裏的權重是不同的,能夠經過這個來計算得分。這裏介紹使用最爲廣泛的 tf- idf機制。
假設咱們有一個文檔集合(Collection), c表示整個集合,d表示其中一篇文章,t表示一個單詞。那麼這裏tf表示詞頻(Term Frequency),就是一個詞t在文章中(或是文章的某個字段中)出現的次數。通常的假設是,某個詞在文章中的tf越高,表示該詞t對於該文而言越重要。固然,篇幅更長的文檔可能擁有更高的tf值,咱們會在後面Lucene的介紹中討論如何計算可使得tf更合理。
同時,另一個經常使用的是 idf,它表示逆文檔頻率(Inverse Document Frequency)。首先,df表示文檔頻率( Document Frequency ),即文檔集合c中出現某個詞t文檔數量。通常的假設是,某個詞t在文檔集合c中,出如今越多的文檔中,那麼其重要性就越低,反之則越高。
剛開始可能會感受有點困惑,可是仔細想一想這並不難理解。比如「的、你、我、是」這種詞常常會出現文檔中,可是並不表明什麼具體的含義。再舉個例子,在討論美食的文檔集合中,「美食」可能會出如今上萬篇文章中,但它並不能使得某篇文檔變得特殊。相反,若是隻有3篇文章討論到水煮魚,那麼這3篇文章和水煮魚的相關性就遠遠高於其餘文章。 「水煮魚」這個詞在文檔集合中就應該擁有更高的權重。對此,一般用df的反比例指標idf表示其重要性,基本公式以下:
其中N是整個文檔集合中文章的數量,log 是爲了確保 idf 分值不要遠遠高於tf而埋沒tf的貢獻,默認取10爲底。因此單詞t的df越低,其idf就越高,t的重要性就越高。那麼綜合起來, tf-idf的基本公式表示以下:
也就是說,一個單詞t,若是它在文檔中的詞頻tf越高,且在整個集合中的idf也很高,那麼t對於d而言就越重要。
排序布爾模型是一種基於加權求和的打分機制,下面將介紹一個比排序布爾模型稍微複雜一點的向量空間模型。此模型的重點,就是將某個文檔轉換爲一個向量 仍是以上面的文章爲例。
統計其中的單詞,假設去重後一共有50個不一樣(Unique)的詞,那麼該文梢的向量就是50個緯度,其中每一個緯度是其對應單詞的tf-idf值,看上去就像這樣:
(四川 = 1.84 ,水煮魚 = 6.30 ,專輯 = 6.80 ,…… )
固然,在系統實現的時候,不會直接用單詞來代來表緯度,而是用單詞的ID。如此一來,一個文檔集合就會轉換爲 一組向量,每一個向量表明一篇文檔。這種表示忽略了單詞在文章中出現的順序,能夠大大簡化不少模型中的計算複雜度 ,同時又保證了至關的準確性,咱們一般也稱這種處理方式爲詞包(Bag Of Word),這點在第一篇的文本分類和聚類中已經有所說起。
同理,用戶輸入的查詢也能轉換爲一組向量,只是和文檔向量相比較,查詢向量的維度會很是低。最後,相關性問題就轉化爲計算查詢向量和文檔向量之間的類似度了。在實際處理中,最經常使用的類似性度量方式是餘弦距離。由於它正好是一個介於0和1之間的數,若是向盤一致就是1,若是正交就是0,這也符合類似度百分比的特性,具體的計算公式以下:
其圖形化解釋如圖所示:
相對於標準的布爾數學模型,向量空間模型具備以下優勢:
基於線性代數的簡單模型,很是容易理解
詞組的權重能夠不是二元的,例如採用 tf-idf 這種機制
容許文檔和索引之間連續類似程度的計算,以及基於此的排序,不限於布爾模型的 「真」「假」兩值
容許關鍵詞的部分匹配
固然,基本的向量空間模型也有不少不足之處:
例如對於很長的文檔,類似度得分不會很理想;沒有考慮到單詞所表明的語義,仍是限於精準匹配;沒有考慮詞在文檔中出現的順序等。
通過前面的探討,咱們發現:要解決相關性,就要根據需求設計合理的模型,越是精細模型,其計算的複雜度每每也就越高。同時,咱們又要保證很是高的查詢效率。互聯網時代,用戶就是普通的衝浪者,「爽快」的體驗相當重要。所以 搜索引擎的結果處理必須是秒級的,一般不能超過3秒。坐在電腦前等待幾分鐘只是爲了知道明天廣州的天氣狀況是沒法想象的,也是沒法接受的。相關性計算的複雜度和速度,看上去就成了一對沒法調和的矛盾體,該如何解決呢?
這裏必需要提到檢索引擎最經典的數據結構設計一一倒排索引(或者稱逆向索引)。先讓咱們假想一下,你是一個熱愛讀書的人,當你進入圖書館或書店的時候,會怎樣快速發現本身喜好的圖書呢?沒錯,就是看書架上的標籤。若是看到 個架子上標着「烹飪 ·地美食」,那麼恭喜你,離介紹川菜的書就不遠了。倒排索引作的就是貼標籤的事情。看看下 面的例子,這是沒有通過倒排索引處理的原始數據,固然實際中的文章不會如此之短。
對於每篇文章的內容,咱們先進行中文分詞,而後將分好的詞做爲該篇的標籤。例如對ID爲1的文章「最上癮的絕味川菜」進行分詞,可分爲以下5個詞:
最,上癮,的,絕味,川菜
那麼文章1就會有5個關鍵詞標籤
再分析ID爲2的文章「大廚必讀系列:經典川菜」,它能夠分爲以下5個詞:
大廚,必讀,系列,經典,川菜
若是和第1次的標籤結果合併起來
請注意ID爲5的關鍵詞「川菜」,它在文章1和2中都出現過,因此咱們會將其對應的文檔ID寫上「1,2」
如此逐個分析完全部5篇文章以後,咱們會獲得表以下 ,這就是倒排索引的原型。
這裏一共出現了18個不重複的單詞,咱們將這個集合稱爲文檔集合的詞典或詞彙(Vocabulary)。從上面這個結構能夠看出,創建倒排索引的時候,是將文檔一關鍵詞的關係轉變爲關鍵詞一文檔集合的關係,同時逐步創建詞典。有了這種數據結構,你會發現關鍵詞的查詢就像在圖書館裏根據標籤找書同樣方便快捷,效率獲得大大提高。例如,咱們查找:
川菜 AND 舌尖
經過查找「川菜」系統會返回文章ID:l、二、3;經過查找「舌尖」系統會返回文章ID:三、4,再取交集,咱們就能找到文章3並進行返回。取交集的歸併操做在計算機領域已經很是成熟,速度快得驚人。
考慮到布爾模型的鄰近(Proximity)操做,或者其餘的計算模型,咱們還能夠在數據結構中加上詞的位置,以及tf-idf等信息,這裏再也不深刻展開 此處最重要的結論是:咱們能夠經過倒排索引保持超高的效率。