天天看點

資訊檢索:對搜尋引擎性能的評價名額的小作業---pooling方法以及MAP value的計算

最近《資訊檢索》課程的homework,要評價資訊檢索評價名額,涉及到一些小東西,比如說pooling method(緩沖池)的計算、MAP values的計算、畫P-R圖,于是記錄下來。

先上作業:

資訊檢索:對搜尋引擎性能的評價名額的小作業---pooling方法以及MAP value的計算

圖1:作業

評價過程:

1.pooling method

先找到自己想要輸入的3個query,到4種搜尋引擎,取回前30條連結。共120個url,需要找到所有相關文檔,周遊所有網頁,查找相關文檔幾乎是不可能的任務,于是,便有pooling method,人工判斷四個搜尋引擎的120網頁是否搜到了query相關的,然後在這120個url中(對url進行去重,4個搜尋引擎搜到的肯定有重複的,重複的url去掉,剩下比如104個,在104個中找),有多少個是相關的,作為總的相關數也即A+C的個數,對應着各搜素引擎在30個中搜到了多少個相關的,以判别搜尋引擎的性能。

資訊檢索:對搜尋引擎性能的評價名額的小作業---pooling方法以及MAP value的計算

圖2:人工判斷的搜尋引擎傳回的連結的相關性并存着

2.P-R圖

根據P-R圖判斷各搜尋引擎對同一query搜尋傳回結果的性能,用基于ranking(排名)的方法計算P、R值,周遊搜尋引擎找到的連結,判斷周遊到的url有多少是相關的,也即是檢索到并且相關的A的個數,周遊過去,也即檢索到的所有的個數A+B=1-->30(如果存了搜尋引擎傳回來的30條url),找到30個點,也就可以畫P-R圖了,實際上畫出來的圖會是,鋸齒狀的,需要做些平滑。可取同一R處多個P的最高點處,取其平均,取其XX等各種方法平滑。有了點,可以用各種方法畫圖了,excel,matlab,直接在代碼裡用python畫圖來的更直接。

3.計算MAP值

MAP(Mean Average Precision):單個主題的平均準确率是每篇相關文檔檢索出後的準确率的平均值。主集合的平均準确率(MAP)是每個主題的平均準确率的平均值。 MAP 是反映系統在全部相關文檔上性能的單值名額。系統檢索出來的相關文檔越靠前(rank 越高),MAP就可能越高。如果系統沒有傳回相關文檔,則準确率預設為0。

例如:假設有兩個主題,主題1有4個相關網頁,主題2有5個相關網頁。某系統對于主題1檢索出4個相關網頁,其rank分别為1, 2, 4, 7;對于主題2檢索出3個相關網頁,其rank分别為1,3,5。對于主題1,平均準确率為(1/1+2/2+3/4+4/7)/4=0.83。對于主題 2,平均準确率為(1/1+2/3+3/5+0+0)/5=0.45。則MAP= (0.83+0.45)/2=0.64。”(參考:http://blog.sina.com.cn/s/blog_662234020100pozd.html)

4.code

#coding:utf-8
'''
Created on 2014年10月27日
'''
import codecs
import pylab as pl
s_file=u"D:/搜狗高速下載下傳/k網絡資訊檢索/IR_homework2work/query_"
url_txt="_url.txt"
list_query=[u"無限開關",u"命中摯愛",u"longkissgoodbye"]
list_se=[u"baidu",u"bing",u"google",u"sogou"]
#将3個120的url去掉重複的,比如說剩下78,82,95,并且将其存到字典中,
#要保證url的相關性,存0/1,故不使用set()
remove_repeat=[{},{},{}]                        
#--------------------------------------------
num=0
for i in range(len(list_query)):                    #i,分别為0,1,2代表着具體的query
    for j in range(len(list_se)):                           #j。分别代表着各種se
        #print "以下是在:\"",list_se[j],"\"中搜尋\"",list_query[i],"\"的結果"
        s_dir=s_file+list_query[i]+"/"+list_se[j]+url_txt            #
        with codecs.open(s_dir) as file_url:
            text_url=file_url.readlines()
        for line in text_url:                   #周遊每一行,取url及相關文檔判别标志
            line=line.decode("utf-8")
            #------------------------------直接把整行line投到set()裡去重,也行,但還是要解析-
            list_01_url=line.split(" ")           #前段處理已用空格隔開0/1和url
            url=list_01_url[1].strip("\n")        #去掉換行符,
            #print type(url),type(remove_repeat[i])
            if url in remove_repeat[i].keys():
                pass
            else:#将i分别為無限開關,XX,XX,的120個url去重存到remove_repeat[i]中
                remove_repeat[i][url]=int(list_01_url[0])
            num=num+1
#
#去重後,相關文檔的個數
list_rel_url=[0,0,0]
for i in range(len(remove_repeat)):
    for j in remove_repeat[i].keys():
        if remove_repeat[i][j]==1:
            list_rel_url[i]=list_rel_url[i]+1
    print "去重後剩下url分别為:",len(remove_repeat[i])
print "去重後相關url分别為:",list_rel_url
print 30*"**"
#---------------------------
for i in range(len(list_query)):                    #i,分别為0,1,2代表着具體的query
    for j in range(len(list_se)):                           #j。分别代表着各種se
        num_url=0
        num_30line=0
        list_R=[]
        list_P=[]
        list_num_url_line=[]
        print "以下是在:\"",list_se[j],"\"中搜尋\"",list_query[i],"\"的結果"
        s_dir=s_file+list_query[i]+"/"+list_se[j]+url_txt            #
        with codecs.open(s_dir) as file_url:
            text_url=file_url.readlines()
        for line in text_url:                   #周遊每一行,取url及相關文檔判别标志
            line=line.decode("utf-8")
            #------------------------------直接把整行line投到set()裡去重,也行,但還是要解析-
            list_01_url=line.split(" ")           #前段處理已用空格隔開0/1和url
            url_rel=int(list_01_url[0])
            url=list_01_url[1].strip("\n")        #去掉換行符,
            if url_rel==1:                      #周遊30個,遇到了1,就得到一個點,P-R圖,不必畫30個點,
                num_url=num_url+1
                num_30line=num_30line+1
                R=num_url*1.0/list_rel_url[i]
                P=num_url*1.0/num_30line
                list_num_url_line.append(num_30line)        #将那些出現1的行數,記錄下來,用來算MAP值
            else:
                num_30line=num_30line+1
            list_R.append(R)
            list_P.append(P)
        #計算MAP值
        print "人工判斷,有",num_url,"個相關的"
        print list_query[i],"在",list_se[j],"下的MAP值為:",sum([1.0/k for k in list_num_url_line])*1.0/num_url
        #周遊完了30行,并且資料分别存到了list_R和list_P中,就可以開始畫圖了
        #s_title=list_query[i].decode('utf-8')
        #pl.title(s_title)                        #在圖檔中,沒發顯示中文,亂碼了嗎
        pl.xlabel(u"Recall")
        pl.ylabel(u"Precision")
        pl.plot(list_R,list_P,label=list_se[j])
        pl.legend()
    pl.savefig(s_file+list_query[i]+"/"+list_query[i]+"_PR.png")    #需要放到show()前面,不然存下來的圖檔為空白
    pl.show()       #待畫好了四張圖,再展示出來
    print 30*"**"
           
5.結果:
資訊檢索:對搜尋引擎性能的評價名額的小作業---pooling方法以及MAP value的計算

圖3:“命中摯愛”的PR-圖

6.小感想

最後計算MAP值,出來的結果不科學。搜狗居然赢了,吓尿了~!發現是其相關文檔少了,反而成為了優勢。另外的話,資料量太少了,隻有30個,資料量少的時候用MAP判斷搜尋引擎的性能可能不太好。還有關于曲線平滑的問題,在後面的高于前面,這一點也是不太合理,也沒深入分析~,~.......