您的位置:首页 > 其它

Spark数据挖掘-TF-IDF文档矩阵

2015-11-19 00:00 597 查看
摘要: 得到词文档矩阵往往都是文本挖掘算法的第一步,词文档矩阵中行表示语料库中出现过的词(实际代码都是对词进行整数编码),列表示所有的文档,矩阵中的每个值就代表词在文档中的重要程度。目前已经有很多计算词在文档中权重的模型,不过最通用的模型应该就是 **词频-逆文档频率(简称:TF-IDF)** 矩阵。

Spark数据挖掘-TF-IDF文档矩阵

前言

得到词文档矩阵往往都是文本挖掘算法的第一步,词文档矩阵中行表示语料库中出现过的词(实际代码都是对词进行整数编码),列表示所有的文档,矩阵中的每个值就代表词在文档中的重要程度。目前已经有很多计算词在文档中权重的模型,不过最通用的模型应该就是 词频-逆文档频率(简称:TF-IDF) 矩阵。

TF-IDF

先看一下TF-IDF如何计算每个词在文档中的重要程度,先假设得到了下面几个变量的值:

termFrequencyInDoc:Int 词在文档中出现的次数

totalTermsInDoc: Int 文档中所有词的个数

termFreqInCorpus: Int 语料库中出现这个词的不同文档数

totalDocs: Int 整个语料库包含的文档数量

利用上面的几个值就可以计算一个词在文档中的重要程度,代码如下:

def termDocWeight(termFrequencyInDoc: Int, totalTermsInDoc: Int,
termFreqInCorpus: Int, totalDocs: Int): Double = {
val tf = termFrequencyInDoc.toDouble / totalTermsInDoc
val docFreq = totalDocs.toDouble / termFreqInCorpus
val idf = math.log(docFreq)
tf * idf
}

TF-IDF含义解读

直观理解,TF-IDF考虑了如下两个方面:

首先,词在某篇文档中出现的越多越重要

其次,词在其他文档中尽量少出现,如果每篇文档中它都出现的很多,它就没有区分度了。所以这里采用的是文档频率取逆,也就是取倒数。

但是有个问题,首先词频是近似服从指数分布,一些通用词出现的次数可能是低频词几十或者几百倍,直接采用文档频率取逆会导致稀缺词获得一个巨大的权重,实际上就会忽略其他词的影响,这样显然不妥,为了去掉这个影响,算法采用对文档频率取逆之后再取对数,这样就把乘法差异转化为加法差异。使得稀缺词权重降低了。

TF-IDF的局限

这个算法本质还是词袋模型,它没有考虑词与词之间的顺序、语法结构以及语义。通过对每个不同的词计数,这个模型很难区别一词多义、以及同义词。实际编程中往往每篇文档表示为行向量,每个元素代表词对应的索引位置,这样可以适应语料库中文档变的越来越多,通常情况下,语料库文档的增加速度肯定大过词的增长速度。而且这样的行向量也是稀疏表示,节省空间。

TF-IDF实战

TF-IDF原理非常简单,实际工作中还是有很多需要注意的地方,下面就用 Spark 实战的方式讲解如何将一个语料库转为 TF-IDF 矩阵,首先给出具体的步骤:

实际工作中对每篇文档往往都有一个唯一的标识主键,这样方便以后的统计

文档清洗(去掉不符合要求的文档:比如文档内容为空)

文档分词(去掉停用词、按词性过滤一下词、过滤低频词、词干提取),其中词干提取指的是将比如:“大款、大款们”合并为一个词,中文实现这个难度很大。

数据加载,词编码、文档编码

将数据编码之后转为文档词向量再合并为矩阵

计算IF-IDF

数据清洗、停词库每个项目都会有不同的要求,但是分词、词编码、文档编码等工作还是比较通用的,下面会对通用技术通过 Spark 实战详细讲解(尤其是分布式编程需要注意的地方:)

分布式文本分词

分布式文本分词注意两个地方:

停词库需要广播到所有机器

每个 executor 只需启动一个分词模型即可,分词模型很耗资源,与连接数据库一样,每个executor只需启动一个实例

计算TF-IDF

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

val hashingTF = new HashingTF()
val tf: RDD[Vector] = hashingTF.transform(documents)

tf.cache()
//没有在两个文档中出现过的词语不要
val idf = new IDF(minDocFreq = 2).fit(tf)
val tfidf: RDD[Vector] = idf.transform(tf)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Spark 数据挖掘 TF-IDF