TF-IDF原理及使用

一. 什么是TF-IDF

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

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

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

这也就是TF-IDF的含义.

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

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

公式:

TFw=w

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

公式:

IDF=log(w+1),10

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

TFIDF=TFIDF

二. 一个实例

参考: http://www.ruanyifeng.com/blog/2013/03/tf-idf.html

这里写图片描述

三. Spark 中 TF-IDF 的实现

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

// 参考自spark官网教程 http://spark.apache.org/docs/latest/ml-features.html#tf-idf
// In the following code segment, we start with a set of sentences. 
// We split each sentence into words using Tokenizer. For each sentence (bag of words),
// we use HashingTF to hash the sentence into a feature vector. We use IDF to rescale
// the feature vectors; this generally improves performance when using text as features. // Our feature vectors could then be passed to a learning algorithm.

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,[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]
// 其中,20是标签总数,下一项是单词对应的hashing ID.最后是TF-IDF结果

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

//参考: http://spark.apache.org/docs/1.4.1/mllib-feature-extraction.html#tf-idfark.mllib.feature.HashingTF
//进阶参考
//http://blog.csdn.net/jiangpeng59/article/details/52786344

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

// Load documents (one per line).
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)

四. 参考

http://blog.csdn.net/google19890102/article/details/29369793
http://www.ruanyifeng.com/blog/2013/03/tf-idf.html
http://www.cnblogs.com/rausen/p/4142838.html
http://blog.csdn.net/jiangpeng59/article/details/52786344

### TF-IDF原理 TF-IDF 是一种用于评估词语在文档集合中的重要性的统计方法。其核心思想在于通过两个指标来衡量一个词的重要性: 1. **Term Frequency (TF)**:表示某词在特定文档中出现的频率。如果某个词频繁出现在一篇文档中,则该词可能对该文档具有较高的代表性。 2. **Inverse Document Frequency (IDF)**:表示某词在整个语料库中的稀有程度。如果某个词仅在一个或少数几个文档中出现,而不在其他文档中频繁出现,则认为这个词对于区分不同文档非常重要。 两者的乘积即为 TF-IDF 值,定义如下公式所示[^1]: \[ \text{weight}(t,d) = \text{tf}(t,d) \times \text{idf}(t) \] 其中, - \( t \) 表示目标词; - \( d \) 表示当前文档; - \( \text{tf}(t, d) \) 表示词 \( t \) 在文档 \( d \) 中的频次; - \( \text{idf}(t) \) 定义为 \( \log\left(\frac{\text{总文档数}}{\text{包含词 } t \text{ 的文档数} + 1}\right) \),加 1 防止分母为零的情况发生。 当某个词既高频又罕见时(即 TFIDF 同时较大),则它的 TF-IDF 值会很高,表明它是这篇文档的重要特征之一[^2]。 ### 图解说明 以下是关于 TF-IDF 计算的一个简单图解过程: #### 步骤一:构建语料库 假设有一个小型语料库,由三篇文档组成: ```plaintext Doc1: 我的梦想是成为一名科学家。 Doc2: 科学家们正在研究人工智能技术。 Doc3: 人工智能的发展离不开数据的支持。 ``` #### 步骤二:计算 Term Frequency (TF) 针对每篇文档分别计算各词的频率。例如,在 Doc1 中,“梦想”的 TF 可能为 0.25(因为“梦想”出现了 1 次,整句话共有 4 个词)。 #### 步骤三:计算 Inverse Document Frequency (IDF) 考虑整个语料库,统计每个词的分布情况。“梦想”只出现在 Doc1 中,因此其 IDF 值较高;而像“科学”这样的常见词由于分布在多篇文档中,IDF 较低。 #### 步骤四:综合计算 TF-IDF 将上述两项相乘得到最终的结果。比如,“梦想”在 Doc1 中的 TF-IDF 得分会显著高于其他词,从而被选作关键词。 ![TF-IDF 流程](https://upload.wikimedia.org/wikipedia/commons/thumb/8/8e/Tfidf_conceptual_diagram.svg/1920px-Tfidf_conceptual_diagram.svg.png) 此图为概念性描述,展示了如何基于 TFIDF 来决定哪些词汇更适合作为代表某一类文本的核心术语。 ### 示例代码实现 下面提供一段 Python 实现 TF-IDF 的简易版本: ```python from sklearn.feature_extraction.text import TfidfVectorizer corpus = [ '我的梦想是成为一名科学家', '科学家们正在研究人工智能技术', '人工智能的发展离不开数据的支持' ] vectorizer = TfidfVectorizer() X = vectorizer.fit_transform(corpus) print("Vocabulary:", vectorizer.get_feature_names_out()) print("TF-IDF Matrix:\n", X.toarray()) ``` 运行以上脚本后可获得对应于输入句子集的向量矩阵形式表达,每一列代表一个独特词汇经过标准化处理后的权重值。 尽管如此,需要注意的是传统 TF-IDF 方法存在一定的缺陷——缺乏对上下文中深层次意义的理解能力以及难以体现词语间复杂关联等问题已被指出过[^3]。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值