TF-IDF逆文本频率指数
TF-IDF 逆文本频率指数
1. 原理
TF-IDF(term frequency–inverse document frequency)是信息处理和数据挖掘的重要算法,它属于统计类方法。最常见的用法是寻找一篇文章的关键词。
其公式如下:
TF(词频)是某个词在这篇文章中出现的频率,频率越高越可能是关键字。它具体的计算方法如上面公式所示:某关键在文章中出现的次数除以该文章中所有词的个数,其中的 i 是词索引号,j 是文章的索引号,k 是文件中出现的所有词。
IDF(逆向文档频率)是这个词出现在其它文章的频率,它具体的计算方法如上式所示:其中分子是文章总数,分母是包含该关键字的文章数目,如果包含该关键字的文件数为 0,则分母为 0,为解决此问题,分母计算时常常加 1。当关键字,如“的”,在大多数文章中都出现,计算出的 idf 值算小。
词出现次数越多,idf 为越大的负数,说明这词没什么用;出现少,则为正值;不多不少为 0
把 TF 和 IDF 相乘,就是这个词在该文章中的重要程度。
2. 使用 Sklearn 提供的 TF-IDF 方法
Sklearn 是最常用的机器学习第三方模型,它也支持对 TF-IDF 算法。
本例中,先使用 Jieba 工具分词,并模仿英文句子,将其组装成以空格分割的字符串。
1 | 01 import jieba |
然后使用 sklearn 提供的 CountVectorizer 工具将句子列表转换成词频矩阵,并将其组装成 DataFrame。
1 | 01 vectorizer = CountVectorizer() |
其方法 get_feature_names 返回数据中包含的所有词,需要注意的是它去掉了长度为 1 的单个词,且重复的词只保留一个。X.toarray() 返回了词频数组,组合后生成了包含关键词的字段,这些操作相当于对中文切分后做 OneHot 展开。每条记录对应列表中的一个句子,如第一句“第一天我参观了美术馆”,其关键字“参观”、“第一天”、“美术馆”被置为 1,其它关键字置 0。
接下来使用 TfidfTransformer 方法计算每个关键词的 TF-IDF 值,值越大,该词在它所在的句子中越重要:
1 | 01 transformer = TfidfTransformer() |
经过对数据 X 的计算之后,返回了权重矩阵,句中的每个词都只在该句中出现了一次,因此其 TF 值相等,由于“参观”在三句中都出现了,其 IDF 较其它关键字更低。细心的读者可以发现,其 TF-IDF 结果与上述公式中计算得出的结果这一致,这是由于 Sklearn 除了实现基本的 TF-IDF 算法外,还其行了归一化、平滑等一系列优化操作。详细操作可参见 Sklearn 源码中的 sklearn/feature_extraction/text.py 具体实现。
3. 写程序实现 TF-IDF 方法
TF-IDF 算法相对比较简单,手动实现代码量也不大,并且可以在其中加入定制作化操作,例如:下例中也加入了单个字重要性的计算。
本例中使用了 Counter 方法统计各个词在所在句中出现的次数。
1 | 01 from collections import Counter |
接下来定义了函数分别计算 TF,IDF 等值。
1 | 01 def tf(word, count): |
从返回结果可以看出,其 TF-IDF 值与 Sklearn 计算出的值略有不同,但比例类似,且对单个字进行了统计。
最后,需要再探讨一下 TF-IDF 的使用场景。在做特征工程时,常遇到这样的问题:从一个短语或短句中提取关键字构造新特征,然后将新特征代入分类或者回归模型,是否需要使用 TF-IDF 方法?首先,TF 是词频,即它需要在一个文本中出现多次才有意义,如果在短句中,每个词最多只出现一次,那么计算 TF 不如直接判断其是否存在。
另外,TF-IDF 的结果展示的是某一词针对于它所在文档的重要性,而不是对比两文档的差异。比如上例中虽然三个短句都包含“参观”,IDF 较小,由于词量小 TF 较大,其最终得分 TF-IDF 仍然不太低。如果两个短语属于不同类别,新特征对于提取分类特征可能没有意义,但是对于生成文摘就是有意义的关键字。对于此类问题,建议使用:先切分出关键词,将是否包含该关键词作为新特征,然后对新特征和目标变量做假设检验,以判断是否保留该变量的方法提取新特征。