一. 信息检索技术简述
信息检索技术是当前比较热门的一项技术,我们通常意义上的论文检索,搜索引擎都属于信息检索的范畴。信息检索的问题可以抽象为:在文档集合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)
运行结果如下: