Lucene:信息檢索與全文檢索

目錄html

 

 

一、信息檢索的概念java


信息檢索就是從信息集合中找出與用戶需求相關的信息。被檢索出的信息除了文本外,還有圖像、音頻、視頻等多媒體信息。程序員

 

二、信息檢索技術的分類算法


目前信息檢索技術可分爲3類:數據庫

  • 全文檢索:把用戶的查詢請求和全文中的每個詞進行比較,不考慮查詢請求與文本語義上的匹配。在信息檢索工具中,全文檢索是最具通用性和實用性的。
  • 數據檢索:查詢要求和信息系統中數據都遵循必定的格式,具備必定的結構,容許對特定的字段檢索。其性能與使用有不少的侷限性,而且支持語義匹配的能力較差。
  • 知識檢索:調用的是用於知識的、語義上的匹配。

 

                        全文檢索的通常過程apache

三、全文檢索與數據庫查詢對比服務器


全文檢索出現的目的就是爲了更快地查找信息;數據庫查詢效率低(例如拿一本字典來一頁一頁找,效率確定很低)。全文搜索是按索引來找,效率高(從字典的索引找,再找到哪一頁,效率會高)架構

 

四、全文檢索工具通常由這樣的三部分組成函數


全文檢索工具通常由索引部分、分詞部分和檢索部分構成。工具

 

五、全文檢索中創建索引與進行檢索的流程


  • 創建索引:就是對待檢索的信息進行必定的分析,並將分析結果按照必定的組織方式存儲起來,一般將這些結果存儲在文件中。存儲分析結果的文件的集合就是索引。在查詢時,先從索引中查找,因爲索引是按照必定的結構組織的,因此查詢的速度很是快。
  • 爲提供檢索的功能,信息檢索系統會事先作一些準備工做:信息的採集與加工。
  • 信息採集:把信息源的信息拷貝到本地,構成待檢索的信息集合。(信息源能夠是互聯網中的網頁、硬盤中的txt、doc、pdf等格式的電子文檔,或是文件系統上的文件等等)。
  • 信息加工:爲採集到本地的信息編排索引,爲查詢作好準備。

流程以下:

 

六、索引裏面究竟存什麼?


假設:個人文檔集合裏面有100篇文檔,爲了方便表示,咱們爲文檔編號從1到100,獲得下面的結構

inverted index

左邊保存的是一系列字符串,稱爲詞典

每一個字符串都指向包含此字符串的文檔(Document)鏈表,此文檔鏈表稱爲倒排表(Inverse List)。

有了索引,便使保存的信息和要搜索的信息一致,能夠大大加快搜索的速度。

好比說,咱們要尋找既包含字符串「lucene」又包含字符串「solr」的文檔,咱們只須要如下幾步:

1. 取出包含字符串「lucene」的文檔鏈表。

2. 取出包含字符串「solr」的文檔鏈表。

3. 經過合併鏈表,找出既包含「lucene」又包含「solr」的文件。

inverted index merge

看到這個地方,有人可能會說,全文檢索的確加快了搜索的速度,可是多了索引的過程,二者加起來不必定比順序掃描快多少。的確,加上索引的過程,全文檢索不必定比順序掃描快,尤爲是在數據量小的時候更是如此。而對一個很大量的數據建立索引也是一個很慢的過程。

然而二者仍是有區別的,順序掃描是每次都要掃描,而建立索引的過程僅僅須要一次,之後即是一勞永逸的了,每次搜索,建立索引的過程沒必要通過,僅僅搜索建立好的索引就能夠了。

這也是全文搜索相對於順序掃描的優點之一:一次索引,屢次使用。

 

七、如何建立索引


From:http://www.cnblogs.com/forfuture1978/archive/2009/12/14/1623594.html

全文檢索的索引建立過程通常有如下幾步:

第一步:一些要索引的原始文檔(Document):爲了方便說明索引建立過程,這裏特地用兩個文件爲例:

  • 文件一:Students should be allowed to go out with their friends, but not allowed to drink beer.
  • 文件二:My friend Jerry went to school to see his students but found them drunk which is not allowed.

 

第二步:將原始文檔傳給分詞組件(Tokenizer):分詞組件(Tokenizer)會作如下幾件事情(此過程稱爲Tokenize)

  • 將文檔分紅一個一個單獨的單詞。
  • 去除標點符號。
  • 去除停詞(Stop word)

對於每一種語言的分詞組件(Tokenizer),都有一個停詞(stop word)集合。

 

通過分詞(Tokenizer)後獲得的結果稱爲詞元(Token)

在咱們的例子中,便獲得如下詞元(Token):

「Students」,「allowed」,「go」,「their」,「friends」,「allowed」,「drink」,「beer」,「My」,「friend」,「Jerry」,「went」,「school」,「see」,「his」,「students」,「found」,「them」,「drunk」,「allowed」。

 

第三步:將獲得的詞元(Token)傳給語言處理組件(Linguistic Processor)。

語言處理組件(linguistic processor)主要是對獲得的詞元(Token)作一些同語言相關的處理。

對於英語,語言處理組件(Linguistic Processor)通常作如下幾點:

  • 變爲小寫(Lowercase)
  • 將單詞縮減爲詞根形式,如「cars」到「car」等。這種操做稱爲:stemming
  • 將單詞轉變爲詞根形式,如「drove」到「drive」等。這種操做稱爲:lemmatization

 

Stemming 和 lemmatization的異同:

  • 相同之處:Stemming和lemmatization都要使詞彙成爲詞根形式。

  • 二者的方式不一樣:
    • Stemming採用的是「縮減」的方式:「cars」到「car」,「driving」到「drive」。
    • Lemmatization採用的是「轉變」的方式:「drove」到「drove」,「driving」到「drive」。
  • 二者的算法不一樣:
    • Stemming主要是採起某種固定的算法來作這種縮減,如去除「s」,去除「ing」加「e」,將「ational」變爲「ate」,將「tional」變爲「tion」。
    • Lemmatization主要是採用保存某種字典的方式作這種轉變。好比字典中有「driving」到「drive」,「drove」到「drive」,「am, is, are」到「be」的映射,作轉變時,只要查字典就能夠了。
  • Stemming和lemmatization不是互斥關係,是有交集的,有的詞利用這兩種方式都能達到相同的轉換。

 

語言處理組件(linguistic processor)的結果稱爲詞(Term)

在咱們的例子中,通過語言處理,獲得的詞(Term)以下:

「student」,「allow」,「go」,「their」,「friend」,「allow」,「drink」,「beer」,「my」,「friend」,「jerry」,「go」,「school」,「see」,「his」,「student」,「find」,「them」,「drink」,「allow」。

 

也正是由於有語言處理的步驟,才能使搜索drove,而drive也能被搜索出來。

 

第四步:將獲得的詞(Term)傳給索引組件(Indexer)。

索引組件(Indexer)主要作如下幾件事情:

1. 利用獲得的詞(Term)建立一個字典。

在咱們的例子中字典以下:

Term

Document ID

student

1

allow

1

go

1

their

1

friend

1

allow

1

drink

1

beer

1

my

2

friend

2

jerry

2

go

2

school

2

see

2

his

2

student

2

find

2

them

2

drink

2

allow

2

 

2. 對字典按字母順序進行排序。 

Term

Document ID

allow

1

allow

1

allow

2

beer

1

drink

1

drink

2

find

2

friend

1

friend

2

go

1

go

2

his

2

jerry

2

my

2

school

2

see

2

student

1

student

2

their

1

them

2

 

3. 合併相同的詞(Term)成爲文檔倒排(Posting List)鏈表。

postinglist

在此表中,有幾個定義:

  • Document Frequency 即文檔頻次,表示總共有多少文件包含此詞(Term)。
  • Frequency 即詞頻率,表示此文件中包含了幾個此詞(Term)。

因此對詞(Term) 「allow」來說,總共有兩篇文檔包含此詞(Term),從而詞(Term)後面的文檔鏈表總共有兩項,第一項表示包含「allow」的第一篇文檔,即 1號文檔,此文檔中,「allow」出現了2次,第二項表示包含「allow」的第二個文檔,是2號文檔,此文檔中,「allow」出現了1次。

到此爲止,索引已經建立好了,咱們能夠經過它很快的找到咱們想要的文檔。

並且在此過程當中,咱們驚喜地發現,搜索 「drive」,「driving」,「drove」,「driven」也可以被搜到。由於在咱們的索引 中,「driving」,「drove」,「driven」都會通過語言處理而變成「drive」,在搜索時,若是您輸入「driving」,輸入的查詢 語句一樣通過咱們這裏的一到三步,從而變爲查詢「drive」,從而能夠搜索到想要的文檔。

 

 

八、如何對索引進行搜索?


到這裏彷佛咱們能夠宣佈「咱們找到想要的文檔了」,僅僅是找到了,可是並非「理想」的結果。

然而事情並無結束,找到了僅僅是全文檢索的一個方面。不是嗎?若是僅僅只有一個或十個文檔包含咱們查詢的字符串,咱們的確找到了。然而若是結果有一千個,甚至成千上萬個呢?那個又是您最想要的文件呢?

 

打開Google吧,好比說您想在微軟找份工做,因而您輸入「Microsoft job」,您卻發現總共有22600000個結果返回。好大的數字呀,忽然發現找不到是一個問題,找到的太多也是一個問題。在如此多的結果中,如何將最相關的放在最前面呢?

固然Google作的很不錯,您一下就找到了jobs at Microsoft。想象一下,若是前幾個所有是「Microsoft does a good job at software industry…」將是多麼可怕的事情呀。

 

如何像Google同樣,在成千上萬的搜索結果中,找到和查詢語句最相關的呢?

如何判斷搜索出的文檔和查詢語句的相關性呢?

這要回到咱們第三個問題:如何對索引進行搜索?

搜索主要分爲如下幾步:

 

第一步:用戶輸入查詢語句。

查詢語句同咱們普通的語言同樣,也是有必定語法的。

不一樣的查詢語句有不一樣的語法,如SQL語句就有必定的語法。

查詢語句的語法根據全文檢索系統的實現而不一樣。最基本的有好比:AND, OR, NOT等。

 

舉個例子,用戶輸入語句:lucene AND learned NOT hadoop。

說明用戶想找一個包含lucene和learned然而不包括hadoop的文檔。

 

第二步:對查詢語句進行詞法分析,語法分析,及語言處理。

因爲查詢語句有語法,於是也要進行語法分析,語法分析及語言處理。

1. 詞法分析主要用來識別單詞和關鍵字。

如上述例子中,通過詞法分析,獲得單詞有lucene,learned,hadoop, 關鍵字有AND, NOT。

若是在詞法分析中發現不合法的關鍵字,則會出現錯誤。如lucene AMD learned,其中因爲AND拼錯,致使AMD做爲一個普通的單詞參與查詢。

2. 語法分析主要是根據查詢語句的語法規則來造成一棵語法樹。

若是發現查詢語句不知足語法規則,則會報錯。如lucene NOT AND learned,則會出錯。

如上述例子,lucene AND learned NOT hadoop造成的語法樹以下:

 

 

3. 語言處理同索引過程當中的語言處理幾乎相同。

如learned變成learn等。

通過第二步,咱們獲得一棵通過語言處理的語法樹。

 

第三步:搜索索引,獲得符合語法樹的文檔。

此步驟有分幾小步:

  1. 首先,在反向索引表中,分別找出包含lucene,learn,hadoop的文檔鏈表。
  2. 其次,對包含lucene,learn的鏈表進行合併操做,獲得既包含lucene又包含learn的文檔鏈表。
  3. 而後,將此鏈表與hadoop的文檔鏈表進行差操做,去除包含hadoop的文檔,從而獲得既包含lucene又包含learn並且不包含hadoop的文檔鏈表。
  4. 此文檔鏈表就是咱們要找的文檔。

 

第四步:根據獲得的文檔和查詢語句的相關性,對結果進行排序。

雖然在上一步,咱們獲得了想要的文檔,然而對於查詢結果應該按照與查詢語句的相關性進行排序,越相關者越靠前。

如何計算文檔和查詢語句的相關性呢?

不如咱們把查詢語句看做一片短小的文檔,對文檔與文檔之間的相關性(relevance)進行打分(scoring),分數高的相關性好,就應該排在前面。

 

那麼又怎麼對文檔之間的關係進行打分呢?

這可不是一件容易的事情,首先咱們看一看判斷人之間的關係吧。

首先看一我的,每每有不少要素,如性格,信仰,愛好,衣着,高矮,胖瘦等等。

其次對於人與人之間的關係,不一樣的要素重要性不一樣,性格,信仰,愛好可能重要些,衣着,高矮,胖瘦可能就不那麼重要了,因此具備相同或類似性格,信仰,愛好的人比較容易成爲好的朋友,然而衣着,高矮,胖瘦不一樣的人,也能夠成爲好的朋友。

於是判斷人與人之間的關係,首先要找出哪些要素對人與人之間的關係最重要,好比性格,信仰,愛好。其次要判斷兩我的的這些要素之間的關係,好比一我的性格開朗,另外一我的性格外向,一我的信仰佛教,另外一個信仰上帝,一我的愛好打籃球,另外一個愛好踢足球。咱們發現,兩我的在性格方面都很積極,信仰方面都很善良,愛好方面都愛運動,於是兩我的關係應該會很好。

 

咱們再來看看公司之間的關係吧。

首先看一個公司,有不少人組成,如總經理,經理,首席技術官,普通員工,保安,門衛等。

其次對於公司與公司之間的關係,不一樣的人重要性不一樣,總經理,經理,首席技術官可能更重要一些,普通員工,保安,門衛可能較不重要一點。因此若是兩個公司總經理,經理,首席技術官之間關係比較好,兩個公司容易有比較好的關係。然而一位普通員工就算與另外一家公司的一位普通員工有血海深仇,怕也難影響兩個公司之間的關係。

 

於是判斷公司與公司之間的關係,首先要找出哪些人對公司與公司之間的關係最重要,好比總經理,經理,首席技術官。其次要判斷這些人之間的關係,不如兩家公司的總經理曾經是同窗,經理是老鄉,首席技術官曾是創業夥伴。咱們發現,兩家公司不管總經理,經理,首席技術官,關係都很好,於是兩家公司關係應該會很好。

 

分析了兩種關係,下面看一下如何判斷文檔之間的關係了。

首先,一個文檔有不少詞(Term)組成,如search, lucene, full-text, this, a, what等。

其次對於文檔之間的關係,不一樣的Term重要性不一樣, 好比對於本篇文檔,search, Lucene, full-text就相對重要一些,this, a , what可能相對不重要一些。因此若是兩篇文檔都包含search, Lucene,fulltext,這兩篇文檔的相關性好一些,然而就算一篇文檔包含this, a, what,另外一篇文檔不包含this, a, what,也不能影響兩篇文檔的相關性。

於是判斷文檔之間的關係,首先找出哪些詞(Term)對文檔之間的關係最重要,如search, Lucene, fulltext。而後判斷這些詞(Term)之間的關係。

找出詞(Term)對文檔的重要性的過程稱爲計算詞的權重(Term weight)的過程。

計算詞的權重(term weight)有兩個參數,第一個是詞(Term),第二個是文檔(Document)。

詞的權重(Term weight)表示此詞(Term)在此文檔中的重要程度,越重要的詞(Term)有越大的權重(Term weight),於是在計算文檔之間的相關性中將發揮更大的做用。

判斷詞(Term)之間的關係從而獲得文檔相關性的過程應用一種叫作向量空間模型的算法(Vector Space Model)

 

下面仔細分析一下這兩個過程:

1. 計算權重(Term weight)的過程。

影響一個詞(Term)在一篇文檔中的重要性主要有兩個因素:

  • Term Frequency(tf):即給定的Term在此文檔中出現了多少次。tf 越大說明越重要。這個數字一般會被歸一化,以防止它偏向長的文件。(注:同一個詞語Term在長文件裏可能會比短文件有更高的詞頻,而無論該詞語重要與否)
  • Document Frequency(df):即有多少文檔包含此Term。df越大說明越不重要。
  • Inverse Document Frequency(idf):是一個詞語Term廣泛重要性的度量。某一特定詞語的IDF,能夠由總文件數目除以包含該詞語之文件的數目,再將獲得的商取對數獲得。

注意:TF-IDF=TF*IDF。某一特定文件內的高詞語頻率,以及該詞語在整個文件集合中的低文件頻率,能夠產生出高權重的TF-IDF。所以,TF-IDF傾向於過濾掉常見的詞語,保留重要的詞語。

例子:有不少不一樣的數學公式能夠用來計算TF-IDF。這邊的例子以上述的數學公式來計算。詞頻 (TF)
是 一詞語出現的次數除以該文件的總詞語數。假如一篇文件的總詞語數是100個,而詞語「母牛」出現了3次,那麼「母牛」一詞在該文件中的詞頻就是 3/100=0.03。一個計算文件頻率(DF) 的方法是測定有多少份文件出現過「母牛」一詞,而後除以文件集裏包含的文件總數。因此,若是「母牛」一詞在1,000份文件出現過,而文件總數是 10,000,000份的話,其逆向文件頻率就是log(10,000,000 / 1,000)=4。最後的TF-IDF的分數爲0.03 * 4=0.12。

 

容易理解嗎?詞(Term)在文檔中出現的次 數越多,說明此詞(Term)對該文檔越重要,如「搜索」這個詞,在本文檔中出現的次數不少,說明本文檔主要就是講這方面的事的。然而在一篇英語文檔 中,this出現的次數更多,就說明越重要嗎?不是的,這是由第二個因素進行調整,第二個因素說明,有越多的文檔包含此詞(Term), 說明此詞(Term)太普通,不足以區分這些文檔,於是重要性越低。

這也如咱們程序員所學的技術,對於程序員自己來講,這項技術掌握越深越好(掌握越深說明花時間看的越多,tf越大),找工做時越有競爭力。然而對於全部程序員來講,這項技術懂得的人越少越好(懂得的人少df小),找工做越有競爭力。人的價值在於不可替代性就是這個道理。

 

道理明白了,咱們來看看公式:

 

 

 

 這僅僅只term weight計算公式的簡單典型實現。實現全文檢索系統的人會有本身的實現,Lucene就與此稍有不一樣。有關Lucene計算公式能夠參考官方文檔(V4.0)

2. 判斷Term之間的關係從而獲得文檔相關性的過程,也即向量空間模型的算法(VSM)。

咱們把文檔看做一系列詞(Term),每個詞(Term)都有一個權重(Term weight),不一樣的詞(Term)根據本身在文檔中的權重來影響文檔相關性的打分計算。

因而咱們把全部此文檔中詞(term)的權重(term weight) 看做一個向量。

Document = {term1, term2, …… ,term N}

Document Vector = {weight1, weight2, …… ,weight N}

一樣咱們把查詢語句看做一個簡單的文檔,也用向量來表示。

Query = {term1, term 2, …… , term N}

Query Vector = {weight1, weight2, …… , weight N}

咱們把全部搜索出的文檔向量及查詢向量放到一個N維空間中,每一個詞(term)是一維。

如圖:

 

咱們認爲兩個向量之間的夾角越小,相關性越大。

因此咱們計算夾角的餘弦值做爲相關性的打分,夾角越小,餘弦值越大,打分越高,相關性越大。

有人可能會問,查詢語句通常是很短的,包含的詞(Term)是不多的,於是查詢向量的維數很小,而文檔很長,包含詞(Term)不少,文檔向量維數很大。你的圖中二者維數怎麼都是N呢?

在這裏,既然要放到相同的向量空間,天然維數是相同的,不一樣時,取兩者的並集,若是不含某個詞(Term)時,則權重(Term Weight)爲0。

相關性打分公式以下:

 

 

舉個例子,查詢語句和三篇文章共有11個Term。其中假定各自的權重(Term weight)以下表格。(注意:沒有詳細計算,只是找了一些數據做爲樣本數據,具體的計算過程不一樣的問題能夠採用不一樣的算法,如前面的log函數能夠採用不一樣的底數等。)

 

 

t1

t2

t3

t4

t5

t6

t7

t8

t9

t10

t11

D1

0

0

.477

0

.477

.176

0

0

0

.176

0

D2

0

.176

0

.477

0

0

0

0

.954

0

.176

D3

0

.176

0

0

0

.176

0

0

0

.176

.176

Q

0

0

0

0

0

.176

0

0

.477

0

.176

因而計算,三篇文檔同查詢語句的相關性打分分別爲:

 

 

因而文檔二相關性最高,先返回,其次是文檔三,最後是文檔一。

 

到此爲止,咱們能夠找到咱們最想要的文檔了。

說了這麼多,其實尚未進入到Lucene, 而僅僅是信息檢索技術(Information retrieval)中的基本理論,然而當咱們看過Lucene後咱們會發現,Lucene是對這種基本理論的一種基本的的實踐。因此在之後分析 Lucene的文章中,會經常看到以上理論在Lucene中的應用。

 

在進入Lucene以前,對上述索引建立和搜索過程所一個總結,如圖: 

此圖參照http://www.lucene.com.cn/about.htm中文章《開放源代碼的全文檢索引擎Lucene》

 

Lucene系統結構與源碼組織圖

從圖中咱們清楚的看到,Lucene的系統由 基礎結構封裝、索引核心、對外接口三大部分組成。其中直接操做索引文件的索引核心又是系統的重點。Lucene的將全部源碼分爲了7個模塊(在java語 言中以包即package來表示),各個模塊所屬的系統部分也如上圖所示。須要說明的是org.apache.lucene.queryPaser是作爲 org.apache.lucene.search的語法解析器存在,不被系統以外實際調用,所以這裏沒有看成對外接口看待,而是將之獨立出來。

 

從面象對象的觀點來考察,Lucene應用了 最基本的一條程序設計準則:引入額外的抽象層以下降耦合性。首先,引入對索引文件的操做org.apache.lucene.store的封裝,而後將索 引部分的實現創建在(org.apache.lucene.index)其之上,完成對索引核心的抽象。在索引核心的基礎上開始設計對外的接口 org.apache.lucene.search與org.apache.lucene.analysis。在每個局部細節上,好比某些經常使用的數據結 構與算法上,Lucene也充分的應用了這一條準則。在高度的面向對象理論的支撐下,使得Lucene的實現容易理解,易於擴展。

 

Lucene在系統結構上的另外一個特色表現爲 其引入了傳統的客戶端服務器結構之外的的應用結構。Lucene能夠做爲一個運行庫被包含進入應用自己中去,而不是作爲一個單獨的索引服務器存在。這天然 和Lucene開放源代碼的特徵分不開,可是也體現了Lucene在編寫上的原本意圖:提供一個全文索引引擎的架構,而不是實現。

 

Lucene索引文件的概念組成和結構組成

Lucene的索引文件的概念結構描述。 Lucene索引index由若干段(segment)組成,每一段由若干的文檔(document)組成,每個文檔由若干的域(field)組成,每 一個域由若干的項(term)組成。項是最小的索引概念單位,它直接表明了一個字符串以及其在文件中的位置、出現次數等信息。域是一個關聯的元組,由一個 域名和一個域值組成,域名是一個字串,域值是一個項,好比將「標題」和實際標題的項組成的域。文檔是提取了某個文件中的全部信息以後的結果,這些組成了 段,或者稱爲一個子索引。子索引能夠組合爲索引,也能夠合併爲一個新的包含了全部合併項內部元素的子索引。咱們能夠清楚的看出,Lucene的索引結構在 概念上即爲傳統的倒排索引(倒排文件或倒排索引是指索引對象是文檔或者文檔集合中的單詞等,用來存儲這些單詞在一個文檔或者一組文檔中的存儲位置,是對文 檔或者文檔集合的一種最經常使用的索引機制。)結構。

 

1. 索引過程:

  • 有一系列被索引文件
  • 被索引文件通過語法分析和語言處理造成一系列詞(Term)。
  • 通過索引建立造成詞典和反向索引表。
  • 經過索引存儲將索引寫入硬盤。

2. 搜索過程:

  • 用戶輸入查詢語句。
  • 對查詢語句通過語法分析和語言分析獲得一系列詞(Term)。
  • 經過語法分析獲得一個查詢樹。
  • 經過索引存儲將索引讀入到內存。
  • 利用查詢樹搜索索引,從而獲得每一個詞(Term)的文檔鏈表,對文檔鏈表進行交,差,並獲得結果文檔。
  • 將搜索到的結果文檔對查詢的相關性進行排序。
  • 返回查詢結果給用戶。

 轉載自 http://www.cnblogs.com/bluepoint2009/archive/2012/09/25/lucene-information-retrieval-and-fulltext-retrieval.html

相關文章
相關標籤/搜索