一. 信息檢索技術簡述
信息檢索技術是當前比較熱門的一項技術,我們通常意義上的論文檢索,搜索引擎都屬於信息檢索的范疇。信息檢索的問題可以抽象為:在文檔集合D上,對於關鍵詞w[1]…w[k]組成的查詢串q,返回一個按查詢串q和文檔d匹配度relevance(q,d)排序的相關文檔列表D。
經典的信息檢索模型包括布爾模型,向量模型,TF-IDF模型。布爾模型以集合的布爾運算為基礎,查詢效率高,但模型過於簡單,無法有效地對不同文檔進行排序,所以查詢效果不佳。向量模型把文檔和查詢串都視為詞所構成的多維向量,而文檔與查詢的相關性即對應於向量間的夾角。不過,由於通常詞的數量巨大,向量維度非常高,而大量的維度都是0,計算向量夾角的效果並不好。加上龐大的計算也使得向量模型幾乎不具有在互聯網搜索引擎這樣海量數據集上實施的可行性。TF-IDF模型目前廣泛被應用於搜索引擎等實際應用中。其主要思想是:如果詞w在一篇文檔d中出現的頻率高,並且在其他文檔中很少出現,則認為詞w具有很好的區分能力,適合用來把文章d和其他文章區別開來。
二. TF-IDF模型
1. 概念
1)詞w在文檔d中的詞頻tf(Term Frequency),指詞w在文檔d中出現的頻率。
tf(w, d)=count(w, d) / size (d)
2)詞w在整個文檔集合中的逆向文檔頻率idf(Inverse Document Frequency), 即文檔總數n與詞w所出現文件數docs(W, D)比值的對數:
idf = log (n / docs (W, D))
3)Tf-idf模型通過計算tf和idf為每一個文檔d和由關鍵詞w[1]…w[k]組成的查詢串q計算一個權值,用於表示查詢串q與文檔d的匹配度:
Tf-idf (q, d)
= sum { i=I …k | tf-idf(w[i], d) }
= sum { i=1…k | tf(w[i], d) * idf( w[i]) }
2.應用(處理包含14個TXT文檔的語料庫)
1)分別處理各個TXT,計算詞頻。
import nltk from nltk.corpus import * def mid_text_dir(): corpus_root=r"D:\segfile" wordlists=PlaintextCorpusReader(corpus_root, '.*') return wordlists def getTextTermFreq(wordlists): filelist=wordlists.fileids() path='D:/mi-result/' for file in filelist: word=wordlists.words(file) vocab=set(word) f1=open(path+file+'.txt', 'w+') tip="the text has %d different words and the sum of vocab is %d" % (len(vocab),len(word)) print(tip) f1.write(tip) f1.write('----------------------\n\n') fdist=nltk.FreqDist(word) for w in vocab: f1.write(w.ljust(25)+str(fdist[w]).ljust(10)+str(fdist[w]/len(word))+'\n') f1.close() print(tip)
運行結果如下截圖:
2)運用TF-IDF算法
def getFilelist(path) : //訪問目標語料庫,獲得文件列表 filelist = [] files = os.listdir(path) for f in files : if(f[0] == '.') : pass else : filelist.append(f) return filelist,path def fenci(argv,path) : //分詞,並保存文件 sFilePath = 'D:/my_segfile/' if not os.path.exists(sFilePath) : os.mkdir(sFilePath) filename = argv try: f = open(path+filename,'r+', encoding= 'gbk') file_list = f.read() except UnicodeDecodeError: f = open(path+filename,'r+', encoding= 'utf-8') file_list = f.read() f.close() seg_list = jieba.cut(file_list,cut_all=True) result = [] for seg in seg_list : seg = ' '.join(seg.split()) if (seg != '' and seg != "\n" and seg != "\n\n") : result.append(seg) f = open(sFilePath+"/"+filename+"-seg.txt","w+") f.write(' '.join(result)) f.close() def Tfidf(filelist) : //運用TF-IDF算法進行匹配度計算, 該算法首先遍歷所有文件,獲得所有單詞的列表,然后以文章為元素,每個文章保存相同位置的詞的詞頻,然后分別計算每個詞的詞頻。 path = 'D:/segfile/' corpus = [] for ff in filelist : fname = path + ff f = open(fname,'r+') content = f.read() f.close() corpus.append(content) vectorizer = CountVectorizer() transformer = TfidfTransformer() x= vectorizer.fit_transform(corpus) print ("line of x.toarray is %d" % len(x.toarray())) print ("rows of x.toarray is %d" % len(x.toarray()[0])) tfidf = transformer.fit_transform(vectorizer.fit_transform(corpus)) word = vectorizer.get_feature_names() f = open('D:/mi-result/Word.txt','w+') for i in word: f.write(i.ljust(20)) f.close() Term_freq=x.toarray() for h in range(len(Term_freq)): temp_path="D:/mi-result/Term_frequence_text%d.txt" % h f = open(temp_path,'w+') for i in range(len(Term_freq[0])): f.write(word[i].ljust(25)+""+str(Term_freq[h][i])+"\n") f.close() weight = tfidf.toarray() sFilePath = 'D:/tfidffile' if not os.path.exists(sFilePath) : os.mkdir(sFilePath) for i in range(len(weight)) : print ("--------Writing all the tf-idf in the %d file into %s/re%d.txt--------" % (i, sFilePath, i)) path= "%s/re%d.txt" % (sFilePath, i) ##f = open(sFilePath+'/re'+i+'.txt','w+') f = open(path,'w+') for j in range(len(word)) : f.write(word[j].ljust(25)+""+str(weight[i][j])+"\n") f.close() if __name__ == "__main__" : wordlists=mid_text_dir() getTextTermFreq(wordlists) argv='D:/segfile/' (allfile,path) = getFilelist(argv) for ff in allfile: print ("Using jieba on %s " % ff) fenci(ff,path) Tfidf(allfile)
運行結果如下: