盲反饋檢索系統實驗記錄一

在進行實驗之前,先了解相關反饋和盲反饋的一些概念:

相關反饋是基於用戶的,由用戶標出初次查詢結果相關還是不相關,再經過Rocchio算法或其他算法使檢索結果更能滿足用戶需求;

盲反饋也稱僞反饋,是由計算機自動處理檢索結果,不需要用戶的參與也可以得到比較滿意的檢索效果。這種方法假定用戶初始檢索結果的前k篇文檔是相關的,再由系統抽選出這k篇文檔的特徵詞,然後把這些特徵詞和初始查詢詞再放入搜索框中進行二次檢索,這種行爲我們稱之爲“擴展查詢詞”。通過擴展查詢詞可以提高檢索系統的性能。

 本項目就是基於盲反饋理論以及結合相應算法編寫一個檢索系統,並通過一系列的評價指標來測試此係統的性能。本系統是經過小組成員結合相關理論後而確定實施的,本文從項目最初代碼的編寫,直到一個檢索系統的成功運行,以及涉及到的信息檢索的理論,筆者都會一一講解。


編程環境的準備:PHP+MySQL+Apache(項目初期沒有使用MySQL,隨着後期數據集的增大,可以考慮)

額外知識:HTML+CSS+JS+Ajax(主要用於前臺的顯示)


語料庫:本實驗使用搜狗實驗室提供的語料庫http://www.sogou.com/labs/dl/c.html

       在測試時筆者使用的是mini版的10篇IT新聞(文件目錄名問C000010)


在代碼編寫過程中,筆者先使用過程化的方法,然後再把各個功能封裝到Tool.class.php的工具類中,便於以後代碼重用。


首先,建立自己的詞表。

筆者是這樣考慮的,假如有三篇文檔,文檔內容爲:

(html html)

(java html java)

(python java)

先對這三遍文檔去重,

(html)

(java html)

(python java)

然後合併這三篇文檔:

(html java html python java)

然後再對其去重,並且按字母升序排列:

(html java python)

這樣就可以得到我們自己的詞典了。

那爲什麼我們不直接把最初的三篇文檔先合併再去重,這樣不就可以省去對三篇文檔分別去重這一步了嗎?事實上我們也是這樣做的,上面是爲了便於我們理解我們的文檔頻率df是怎麼計算出來的,由紅色字體部分我們可以知道,有多少個重複的詞,這個詞的的文檔頻率就是多少。比如html的df爲2,java的爲2,python爲1.

在中文分詞系統中,我們採用的是分詞工具SCWS,使用PHP調用他提供的方法get_tops可以得到分詞的情況,在內部他已經幫我們對每篇文檔去了重,並且計算出了每個詞的出現的次數times。


我們先來了解一下初始配置文件init.inc.php

<?php
define('TEXT_PATH','D:\AppServ\www\BlindFeedback\SogouC.mini.20061127\SogouC.mini\Sample\C000010');
define('ROOT_PATH',dirname(__FILE__));
require_once 'func.inc.php';
require_once 'Tool.class.php';
?>

此文件定義了兩個常量,TEXT_PATH是保存搜狗實驗室的10篇IT新聞的硬路徑,ROOT_PATH是系統存儲位置的硬路徑;然後是require引入的兩個文件,func.inc.php用來存放使用到的函數,以後會講到;Tool.class.php存放系統主要的功能,隨着功能的增多,可能會再創建一個類。以後需要用到的配置都存放到這個文件中。


在Tool.class.php文件中我們定義了一個靜態方法,用來獲得並存儲詞表:

class Tool{
        //獲取並存儲詞表
        static public function dic($seg){
            $dic=array();   //詞表
            for($i=0;$i<count($seg);$i++){
                for($j=0;$j<count($seg[$i]);$j++){
                    array_push($dic,$seg[$i][$j]['word']);
                }
            }
                                                                                                                                                                                                                                                                                                                                                                                                                    
            $dic=array_unique($dic);
            sort($dic);
            $dic=implode(',',$dic);
                                                                                                                                                                                                                                                                                                                                                                                                                    
            //把詞表存儲起來
            $fp=fopen('dic.txt','w');
            if(!$fp) exit('詞典打開失敗!');
            if(!fwrite($fp,$dic)) exit('詞典寫入失敗!');
            fclose($fp);
        }
?>



這個方法需要傳遞一個參數,這個參數是由Tool.class.php裏定義的一個分詞方法segment得來的,稍後會講到。變量$seg是一個三維數組,$seg[i][j][]表示第i篇文檔的第j個詞。通過兩個for循環,把該詞壓入數組$dic中(array_push方法可以壓入具有相同值的元素),然後array_unique對$dic去重,再按中文拼音字母升序排列,一個數組形式的詞表產生了。爲了把該詞表存入文件名爲dic的txt文件中,需要使用imploded方法把數組通過“,”連接成字符串,然後在使用文件方法fopen把詞表存入dic.txt.


上面提到的segment分詞方法代碼如下:

//scws分詞
static function segment($str){
                                                                                                                                                                                                                    
    if(!$scws=scws_new()) exit('創建SCWS對象失敗!');      //創建SCWS
    $scws->set_charset('gbk');   //設置字符集
    if(!$scws->set_dict('C:\Program Files\scws\dict.xdb')) exit('詞典路徑設置失敗!');
    $scws->set_multi(1);
    $scws->set_ignore(true); //忽略標點
                                                                                                                                                                                                                    
    if(is_string($str)){
        $scws->send_text($str);
        $top=$scws->get_tops(800);
    }else if(is_array($str)){
        for($i=0;$i<count($str);$i++){
            $scws->send_text($str[$i]['con']);
            $top[]=$scws->get_tops(800);
        }
    }
    return $top;
                                                                                                                                                                                                                    
}



該方法需要傳第一個參數該參數可以說字符串,也可以是包含內容的數組。可以使用下面介紹的fileStr方法獲取10篇IT新聞的內容並把它們存入數組中。segment方法內部都是調用SCWS提供的分詞方法,如需詳細瞭解可以到SCWS官網查看文檔(該項目開源)。筆者只介紹get_tops方法,該方法返回的是最終的分詞結果:

wKiom1M6JfvBGkoWAAENiFJxhhw319.jpg

wKioL1M6JdOxop0BAAE2zJG3llE417.jpg

由於詞的數量太多,以後實驗效果截圖只截取前面和最後的部分。可以看到get_tops的返回結果是一個三維數組[word]表示所截取的詞,[times]表示詞頻,[weight]表示權重(不是我們所瞭解的tf*idf),[attr]表示詞性。get_tops方法已經爲我們除去了大部分無意義的詞。與get_tops相對應的是get_result,它返回的是所有分好的詞,包括停用詞、標點符號等。





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章