CS 582信息檢索課程的最終項目
要從終端運行程序,只需使用命令:
python main.py
提供了一份報告,以更好地解釋搜索引擎的功能和UI,請參考:
report.pdf
該文檔是伊利諾伊大學芝加哥大學CS 582信息檢索最終項目的報告。該項目包括從頭開始為UIC域構建Web搜索引擎。該軟件是模塊化構建的,從網絡爬行開始,瀏覽頁面預處理,索引並最終添加圖形用戶界面。此外,我們發明的定制的“智能”組件是必需的。
我決定通過使用基於偽重複反饋方法的查詢擴展來實驗搜索引擎優化,該方法試圖從用戶的查詢中獲取廣泛的上下文,我稱其為上下文pseudo-rewance反饋( CPRF )。這應該已經為搜索引擎添加了兩種改進類型:
不要僅將所有結果集中在查詢中的單詞上,而是將各種和相關的內容包括到檢索到的頁面集。
擴大結果總數,包括不包含查詢中存在任何單詞的網頁,但由於處理同一主題,因此仍然可能對用戶感興趣。
頁面排名實現也已集成,可以從應用程序UI打開或關閉。有關兩個智能組件的更多詳細信息,請稍後在本文檔中找到。
可以通過GitHub訪問包含該軟件的存儲庫:
https://github.com/mirkomantovani/web-search-engine-uic
該軟件是用Python3以面向對象的編程方式編寫的,以使其在未來易於擴展。 In order to make it easy to download and test the code without having to perform an extensive and time-consuming crawling and page preprocessing, the dataset containing 10000 pages crawled from the UIC domain: https://www.uic.edu/, and the preprocessed pages and needed files generated (Inverted Index, TF-IDF scores, Page Ranks, Document lengths, documents' tokens, URL)包含在存儲庫中。這樣,通過克隆存儲庫可以運行main.py ,並且在不到一秒鐘的時間內,搜索引擎就可以在輸入中獲取查詢。但是,在以下所有其他組件的小節中還包括並解釋了運行爬網和預處理的腳本。
可以通過執行腳本MultineReaded_crawling.py來完成網絡爬行,通過使用隊列模塊以同步的方式訪問資源,可以同時進行爬行,可以通過在同一腳本中修改整體常數thread_number的線程數量,但是,默認情況下,crawement and crawneck and Internet and crawneck and Internet and tose note note note note note and the Internect and the Internect and the Internect and with note and bate and the Internet。
爬行從UIC CS子域開始:https://www.cs.uic.edu/在MultiThreaded_crawling.py腳本中指定。
爬行是通過廣度優先的策略發生的,每個頁面都使用HTMLPARSER庫脫水,下載和解析,其鏈接被提取並檢查為屬於UIC域,然後將其添加到FIFO隊列中,如果是適當的形式。所有不良格式的黑名單是由我得出的,同時看到了我在爬行中得到的結果,並以這種18種格式組成:“ .docx”,“ .doc”,“ .avi”,“ .mp4”,“ .jpg”,“ .jpg”,“ .jpeg”,.jpeg“ .jpeg”,“ .png”,.png“ .png”,“ .gif”,“ .gif”,“ .pdf”。 “ .tgz”,“ .zip”,“ .exe”,“ .js”,“ .css”,“ .ppt”。 10秒鐘的超時將指定為下載頁面並傳遞到下一頁之前下載頁面的最大時間。
提取它們後也修改了URL,每個最初的HTTP變成https,消除了末端的所有砍伐,查詢字符串被刪除,並且還刪除了由哈希符號(#)表達的頁面內鏈接,以便不讓crawler相信更多的頁面具有不同的頁面,並且不同的是不同的頁面,請與眾不同。此外,通過在關閉HREF之前打開<a>標籤的鏈接的處理,並通過在字符串中另一個標籤“ <”打開的鏈接完成內部打開內部。
在爬網期間,將兩個詞典,來自代碼的URL和來自URL的代碼的URL經常保存到磁盤以後在以後使用,網頁的代碼是按時間順序排列的下載頁面的數量。
可以從run_preprocessing.py腳本執行爬行頁面的預處理,您還可以通過更改相應的常數page_rank_max_iter和n_pages來指定要考慮的頁面數量和頁面排名的最大迭代次數。
在預處理過程中,使用Preprocess.py腳本的定制對象。首先在<script>和<style>中首先獲取純文本,從而對每個頁面進行預處理。在此步驟中,我決定使用一個非常快速的庫: SelectOlax ,這是使用C. Cpython編寫的適度引擎的Python API,當然,相對於任何用純Python編寫的HTML Parses,計算時間中至少提供了一個數量級。然後,該頁面被令牌化,使用NLTK使用Porterstemmer來驅動令牌,使用文件optwords.txt中提供的停止字的列表消除了停止字詞,刪除了數字,並且不考慮3個字母的單詞。
在預處理中,構建了倒置索引,並且每個單詞doc對的TF-idf計算並存儲在倒置索引中。還創建了有向的Web圖( Graph.py ),並將其輸入到Page_rank.py中的頁面排名的實現。然後,以後回答查詢所需的所有文件將作為二進製文件保存。
預處理預處理和10000頁的PAGE_RANK收斂所需的總時間約為236秒,頁排名運行時間僅為11秒。
main.py腳本包含搜索引擎的訪問點。啟動程序時,創建了一個定制對象來引導查詢,而是實例化tfidfranker對象,以根據查詢對文檔進行排名。
當基於用戶查詢對文檔進行排名時,最多考慮100個文檔,此常數可以在main.py中更改。
用戶界面是圖形的,並使用Python軟件包:EasyGui實現。 GUI是一個可擴展的模塊, customgui.py ,包含該程序基本功能的主要API。
當程序啟動時,詢問用戶的基本設置,他是否要使用頁面排名和上下文偽重複反饋。之後,出現主菜單。主菜單顯示了搜索引擎的當前設置以及一些可以執行的主要操作的按鈕。可以通過從主菜單中選擇適當的按鈕在運行時動態更改設置。其他兩個選擇是:退出程序並運行查詢。如果用戶按下按鈕創建新查詢,則會出現一個新窗口,並提示用戶插入新查詢。當他點擊還可以時,查詢將進行預處理,並對文檔進行排名,並且將顯示前10個文檔(程序中的變量)文檔以及有關預處理查詢的信息以及如果偽優惠的反饋(如果打開),則可能是擴展的令牌。現在,用戶可以雙擊結果打開頁面上的頁面上的新選項卡上的默認瀏覽器瀏覽器的新選項卡,也可以遞歸地按列表末尾的“顯示更多結果”,以顯示10個結果。此外,如果偽相關反饋的反饋已經關閉,則還可以使用戶在擴展中重新匯總相同的查詢。
運行查詢並決定取消或打開結果後,將用戶提示回主菜單,在那裡他可以更改設置和/或運行新的查詢或具有不同設置的同一查詢,以將結果與先前獲得的結果進行比較。
我在該項目開發過程中遇到的主要挑戰是:
最初,選擇要設計哪種智能組件確實很難。我在這種類型的應用程序上都沒有經驗,並且在沒有演示測試的情況下考慮改進是如此困難。
在實施部分期間,我花了很多時間在了解我尚不知道的Python庫和構造上,例如線程,如何實現或進行網絡刮擦以將鏈接從HTML頁面中獲取。我必須從頭開始學習的另一件事是如何在Python創建GUI。
一個煩人的事情是,我不得不多次爬行10000頁,因為我以各種和錯誤的格式發現。最後,我必須黑名單的整個格式列表的大小為18個,其中包括“ .docx”,“ .doc”,“ .avi”,.mp4“,” .jpg“,” .jpeg“,” .jpeg”,“ .png”,“ .png”,“ .png”,“ .gif”,“ .gif”,“ .pdf”,“ .pdf” .pdf“ .pdf”,“ .gz”,“ .rar”,“ .rar”。 “ .exe”,“ .js”,“ .css”,“ .ppt”。
一個非常具有挑戰性的是,超參數調整和頁面排名的集成對文檔進行排名。決定對擴展查詢的代幣進行多少重要性的參數“ E ”是最難調整的,因為如果您沒有標記數據(每個查詢的相關文檔),則無法知道搜索引擎的平均性能。另外,查詢相關性是主觀的,您永遠不知道一個人想要檢索什麼,並且只能根據查詢進行猜測。我認為e最多應為0.5,最後我將其設置在0.1-0.2左右,您不想通過對未由用戶鍵入的單詞非常重要來偏向於疑問。
我使用的加權方案是文檔中簡單的單詞的簡單tf-idf,因為它被證明是Web搜索引擎最有效的一種,並且以正確的方式說明了每個文檔中單詞的重要性。我什至沒有考慮嘗試另一種措施,只是因為這不是該項目的目的,而且似乎效果很好。
用於對文檔進行排名的相似性度量是餘弦相似性。我從內部產品的相似性開始實現,然後切換到這只是更改一行代碼的問題。我認為餘弦相似性最好使用,因為它考慮了文檔的長度和查詢長度。它更為複雜,通常在這種類型的應用程序中效果很好,因此選擇相似性度量並不是真正的問題,我只是知道餘弦相似性是正確的。
我對我提出的一些隨機和多樣的查詢進行了對10的評估(僅考慮了前10個結果)。這是結果:
查詢: “顧問論文”,第一個結果是https://grad.uic.edu/electronic-thesis-dissertation-faqs,我認為所有結果都與論文和相關性有關,我將給出一個精度: p = 1.0與此查詢。
查詢: “職業博覽會”,第一個結果是https://ecc.uic.edu/career-fairs,我認為所有結果都與職業博覽會,職業服務,活動,活動和就業有些相關,我將精確: P = 1.0與此查詢。
查詢: “研究助手”,第一個結果是http://grad.uic.edu/assistanthips,我認為除最後一個與助手有關的是RA,TA或GA,僅僅是因為UIC域沒有RA的特定頁面,所以我將提供精確的: P = 0.9 to to to to to to to to to ie ceery。
查詢: “實習和工作”,第一個結果是https://careerservices.uic.edu/students/internships,這次只有6個網頁是相關的,但是,這些網頁仍然與職業和就業無關。我將給出一個精度: p = 0.6對此查詢。
查詢: “學生中心東地址”,第一個結果是https://fimweb.fim.uic.edu/buildingsdata.aspx,此查詢更加具體,更複雜,實際上只有從4個結果中,我們實際上能夠提取建築物的地址,但是所有其他結果,但是所有其他結果,都在談論East的學生中心,這仍然不是那樣。我將給出一個精度: p = 0.4對此查詢。
平均精度為0.78 ,每個查詢至少返回一個相關結果的事實,我認為結果是離散的。
我嘗試的第一個智能是簡單而簡單的頁面排名。在對頁面的預處理進行預處理時,提取了鏈接,並基於創建世界圖的鏈接連接。頁面排名的實現使其與整個圖創建了一個強烈的組件,這意味著從每個節點可以從每個節點中獲得具有非null概率的另一個節點。通過這種解釋,隨機步行者不可能被卡在頁面中。
頁面排名很難集成到文檔的評分中以對其進行排名。首先,我嘗試僅將餘弦相似性和頁面排名的線性組合進行線性組合,看看它是如何工作的,這很糟糕,因為如果頁面排名的重量遠遠超過主頁和其他權威頁面,那麼結果總是會出現在結果中。相反,如果重量更傾向於餘弦相似性,那麼頁排名根本就不會產生效果。
第二次嘗試產生了相當不錯的結果。我基本上只是僅使用了所有其他結果,並認為他們是非與之相關的。然後,我將線性組合與頁面排名進行。這次之所以起作用,是因為它只是已經相關文檔的不同置換,例如,本主頁和其他權威文件目前已經被丟棄。
我認為,在這種類型的應用程序中,頁面排名的目的是實現的,我能夠偏向正常的搜索,以考慮更相關的更具權威的頁面,以便用戶更有可能找到與他在查詢中類型的結果相似的結果之外,除了結果非常相似。
上下文偽重複反饋( CPRF ),我想出了我的原理和自定義智能組件的想法,將近一個月以來。當我實施時,我不確定它是否會按預期工作,我真的很害怕我無所事事。
當我想到網絡搜索引擎可以擁有哪種智能組件時,我認為如果我們能猜測用戶查詢的上下文並給予他除了他專門要求的內容外,那將是很好的,這些結果與他所搜索的內容非常相關。基於同義詞的簡單靜態查詢擴展將太簡單,無法捕獲相關但具有不同語義的內容。
但是,起點總是必須是用戶的查詢,因為除了最初,別無其他。我真的很喜歡偽交易反饋如何讓您以自動方式重新重新查詢的想法。當然,當詢問用戶要在他的查詢中包含哪些其他單詞時,明確的相關性反饋可能會更好,但是與此同時,他在搜索時必須回答一些問題可能會很煩人。偽交易反饋似乎是一種更合適,更簡單的方法,可以在後台運行一些更複雜的查詢,甚至不知道。
為了提取一些可以表達公式查詢的上下文的單詞,我決定使用一些最初檢索文檔的固有信息。特別是,我認為文檔中具有最高tf-idf的單詞可以代表該文檔的主題,及其與其他文檔的區別,因為當許多文檔中沒有包含該單詞時,TF-IDF很高,但該文檔中的複發是很高的。
提取上下文單詞的過程如下:從排名的文檔中,我選擇了number_docs_expansion文檔,我將其設置為30,但可以在pseudo_relevance_feedback.py中更改。 ,對於每個文檔,我將帶有最高tf-idf(常數number_top_tokens)的令牌和對於其中的每個不同令牌所示,如果存在單詞,則將每個文檔的所有tf-idf總結。最後,我對令牌進行排名,排名最高的單詞是代表查詢上下文的每個檢索文檔的常見單詞。然後,我返回n個擴展的單詞(常數number_expansion_tokens)設置,將原始的查詢令牌減去,以免重複重複,並且對這些單詞賦予了過多的重要性。
擴展的令牌將具有差異的重量,少於查詢中的原始單詞,可以在statistics.py腳本中更改此e_const。
根據我嘗試的查詢,我認為智能組件在某些情況下確實給出了一些改進。
始終有效的第一個重要結果是能夠擴展檢索到的文檔的集合,實際上,如果只有幾個文檔包含查詢中的任何單詞,則普通搜索引擎只能檢索那些文檔。取而代之的是,使用CPRF SMART組件,結果集將更大,並且可能始終導致檢索到的尺寸超過100個文檔。
我在某些查詢中註意到的另一個積極結果是,它實際上找到了我要尋找的目的,而簡單的搜索引擎甚至沒有在前十個結果中找到它。可以通過搜索“計算機科學課程”來觀察一個例子,我想找到的是UIC計算機科學系提供的所有主要課程的列表。這是當智能組件處於活動狀態時,發動機檢索的第一個結果。相反,如果不激活它,該頁面就不在第一個結果中。
最後,我試圖搜索“信息檢索” ,沒有CPRF的搜索引擎非常糟糕,第一個結果是UIC部門的搜索頁面,這也可能是因為在UIC域中沒有信息檢索頁面,或者僅包含在域中。但是,隨著智能組件的啟用,發現了許多與此相關的網頁,其中兩個是“ Cornelia Caragea”,教授在這本課程的教授中,許多頁面確實與她的出版物和信息檢索方面的工作有關,這也是搜索引擎的一個很好的屬性。如果找不到非常相關的結果,它仍然能夠找到有關相關事物的最佳結果。
正如5.3在我進行了普通搜索引擎和使用智能組件之間進行比較時所解釋的那樣,我認為產生的結果非常好,當我考慮這一點時,我得到了期望。我通過測試發現的摘要是:
即使原始查詢僅輸出一堆網站,也可以找到更多結果的能力。
像我在第5.3段中解釋的那樣,在查詢“計算機科學課程”的查詢“計算機科學課程”中找到我實際尋找的內容的能力。
即使語料庫不包含與查詢非常相關的頁面以及用戶正在搜索的內容,我還注意到此查詢“信息檢索”,如第5.3段所述的查詢“信息檢索” 。
一種向我表明這產生正確結果的方法是,在代表上下文的前10個擴展單詞中,存在屬於用戶查詢的某些單詞。這說明了該方法如何有效地捕獲主題,並且沒有其他方法可以描述該集合中的其他單詞,即使不是作為與原始查詢中相同上下文的單詞相同的單詞。
談論頁面排名。我認為它可以完成工作,但是它不會以我實施的方式改變排名太多,這只是一種偏向結果的方式,以便如果有的話,更喜歡更有權威的頁面。
可以肯定的是,必須從這裡解決的一件事是超參數調整。這是最困難的事情,主要是因為缺乏標記的數據。我不知道,如果我無法評估查詢的精度,則哪個值的效果更好,並且為了自動對其進行調整,應該有很多已經標記的數據。