TF-IDF原理以及Spark环境下的使用

数据摆渡人
• 阅读 3767

一. 什么是TF-IDF

TF-IDF(Term Frequency-Inverse Document Frequency, 词频-逆文件频率).

是一种用于资讯检索与资讯探勘的常用加权技术。TF-IDF是一种统计方法,用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。

上述引用总结就是, 一个词语在一篇文章中出现次数越多, 同时在所有文档中出现次数越少, 越能够代表该文章.这也就是TF-IDF的含义.

词频 (term frequency, TF) 指的是某一个给定的词语在该文件中出现的次数。这个数字通常会被归一化(一般是词频除以文章总词数), 以防止它偏向长的文件。(同一个词语在长文件里可能会比短文件有更高的词频,而不管该词语重要与否。)

TF公式:TF = 在某一文档中词条w出现的次数 / 该文档中所有的词条数目

但是, 需要注意, 一些通用的词语对于主题并没有太大的作用, 反倒是一些出现频率较少的词才能够表达文章的主题, 所以单纯使用是TF不合适的。权重的设计必须满足:一个词预测主题的能力越强,权重越大,反之,权重越小。所有统计的文章中,一些词只是在其中很少几篇文章中出现,那么这样的词对文章的主题的作用很大,这些词的权重应该设计的较大。IDF就是在完成这样的工作.

逆向文件频率 (inverse document frequency, IDF) IDF的主要思想是:如果包含词条t的文档越少, IDF越大,则说明词条具有很好的类别区分能力。某一特定词语的IDF,可以由总文件数目除以包含该词语之文件的数目,再将得到的商取对数得到。

IDF公式:IDF = log(语料库的文档总数 / (包含词条w的文档数 + 1))

分母之所以要加1,是为了避免分母为0

  某一特定文件内的高词语频率,以及该词语在整个文件集合中的低文件频率,可以产生出高权重的TF-IDF。因此,TF-IDF倾向于过滤掉常见的词语,保留重要的词语。

IF-IDF公式:IF-IDF = IF * IDF

最终公式:IF-IDF = (在某一文档中词条w出现的次数 / 该文档中所有的词条数目) * log(语料库的文档总数 / (包含词条w的文档数 + 1))

二. 案例

TF-IDF原理以及Spark环境下的使用

三. Spark 中 TF-IDF 的实现

1. 基于spark1.4.1 ml算法包的TF-IDF算法

import org.apache.spark.{SparkContext, SparkConf}
import org.apache.spark.ml.feature.{Tokenizer,HashingTF, IDF}
import org.apache.spark.mllib.linalg.{Vectors, Vector}
// 创建实例数据
val sentenceData = sqlContext.createDataFrame(Seq(
  (0, "Hi I heard about Spark"),
  (0, "I wish Java could use case classes"),
  (1, "Logistic regression models are neat")
)).toDF("label", "sentence")

//  scala> sentenceData.show
//  +-----+--------------------+
//  |label|            sentence|
//  +-----+--------------------+
//  |    0|Hi I heard about ...|
//  |    0|I wish Java could...|
//  |    1|Logistic regressi...|
//  +-----+--------------------+

//句子转化成单词数组
val tokenizer = new Tokenizer().setInputCol("sentence").setOutputCol("words")
val wordsData = tokenizer.transform(sentenceData)

// scala> wordsData.show
//  +-----+--------------------+--------------------+
//  |label|            sentence|               words|
//  +-----+--------------------+--------------------+
//  |    0|Hi I heard about ...|ArrayBuffer(hi, i...|
//  |    0|I wish Java could...|ArrayBuffer(i, wi...|
//  |    1|Logistic regressi...|ArrayBuffer(logis...|
//  +-----+--------------------+--------------------+

// hashing计算TF值,同时还把停用词(stop words)过滤掉了. setNumFeatures(20)表最多20个词
val hashingTF = new HashingTF().setInputCol("words").setOutputCol("rawFeatures").setNumFeatures(20)
val featurizedData = hashingTF.transform(wordsData)

// scala> featurizedData.show
//  +-----+--------------------+--------------------+--------------------+
//  |label|            sentence|               words|         rawFeatures|
//  +-----+--------------------+--------------------+--------------------+
//  |    0|Hi I heard about ...|ArrayBuffer(hi, i...|(20,[5,6,9],[2.0,...|
//  |    0|I wish Java could...|ArrayBuffer(i, wi...|(20,[3,5,12,14,18...|
//  |    1|Logistic regressi...|ArrayBuffer(logis...|(20,[5,12,14,18],...|
//  +-----+--------------------+--------------------+--------------------+


val idf = new IDF().setInputCol("rawFeatures").setOutputCol("features")
val idfModel = idf.fit(featurizedData)
val rescaledData = idfModel.transform(featurizedData)
// 提取该数据中稀疏向量的数据,稀疏向量:SparseVector(size,indices,values)
// rescaledData.select("features").rdd.map(row => row.getAs[linalg.Vector](0)).map(x => x.toSparse.indices).collect
rescaledData.select("features", "label").take(3).foreach(println)
// 其中,20是标签总数,下一项是单词对应的hashing ID.最后是TF-IDF结果
//  [(20,[5,6,9],[0.0,0.6931471805599453,1.3862943611198906]),0]
//  [(20,[3,5,12,14,18],[1.3862943611198906,0.0,0.28768207245178085,0.28768207245178085,0.28768207245178085]),0]
//  [(20,[5,12,14,18],[0.0,0.5753641449035617,0.28768207245178085,0.28768207245178085]),1]

2.基于RDD的MLlib包中的TF_IDF算法

import org.apache.spark.mllib.linalg.Vector
val sc: SparkContext = ...

val documents: RDD[Seq[String]] = sc.textFile("...").map(_.split(" ").toSeq)

val hashingTF = new HashingTF()
val tf: RDD[Vector] = hashingTF.transform(documents)
tf.cache()
val idf = new IDF().fit(tf)
val tfidf: RDD[Vector] = idf.transform(tf)
点赞
收藏
评论区
推荐文章
lucien-ma lucien-ma
4年前
Git基础命令教程
Git学习git之前,我们需要先明白一个概念,版本控制!版本控制什么是版本控制版本控制(Revisioncontrol)是一种在开发的过程中用于管理我们对文件、目录或工程等内容的修改历史,方便查看更改历史记录,备份以便恢复以前的版本的软件工程技术。实现跨区域多人协同开发追踪和记载一个或者多个文件的历史记录组织和保护你的源代码和文档统计工作量
Wesley13 Wesley13
3年前
iOS学习之 plist文件的读写
在做iOS开发时,经常用到到plist文件, 那plist文件是什么呢?它全名是:PropertyList,属性列表文件,它是一种用来存储串行化后的对象的文件。属性列表文件的扩展名为.plist,因此通常被称为 plist文件。文件是xml格式的。Plist文件通常用于储存用户设置,也可以用于存储捆绑的信息我们创建一个项目来学习pl
Easter79 Easter79
3年前
springboot中切换配置(多个配置文件
问题描述:在springboot项目中可能有测试环境、开发环境、生产环境,在这些环境中我们可能要使用不同的配置,如果每次切换环境的时候都要重新写一份配置文件就很麻烦了,所以下面提供一种方法可以快速且简便的切换不同环境下的配置。解决方案:1、首先在resources目录下创建完整的配置文件(包括测试、开发、生产环境下的相关配置文件
Stella981 Stella981
3年前
Scrapy爬虫框架下执行爬虫的方法
  在使用Scrapy框架进行爬虫时,执行爬虫文件的方法是scrapycrawlxxx,其中xxx是爬虫文件名。  但是,当我们在建立了多个文件时,使用上面的命令时会比较繁琐麻烦,我们就可以使用下述方法同时完成爬虫文件的执行。  第一种,在scrapy框架下建立一个运行文件,如run.py,在文件中建立一个列表,列表为爬虫的执行命令,
Wesley13 Wesley13
3年前
Java中的SPI是怎么一回事
!(https://oscimg.oschina.net/oscnet/up2acf1859e4ef7973a34a3dffe4af94a7b51.png)SPI,全称为ServiceProviderInterface,是一种服务发现机制。它通过在ClassPath路径下的METAINF/services文件夹查找文件,自动加载文件里所定
Wesley13 Wesley13
3年前
Java文件格式
\.java文件是保存源代码的文本文件(\代表类名)使用javac\.java可以编译该文件使用java\可以运行该类\.class是用于保存Java类的二进制编码以及Class对象,每一个Java类都有一个解释该类特征的Class对象。\.jar文件是一种压缩文件格式打包命令jarcvf
Wesley13 Wesley13
3年前
CSS瀑布流布局
瀑布流布局是什么瀑布流布局是一种常见的网页布局方式,视觉上给人一种参差不齐的多栏的效果,常用于图片为主的版块,如下图。!(https://timgsa.baidu.com/timg?image&quality80&sizeb9999_10000&sec1589721778046&dib34a014e7481f1a5685
Wesley13 Wesley13
3年前
AI金融知识自学偏量化方向
前提:统计学习(统计分析)和机器学习之间的区别金融公司采用机器学习技术及招募相关人才要求第一个问题:  机器学习和统计学都是数据科学的一部分。机器学习中的学习一词表示算法依赖于一些数据(被用作训练集),来调整模型或算法的参数。这包含了许多的技术,比如回归、朴素贝叶斯或监督聚类。但不是所有的技术都适合机器学习。例如有一种统计和数
Stella981 Stella981
3年前
Linux的文件描述符
(1).文件描述符的定义  文件描述符是内核为了高效管理已被打开的文件所创建的索引,用于指向被打开的文件,所有执行I/O操作的系统调用都通过文件描述符;文件描述符是一个简单的非负整数,用以表明每个被进程打开的文件。程序刚刚启动时,第一个打开的文件是0,第二个是1,以此类推。也可以理解为文件的身份ID。  用户通过操作系统处理信息的过程中,使用的交互设
Easter79 Easter79
3年前
Tachyon 0.7.1伪分布式集群安装与测试
Tachyon是一个高容错的分布式文件系统,允许文件以内存的速度在集群框架中进行可靠的共享,就像Spark和MapReduce那样。通过利用信息继承,内存侵入,Tachyon获得了高性能。Tachyon工作集文件缓存在内存中,并且让不同的Jobs/Queries以及框架都能内存的速度来访问缓存文件。因此,Tachyon可以减少那些需要经常使用的数据集通过
崇恩圣帝 崇恩圣帝
1年前
使用机器学习识别文本验证码的实现方法
在网络应用中,验证码常用于防止恶意机器人或自动程序对网站进行攻击。识别文本验证码是一个常见的问题,本文将介绍如何使用机器学习方法来实现这一目标。1.文本验证码识别方法文本验证码通常包含英文和数字字符,识别文本验证码的一种常见方法是使用图像处理和机器学习技术