python数据挖掘实战笔记——文本挖掘(7):TF-IDF原理

概念:

  • 词频(Term Frequency):指的是某一指定的词在该文档中出现的次数。 逆文档频率(Inverse Document
  • Frequency):IDF就是每个词的权重,它的大小与一个词的常见程度成反比。
  • TF-IDF:衡量某个词是否关键词的指标,该值越大,是关键词的可能性就越大。
  • 计算公式:
  • TF=该词在文档中出现的次数。
  • IDF=log(文档总数/包含该词的文档数+1)
  • TF-IDF=TF*IDF
    上代码:

首先构建语料库:

import numpy

#创建语料库
import os;
import os.path;
import codecs;

filePaths = [];
fileContents = [];
for root, dirs, files in os.walk(
    r"C:\Users\www12\Desktop\data\2.7\\SogouC.mini\\Sample"
):
    for name in files:
        filePath = os.path.join(root, name);
        filePaths.append(filePath);
        f = codecs.open(filePath, 'r', 'utf-8')
        fileContent = f.read()
        f.close()
        fileContents.append(fileContent)

import pandas;
corpos = pandas.DataFrame({
    'filePath': filePaths, 
    'fileContent': fileContents
})

进行分词处理

import re

zhPattern = re.compile(u'[\u4e00-\u9fa5]+')  #正则表达式识别中文词

import jieba
#分词
segments = []
filePaths = []
for index, row in corpos.iterrows():
    filePath = row['filePath']
    fileContent = row['fileContent']
    segs = jieba.cut(fileContent)
    for seg in segs:
        if zhPattern.search(seg):  #过滤非中文词
            segments.append(seg)
            filePaths.append(filePath)
#得到分词结果
segmentDF = pandas.DataFrame({
    'filePath':filePaths, 
    'segment':segments
})

接着跟之前的代码一样,去掉停用词

#移除停用词
stopwords = pandas.read_csv(
    "D:\\PDM\\2.7\\StopwordsCN.txt", 
    encoding='utf8', 
    index_col=False,
    quoting=3,
    sep="\t"
)

segmentDF = segmentDF[
    ~segmentDF.segment.isin(
        stopwords.stopword
    )
]

进行词频统计:

#按文章进行词频统计
segStat = segmentDF.groupby(
    by=["filePath", "segment"]
)["segment"].agg({
    "计数":numpy.size
}).reset_index().sort_values(
    by=["计数"],
    ascending=False
)
#把小部分的数据删除掉
segStat = segStat[segStat.计数>1]

结果如图:
在这里插入图片描述
接着对文档进行向量化处理:

#进行文本向量计算
tf = segStat.pivot_table(
    index='filePath', 
    columns='segment', 
    values='计数',
    fill_value=0
)
#文件路径作为行,分词作为列,计数列作为值,缺失值填充为0。
tf.index
tf.columns

tf是一个DateFrame,分词是行,文件路径是列,值是计数列,如图所示:
在这里插入图片描述
计算IDF=log(文档总数/包含该词的文档数+1)

#计算IDF
def hanlder(x): 
    return (numpy.log2(len(corpos)/(numpy.sum(x>0)+1)))

idf = tf.apply(hanlder)
#计算TF-IDF
tf_idf = pandas.DataFrame(tf*idf)

接着进行关键字提取:

#提取关键词
tag1s = []
tag2s = []
tag3s = []
tag4s = []
tag5s = []

for filePath in tf_idf.index:
    tagis = tf_idf.loc[filePath]#提取每一个filepath对应的行,作为tagis的列,共100列,3207行
    tagis=tagis.sort_values(#对每一列进行排序,取前五
        ascending=False
    )[:5]
    tag1s.append(tagis[0])#分别取前五位关键词
    tag2s.append(tagis[1])
    tag3s.append(tagis[2])
    tag4s.append(tagis[3])
    tag5s.append(tagis[4])

tagDF = pandas.DataFrame({
    'filePath':corpos.filePath, 
    'fileContent':corpos.fileContent, 
    'tag1':tag1s, 
    'tag2':tag2s, 
    'tag3':tag3s, 
    'tag4':tag4s, 
    'tag5':tag5s
})

结果如图:
在这里插入图片描述
到这里关键词提取就完成了。
在代码执行的过程中我发现了一个细节,让我百思不得其解,是这样的,segStat是词频统计之后,又去掉单字词得到的结果,它的长度为5729行
在这里插入图片描述
然后经过文件向量化处理后,也就是segStat.pivot_table()方法之后,它的size变成了(100,3207),这是为啥?第一:这个100是哪来的?第二:分词segStat[segment]总共有5729个,为什么len(tf[columns])=3207?
在这里插入图片描述
经过我苦苦思索,终于豁然开朗,原来segStat里是将源文件里的内容分词处理,一个文件被分成了很多词,每个词都有对应的文件路径作为index,所以len(segStat)就有很多行,等于5729,然后 当执行pivot_table()的时候,重复的文件路径就自动筛选掉了,就只有源文件的路径,也就是100个,第一个问题就搞明白了。

第二个问题,我特别困惑,观察了segStat的这个表,发现原因就是同一个词可以在多个文件里出现,比如这个“中国”,所以这个表文件路径唯一,但是词不唯一,
在这里插入图片描述
但是到了tf表里,文件路径唯一,词也唯一,如下图:
在这里插入图片描述

等于是变成了二维表
tf我们看的是一个词在多个文件的出现频次分布情况。
搞明白了这两个问题,我发现好像对代码的理解更深入了一些,函数的运作使表结构发生变化,从而影响了数据的长度。
通过解决这两个疑惑,我有了一些学习上的感受:如果只是运行一遍程序,得到想要的结果,但肯定不会注意到表格的size发生变化了,偏偏是这一个小小的细节和疑惑,能参透这么多知识,这难道不应该给我们学习思路上的以启示吗?我刚开始学的时候,我也发愁,代码一下子又看不懂,自己写一遍又记不住,慢慢写博客笔记对我来说算是一个更细致地方法,但是还是太粗糙了,深入到表格的结构、字段长度的变化,以及为什么要这样做,我们根本就没注意到,也没有思考过,代码运行肯定能得到结果,但是这其中有很多细节我这种初学者很容易会忽略,又要有扎实的pandas基础,还要心细多思考,数据挖掘的学习,果然需要花很多精力和功夫。

猜你喜欢

转载自blog.csdn.net/weixin_42695959/article/details/82859204
今日推荐