在solr中如何設置權重
這是我看過的“全文檢索基本理論” 希望對妳有幫助 妳可以選擇性的看 我們生活中的數據總體分為兩種:結構化數據和非結構化數據。結構化數據:指具有固定格式或有限長度的數據,如數據庫,元數據等。 非結構化數據:指不定長或無固定格式的數據,如郵件,word文檔等。 當然有的地方還會提到第三種,半結構化數據,如XML,HTML等,當根據需要可按結構化數據來處理,也可抽取出純文本按非結構化數據來處理。非結構化數據又壹種叫法叫全文數據。按照數據的分類,搜索也分為兩種: ? 對結構化數據的搜索:如對數據庫的搜索,用SQL語句。再如對元數據的搜索,如利用windows搜索對文件名,類型,修改時間進行搜索等。 ? 對非結構化數據的搜索:如利用windows的搜索也可以搜索文件內容,Linux下的grep命令,再如用Google和百度可以搜索大量內容數據。 對非結構化數據也即對全文數據的搜索主要有兩種方法:壹種是順序掃描法(Serial Scanning):所謂順序掃描,比如要找內容包含某壹個字符串的文件,就是壹個文檔壹個文檔的看,對於每壹個文檔,從頭看到尾,如果此文檔包含此字符串,則此文檔為我們要找的文件,接著看下壹個文件,直到掃描完所有的文件。如利用windows的搜索也可以搜索文件內容,只是相當的慢。如果妳有壹個80G硬盤,如果想在上面找到壹個內容包含某字符串的文件,不花他幾個小時,怕是做不到。Linux下的grep命令也是這壹種方式。大家可能覺得這種方法比較原始,但對於小數據量的文件,這種方法還是最直接,最方便的。但是對於大量的文件,這種方法就很慢了。有人可能會說,對非結構化數據順序掃描很慢,對結構化數據的搜索卻相對較快(由於結構化數據有壹定的結構可以采取壹定的搜索算法加快速度),那麽把我們的非結構化數據想辦法弄得有壹定結構不就行了嗎?這種想法很天然,卻構成了全文檢索的基本思路,也即將非結構化數據中的壹部分信息提取出來,重新組織,使其變得有壹定結構,然後對此有壹定結構的數據進行搜索,從而達到搜索相對較快的目的。這部分從非結構化數據中提取出的然後重新組織的信息,我們稱之索引。這種說法比較抽象,舉幾個例子就很容易明白,比如字典,字典的拼音表和部首檢字表就相當於字典的索引,對每壹個字的解釋是非結構化的,如果字典沒有音節表和部首檢字表,在茫茫辭海中找壹個字只能順序掃描。然而字的某些信息可以提取出來進行結構化處理,比如讀音,就比較結構化,分聲母和韻母,分別只有幾種可以壹壹列舉,於是將讀音拿出來按壹定的順序排列,每壹項讀音都指向此字的詳細解釋的頁數。我們搜索時按結構化的拼音搜到讀音,然後按其指向的頁數,便可找到我們的非結構化數據——也即對字的解釋。這種先建立索引,再對索引進行搜索的過程就叫全文檢索(Full-text Search)。下面這幅圖來自《Lucene in action》,但卻不僅僅描述了Lucene的檢索過程,而是描述了全文檢索的壹般過程。 全文檢索大體分兩個過程,索引創建(Indexing)和搜索索引(Search)。 ? 索引創建:將現實世界中所有的結構化和非結構化數據提取信息,創建索引的過程。 ? 搜索索引:就是得到用戶的查詢請求,搜索創建的索引,然後返回結果的過程。 於是全文檢索就存在三個重要問題: 1. 索引裏面究竟存些什麽?(Index) 2. 如何創建索引?(Indexing) 3. 如何對索引進行搜索?(Search) 下面我們順序對每個個問題進行研究。 二、索引裏面究竟存些什麽索引裏面究竟需要存些什麽呢?首先我們來看為什麽順序掃描的速度慢:其實是由於我們想要搜索的信息和非結構化數據中所存儲的信息不壹致造成的。非結構化數據中所存儲的信息是每個文件包含哪些字符串,也即已知文件,欲求字符串相對容易,也即是從文件到字符串的映射。而我們想搜索的信息是哪些文件包含此字符串,也即已知字符串,欲求文件,也即從字符串到文件的映射。兩者恰恰相反。於是如果索引總能夠保存從字符串到文件的映射,則會大大提高搜索速度。由於從字符串到文件的映射是文件到字符串映射的反向過程,於是保存這種信息的索引稱為反向索引。反向索引的所保存的信息壹般如下:假設我的文檔集合裏面有100篇文檔,為了方便表示,我們為文檔編號從1到100,得到下面的結構 左邊保存的是壹系列字符串,稱為詞典。每個字符串都指向包含此字符串的文檔(Document)鏈表,此文檔鏈表稱為倒排表(Posting List)。有了索引,便使保存的信息和要搜索的信息壹致,可以大大加快搜索的速度。比如說,我們要尋找既包含字符串“lucene”又包含字符串“solr”的文檔,我們只需要以下幾步: 1. 取出包含字符串“lucene”的文檔鏈表。 2. 取出包含字符串“solr”的文檔鏈表。 3. 通過合並鏈表,找出既包含“lucene”又包含“solr”的文件。 看到這個地方,有人可能會說,全文檢索的確加快了搜索的速度,但是多了索引的過程,兩者加起來不壹定比順序掃描快多少。的確,加上索引的過程,全文檢索不壹定比順序掃描快,尤其是在數據量小的時候更是如此。而對壹個很大量的數據創建索引也是壹個很慢的過程。然而兩者還是有區別的,順序掃描是每次都要掃描,而創建索引的過程僅僅需要壹次,以後便是壹勞永逸的了,每次搜索,創建索引的過程不必經過,僅僅搜索創建好的索引就可以了。這也是全文搜索相對於順序掃描的優勢之壹:壹次索引,多次使用。 三、如何創建索引全文檢索的索引創建過程壹般有以下幾步:第壹步:壹些要索引的原文檔(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): 1. 將文檔分成壹個壹個單獨的單詞。 2. 去除標點符號。 3. 去除停詞(Stop word)。所謂停詞(Stop word)就是壹種語言中最普通的壹些單詞,由於沒有特別的意義,因而大多數情況下不能成為搜索的關鍵詞,因而創建索引時,這種詞會被去掉而減少索引的大小。英語中挺詞(Stop word)如:“the”,“a”,“this”等。對於每壹種語言的分詞組件(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)壹般做以下幾點: 1. 變為小寫(Lowercase)。 2. 將單詞縮減為詞根形式,如“cars”到“car”等。這種操作稱為:stemming。 3. 將單詞轉變為詞根形式,如“drove”到“drive”等。這種操作稱為:lemmatization。 Stemming 和 lemmatization的異同: ? 相同之處:Stemming和lemmatization都要使詞匯成為詞根形式。 ? 兩者的方式不同: o Stemming采用的是“縮減”的方式:“cars”到“car”,“driving”到“drive”。 o Lemmatization采用的是“轉變”的方式:“drove”到“drove”,“driving”到“drive”。 ? 兩者的算法不同: o Stemming主要是采取某種固定的算法來做這種縮減,如去除“s”,去除“ing”加“e”,將“ational”變為“ate”,將“tional”變為“tion”。 o 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)鏈表。 在此表中,有幾個定義: ? 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 越大說明越重要。 ? Document Frequency (df):即有多少文檔包含次Term。df 越大說明越不重要。 容易理解嗎?詞(Term)在文檔中出現的次數越多,說明此詞(Term)對該文檔越重要,如“搜索”這個詞,在本文檔中出現的次數很多,說明本文檔主要就是講這方面的事的。然而在壹篇英語文檔中,this出現的次數更多,就說明越重要嗎?不是的,這是由第二個因素進行調整,第二個因素說明,有越多的文檔包含此詞(Term), 說明此詞(Term)太普通,不足以區分這些文檔,因而重要性越低。這也如我們程序員所學的技術,對於程序員本身來說,這項技術掌握越深越好(掌握越深說明花時間看的越多,tf越大),找工作時越有競爭力。然而對於所有程序員來說,這項技術懂得的人越少越好(懂得的人少df小),找工作越有競爭力。人的價值在於不可替代性就是這個道理。道理明白了,我們來看看公式: 這僅僅只term weight計算公式的簡單典型實現。實現全文檢索系統的人會有自己的實現,Lucene就與此稍有不同。 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),如下表格。 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之前,對上述索引創建和搜索過程所壹個總結,如圖:此圖參照中文章《開放源代碼的全文檢索引擎Lucene》 1. 索引過程: 1) 有壹系列被索引文件 2) 被索引文件經過語法分析和語言處理形成壹系列詞(Term)。 3) 經過索引創建形成詞典和反向索引表。 4) 通過索引存儲將索引寫入硬盤。 2. 搜索過程: a) 用戶輸入查詢語句。 b) 對查詢語句經過語法分析和語言分析得到壹系列詞(Term)。 c) 通過語法分析得到壹個查詢樹。 d) 通過索引存儲將索引讀入到內存。 e) 利用查詢樹搜索索引,從而得到每個詞(Term)的文檔鏈表,對文檔鏈表進行交,差,並得到結果文檔。 f) 將搜索到的結果文檔對查詢的相關性進行排序。 g) 返回查詢結果給用戶。藍屏