基于RDD的特征的提取和转化的API
TF-IDF
TF-IDF的算法步骤:
- TF(词频)=\(\farc{某个词在该文章出现的次数}{该文章的总词数}\)
- IDF(逆文档频率)=\(log(\frac{语料库的文档总数}{包含该词的文档数+1})\),分母加1是为了不让等于0.
- TF-IDF=TF*IDF
可以看出计算出的每个词的TF-IDF值表示的是这个词其实本质上就是体现了这篇文章中比较有意义的词。
当然TF-IDF存在一个大前提就是一篇文章的核心词出现的次数是很多的。如果,一篇文章的核心词出现的次数很小,那么TF-IDF就失效了。
package com.IT_IDFTest
import org.apache.spark.mllib.feature.{HashingTF, IDF, IDFModel}
import org.apache.spark.mllib.linalg
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
object Main {
def main(args: Array[String]): Unit = {
//TODO 创建环境
val conf: SparkConf = new SparkConf().setAppName("test").setMaster("local[*]")
val sc = new SparkContext(conf)
//TODO 数据操作
val path = "src/main/resources/data/mllib/docment.txt"
val data: RDD[Seq[String]] = sc.textFile(path).map(_.split(' ').toSeq)
val hashingTF = new HashingTF()
//计算出词频
val tf: RDD[linalg.Vector] = hashingTF.transform(data)
//因为需要使用两次TF值,所以可以cache一下(可选)
tf.cache()
//计算逆文档频率
val idf: IDFModel = new IDF().fit(tf)
//计算TF-IDF值
val tfidf: RDD[linalg.Vector] = idf.transform(tf)
tfidf.foreach(r=>{
val array: Array[Double] = r.toArray
array.foreach(r=>{
if(r>0.0){print(r+" ")}
})
println("--------------")
})
//TODO 关闭环境
sc.stop()
}
}
word2vec
推荐一篇博客,该博客有详细的推导过程:https://www.cnblogs.com/peghoty/p/3857839.html
word2vec计算单词的分布式向量表示。分布式表示的主要优点是相似的词在向量空间中是接近的,这使得对新模式的概括更容易,模型估计更稳健。分布式向量表示在许多自然语言处理的应用中是有用的,如命名实体识别、消歧义、解析、标记和机器翻译。
下面的例子表示了如何加载文本文件,然后构建一个word2vec实例,然后输入数据拟合出一个word2vecmodel。最后,我们显示出指定单词的前40个同义词。
package com.word2vectest
import org.apache.spark.mllib.feature.{Word2Vec, Word2VecModel}
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
object Main {
def main(args: Array[String]): Unit = {
//TODO 创建环境
val conf: SparkConf = new SparkConf().setAppName("test").setMaster("local[*]")
val sc = new SparkContext(conf)
//TODO 数据操作
val path = "src/main/resources/data/mllib/sample_lda_data.txt"
val data: RDD[Seq[String]] = sc.textFile(path).map(line => line.split(" ").toSeq)
val word2vec = new Word2Vec()
val model: Word2VecModel = word2vec.fit(data)
val synonym: Array[(String, Double)] = model.findSynonyms("1", 5)
for((a, b) <- synonym){
println(s"$a, $b")
}
//TODO 关闭环境
sc.stop()
}
}
标准化
在数据处理中,各个特征值需要进行标准化,通过对列计算将特征值放缩在单位方差或者除以平均数来进行标准化。
标准化可以提高优化过程中的收敛率,也可以防止巨大的变化的特征在模型训练中产生过大影响。
在Spark中一般使用StandardScaler对象来处理数据的标准化。Spark mllib提供了一下参数:
- withMean:决定数据集的位置(默认为false)
- withStd:将数据压缩在方差之内(默认为true)