引言

TF-IDF是一种简单的特征提取算法

​ 在全文检索功能开发时,一定会设计到很多字段的搜索, 但是一般我们只需要搜索文章特定的关键字即可搜索出来?但是什么是关键字?关键字又是如何计算出来的呢?比如如下数据表信息中,如果提取文章的关键字呢?

TF-IDF算法

​ TF-IDF(term frequency–inverse document frequency)是一种用于信息检索与数据挖掘的常用加权技术。TF是词频(Term Frequency),IDF是逆文本频率指数(Inverse Document Frequency)。

​ TF-IDF思想也就是:如果某个词或短语在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。如下表格,如果搜索C罗就只能检索第一条数据。如果是搜索北京就无法进行区分。说明北京不适合分类。

title content
官方:皮尔洛出任尤文新帅 合同为期2年 北京时间8月10日讯 尤文图斯俱乐部官方消息,皮尔洛出任俱乐部一线队新任主帅,双方签约至2022年6月。尤文在欧冠被里昂淘汰之后,第2天即官宣萨里下课,复赛后的带队表现以及与C罗等大牌球星的相处都存在争议
易建联罚球绝杀!广东险胜北京总分2-1进决赛 北京8月8日,CBA季后赛半决赛京粤大战第三场展开决胜大战。广东以88-85战胜北京,从而以总比分2-1淘汰北京队挺进总决赛,将与辽宁争夺总冠军。这也是广东队队史第15次打进总决赛。易建联竟然…
韩德君35+20辽宁险胜新疆 总分2-0进决赛 北京时间8月7日,CBA下半区半决赛展开第二场争夺,首战获胜的辽宁迎战全华班的新疆。齐麟得到22分创个人职业新高,韩德君砍下35分20篮板,郭艾伦贡

计算公式:

【算法无用系列】TF-IDF算法_tfidf

D为文档总数或者可以为集合数,DF(t,D)表示在集合D有词语t的文档数。分式上下都+1防止有0的情况。源码中log即以e为底而不是以10为底,所以如果是自己计算进行对比的话,使用ln

【算法无用系列】TF-IDF算法_tfidf_02

如上公式说明在集合D中文档d中词语t的TFIDF的值 等于 词语t在文档d的频率乘以词语t在集合D的逆文本指数。

举例说明

tfidf.txt

我中了一个奖品
我爱吃苹果
你是我的小苹果

scala代码

case class ContentBean(content:String,words:Array[String])
  def main(args: Array[String]): Unit = {
    val spark = SparkSession.builder().appName("tfidf")
      .master("local[2]")
      .getOrCreate();
    val path = "C:\\Users\\archermind\\Desktop\\ml-1m\\tfidf.txt"
    import spark.implicits._
    //加载文件
    val input = spark.sparkContext.textFile(path)
    //通过BaseAnalysis 进行分词 分词详解 https://github.com/NLPchina/ansj_seg
    var content = input
      .map(x => ContentBean (x,BaseAnalysis.parse(x).toStringWithOutNature(" ").split(" ")))
      .toDF();
    //HashingTF计算频率TF
    var hashingTF = new HashingTF().setInputCol("words").setOutputCol("rawFeatures")
    var featuresDF = hashingTF.transform(content);
    val idf = new IDF().setInputCol("rawFeatures").setOutputCol("features")
    // idf = ln((m + 1) / (d(t) + 1)) m文章总数  t含有该词文章数
    val idfModel = idf.fit(featuresDF);
    var tfidf = idfModel.transform(featuresDF)
    // 输入结果
    tfidf.show(false)
  }
输出结果,由于太长,可复制出来查看。
+--------------+--------------------------+---------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------+
|content       |words                     |rawFeatures                                                                |features                                                                                                                                               |
+--------------+--------------------------+---------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------+
|我中了一个奖品|[我, 中, 了, 一个, 奖品]  |(262144,[24380,91015,117468,219629,244828],[1.0,1.0,1.0,1.0,1.0])          |(262144,[24380,91015,117468,219629,244828],[0.6931471805599453,0.6931471805599453,0.6931471805599453,0.0,0.6931471805599453])                          |
|我爱吃苹果    |[我, 爱, 吃, 苹果]        |(262144,[14800,105739,173195,219629],[1.0,1.0,1.0,1.0])                    |(262144,[14800,105739,173195,219629],[0.28768207245178085,0.6931471805599453,0.6931471805599453,0.0])                                                  |
|你是我的小苹果|[你, 是, 我, 的, 小, 苹果]|(262144,[14800,27555,80738,129171,219629,238030],[1.0,1.0,1.0,1.0,1.0,1.0])|(262144,[14800,27555,80738,129171,219629,238030],[0.28768207245178085,0.6931471805599453,0.6931471805599453,0.6931471805599453,0.0,0.6931471805599453])|
+--------------+--------------------------+---------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------+

words是分词结果。

rawFeatures是频率信息(262144,[24380,91015,117468,219629,244828],[1.0,1.0,1.0,1.0,1.0]) 通过逗号分隔,前两个不需要关心,最后那个是词出现的频率TF。

features前两个也不需要关心,最后是TF-IDF的值。

按照公式,文档集合D为3。

第一个文档中奖品的频率TF为1。TF-IDF值为ln((3+1)/(1+1)) * 1 = 0.6931471805599453

第二个文档中苹果的频率TF为1。TF-IDF的值为ln((3+1)/(2+1)) * 1 = 0.287682072451