最近《資訊檢索》課程的homework,要評價資訊檢索評價名額,涉及到一些小東西,比如說pooling method(緩沖池)的計算、MAP values的計算、畫P-R圖,于是記錄下來。
先上作業:
圖1:作業
評價過程:
1.pooling method
先找到自己想要輸入的3個query,到4種搜尋引擎,取回前30條連結。共120個url,需要找到所有相關文檔,周遊所有網頁,查找相關文檔幾乎是不可能的任務,于是,便有pooling method,人工判斷四個搜尋引擎的120網頁是否搜到了query相關的,然後在這120個url中(對url進行去重,4個搜尋引擎搜到的肯定有重複的,重複的url去掉,剩下比如104個,在104個中找),有多少個是相關的,作為總的相關數也即A+C的個數,對應着各搜素引擎在30個中搜到了多少個相關的,以判别搜尋引擎的性能。
圖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.結果:
圖3:“命中摯愛”的PR-圖
6.小感想
最後計算MAP值,出來的結果不科學。搜狗居然赢了,吓尿了~!發現是其相關文檔少了,反而成為了優勢。另外的話,資料量太少了,隻有30個,資料量少的時候用MAP判斷搜尋引擎的性能可能不太好。還有關于曲線平滑的問題,在後面的高于前面,這一點也是不太合理,也沒深入分析~,~.......