机器学习算法之TF-idf

机器学习算法之TF-idf tfidf算法是一种文本特征提取方法。tf词频单词在当前文档中的频率局部重要性idf逆文档频率单词在所有文档中的稀缺程度全局重要性tf-idf以上两者的乘积衡量单词在当前文档中的重要性和在所有文档中的特殊性一个词在当前文档中出现次数越多TF高且在其它文档中出现越少IDF高它的TF-IDF值就越高说明这个词对该文档越有代表性也就是每一篇文章中的关键词。我们平时所用的百度谷歌等浏览器这些大型的搜索引擎就是这个原理。这些搜索引擎其实是一个巨大的爬虫系统根据公开的域名爬取网页提取网页中的关键词形成一个自己的索引数据库当我们输入搜索内容的时候就先会在其数据库中搜索然后再按照相关性排序呈现给我们。一、TF-idf简单案列采用简单且小型的数据内容每一行当做一篇文章from sklearn.feature_extraction.text import TfidfVectorizer import pandas as pd inFileopen(rD:\人工智能\机器学习算法\机器学习课件\10、TF-IDF\task2_1.txt,r) corpusinFile.readlines()#当做一个语料库 vectorizerTfidfVectorizer()#定义类对象TfidfVectorizer是一个类 tfidfvectorizer.fit_transform(corpus)#计算tfdif值数据不用做预处理可以直接被处理 print(tfidf) wordlistvectorizer.get_feature_names()#获取语料库所有单词 print(wordlist) dfpd.DataFrame(tfidf.T.todense(),indexwordlist)#tfidf.T.todense()转置稀疏矩阵转为稠密矩阵 #转置的意思就是原本数据是六行十四列转置之后就是十四行六列 print(df) for j in range(len(corpus)):#对每一篇文章的词按照tfidf值降序排列 featurelistdf.iloc[:,j].to_list()#通过索引号第二列的内容并转换为列表 resdict{}#循环排列每一篇文章中单词的逆文档频率 for i in range(0,len(wordlist)): resdict[wordlist[i]]featurelist[i] resdictsorted(resdict.items(),keylambda x:x[1],reverseTrue) print(resdict)#这里是利用sorted方法进行排序需要注意第一个输出输出的tfidf括号0,1的意思是第0篇文章中的第一个词的tfidf值是0.4489258246711445第0篇就是第一篇但是第一个词并不是该篇文章的第一个词而是整个语料库的中的第一个值也就是我们第二个输出第一个词就是document在代码中提到的稀疏矩阵可以观察第一个输出的内容只存该篇文章出现的词tfidf为0的跳过如果把原本某篇文章中没有但在语料库有的词也添上他们的tfidf值为0例如这里会补上0,0tfidf0 0,2tfidf0……那就是稠密矩阵第三个输出最终结果部分二、红楼梦案例红楼梦txt是120回内容每章前有标题分为上卷下卷1.把红楼梦txt每一回分为一章原文文本文件有一个红楼梦开头并不是章节内容所以把他单拿出来作为红楼梦开头txt文件for循环进行遍历每篇开头有标题以‘卷 第’作为寻找标题的判断如果是标题就进行if中代码块将标题作为章节文件名然后继续读取文件第一次找到标题会运行flag0的代码块创建之后读取的内容都写入第一个章节里知道下一个标题被遍历到但是这里原文件文本标题后有两行没用一行是该章节的字数时间等信息一行为空行为了后续方便操作所以这两行不要写入文件这里我使用了变量line_count0记录当前是第几行从第三行开始写入当然也要满足每次新找到一个标题时这个count要重新赋值为0import os #python标准库不需要安装。关于操作系统的库 if not os.path.exists(红楼梦\\红楼梦章节): os.makedirs(红楼梦\\红楼梦章节) file open(rD:\人工智能\机器学习算法\机器学习课件\10、TF-IDF\红楼梦\红楼梦.txt,encodingutf-8)# flag 0#用来标记当前是不是在第一次保存文件 line_count 0 juan_file open(.\红楼梦\红楼梦卷开头.txt,w,encodingutf-8) for line in file: #开始遍历整个红楼梦 if 卷 第 in line: #找到标题 line_count 0 juan_name line.strip() .txt path os.path.join(.\\红楼梦\\红楼梦章节 , juan_name)#构建一个完整的路径 print(path) if flag 0: #判断是否 是第1次读取到 卷 第 juan_file open(path,w,encodingutf-8) #创建第1个卷文件 flag 1 else: #判断是否 不是第1次读取到 卷 第 juan_file.close() #关闭第1次及 上一次的文件对象 juan_file open(path,w,encodingutf-8) #创建一个新的 卷文件 continue if line_count 2:#是因为原文中标题之后有一行为无用信息一行为空我们从第三行才开始写入 line_count 1 continue else: juan_file.write(line)#然后写入其他行 juan_file.close() file.close()2.开始分词分成标准形式1分词需要用到jieba库分词前需要有分词的词库红楼梦词库.txt2文本内容比较多减轻计算量可以不计算标点、常见词、语气词等词这些词不会影响结果叫做停用词词库stopwordCN.txt这里stopword是表头单列列表获取该列所有值导入库 import jieba import os import pandas as pd import codecs #加载自定义词库:让jieba正确识别红楼梦的专有名词 jieba.load_userdict(rD:\人工智能\机器学习算法\机器学习课件\10、TF-IDF\红楼梦分析\红楼梦词库.txt) #加载停用词:删除无意义的词和标点符号 stopwords pd.read_csv(rD:\人工智能\机器学习算法\机器学习课件\10、TF-IDF\红楼梦分析\StopwordsCN.txt, encodingutf8, enginepython,index_colFalse) stopwords_liststopwords[stopword].tolist() 读取文件内容 filepaths[]#用来存储每个文件的完整路径 filecontents[]#存储每个文件的内容 for root,dirs,files in os.walk(./红楼梦/红楼梦章节):#遍历目录下所有文件 #遍历当前目录下的所有文件 for name in files: filepathos.path.join(root,name)#拼接完整文件路径 filepaths.append(filepath)#存储文件路径 fcodecs.open(filepath,r,utf-8)#打开文件 filecontentf.read()#读取文件全部内容 f.close() filecontents.append(filecontent)#存储文件内容 #创建DataFrame表格两列分别为文件路径和文件内容 corpospd.DataFrame({filepath:filepaths,filecontent:filecontents}) 中文分词处理 segmented_text[]#存储分词结果 for content in filecontents: wordsjieba.lcut(content)#使用jieba进行分词 #过滤停用词 filtered[w for w in words if len(w.strip())1#过滤条件长度1不在停用表中至少包含一个中文字符 and w.strip() not in stopwords_list and any(\u4e00 c \u9fff for c in w)] segmented_text.append(filtered)#存储过滤后的分词结果 corpos[segmented]segmented_text#将分词结果添加到dataframe表格第三列分词结果列表 corpos[word_count][len(words) for words in segmented_text]#第四列计算每篇的词数量 保存分词结果 output_txt r全部分词结果.txt#定义输出文件路径 # 将分词结果合并每章用空格连接词语文章之间用换行分隔 all_segmented\n.join([ .join(seg) for seg in corpos[segmented]]) # 写入文件 with open(output_txt, w, encodingutf-8) as f: f.write(all_segmented)标准形式这种形式就和一开始做的小语料库案例一样的形式一行是一篇文章这些文章的词库就组成了一个语料库3.计算tfidf值并排序从大到小进行排序可以根据输出结果得知该篇文章的关键词from sklearn.feature_extraction.text import TfidfVectorizer#tfidf向量化工具 import pandas as pd#数据处理 inFile open(rD:\learn\全部分词结果.txt, r,encodingutf-8) corpus inFile.readlines()#返回一个列表列表一个元素就是一行内容一行是一章 vectorizer TfidfVectorizer() #类转为TF-IDF的向量器 tfidf vectorizer.fit_transform(corpus) #计算tfidf矩阵 wordlist vectorizer.get_feature_names() #行是章节列是所有词语 df pd.DataFrame(tfidf.T.todense(), indexwordlist)#tfidf.T.todense()#转置 for i in range(len(corpus)):#遍历每章 featurelist df.iloc[:,i].to_list()#获取章的所有词的tfidf值 resdict {} #创建字典 for j in range(0, len(wordlist)): resdict[wordlist[j]] featurelist[j] #[(贾宝玉,0.223),()] #tfidf降序排列 resdict sorted(resdict.items(), keylambda x: x[1], reverseTrue) print(第{}回的核心关键词.format(i1),resdict[0:10])#打印前十个结果部分