失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > spark TF-IDF特征提取生成文章关键词

spark TF-IDF特征提取生成文章关键词

时间:2023-10-25 04:49:38

相关推荐

spark TF-IDF特征提取生成文章关键词

TF-IDF

TF-IDF(term frequency–inverse document frequency)中文"词频-逆向文件频率",通过它将文本特征向量化,用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。

词频(TF)表示某关键词在文本中出现次数:

TF=某单词在文档中出现次数文档中所有单词出现次数总和TF = \dfrac{某单词在文档中出现次数}{文档中所有单词出现次数总和} TF=文档中所有单词出现次数总和某单词在文档中出现次数​

逆向文件频率(IDF)是一个词语普遍重要性的度量:

IDF=log文档总数n包含单词w的文档数目+1IDF = log\dfrac{文档总数n}{包含单词w的文档数目+1} IDF=log包含单词w的文档数目+1文档总数n​

其中加1是为了避免分母为0

TF−IDF=TF∗IDFTF-IDF=TF*IDF TF−IDF=TF∗IDF

在n个文档中,如果一个单词在文档DiD_iDi​中出现次数比较多,而很少出现在其它的文档中,那么TF值越大,IDF值越大,单词就更能作为文档DiD_iDi​的关键词。

数据准备

可以到/~jason/20Newsgroups/获取一些外国的英文新闻内容。为了比较好观察运行结果,随便从百度找了几篇新闻,以新闻标题为文件名称:

测试代码

val conf = new SparkConf().setMaster("local[2]").setAppName("TF_IDF_NEWS")var sc = new SparkContext(conf);val sqlContext = new SQLContext(sc)val path = "G:\\news\\*"val rdd = sc.wholeTextFiles(path) //读取目录下所有文件:[(filename1:content1),(filename2:context2)]val filename = rdd.map(_._1); //保存所有文件名称:[filename1,filename2],为输出结果做准备import scala.collection.JavaConverters._val stopWords = sc.textFile("zh-stopWords.txt").collect().toSeq.asJava //构建停词val filter = new StopRecognition().insertStopWords(stopWords) //过滤停词filter.insertStopNatures("w", null, "null") //根据词性过滤val splitWordRdd = rdd.map(file => { //使用中文分词器将内容分词:[(filename1:w1 w3 w3...),(filename2:w1 w2 w3...)]val str = ToAnalysis.parse(file._2).recognition(filter).toStringWithOutNature(" ")(file._1, str.split(" "))})val df = sqlContext.createDataFrame(splitWordRdd).toDF("fileName", "words");//val tokenizer = new org.apache.spark.ml.feature.RegexTokenizer().setInputCol("context").setOutputCol("words").setMinTokenLength(3)//val words = tokenizer.transform(df)//val stopWordsRemover = new org.apache.spark.ml.feature.StopWordsRemover().setInputCol("words").setOutputCol("stopWords");//val stopWords = stopWordsRemover.transform(df);//stopWords.select("stopWords").show(10, 200)val hashingTF = new org.apache.spark.ml.feature.HashingTF().setInputCol("words").setOutputCol("rawFeatures").setNumFeatures(200000)val documents = hashingTF.transform(df)val idf = new org.apache.spark.ml.feature.IDF().setInputCol("rawFeatures").setOutputCol("features")val idfModel = idf.fit(documents)val idfData = idfModel.transform(documents)var wordMap = df.select("words").rdd.flatMap { row => //保存所有单词以及经过hasingTf后的索引值:{单词1:索引,单词2:索引...}{row.getAs[Seq[String]](0).map { w => (hashingTF.indexOf(w), w) }}}.collect().toMapval keyWords = idfData.select("features").rdd.map { x =>{val v = x.getAs[org.apache.spark.ml.linalg.SparseVector](0)//idf结果以稀疏矩阵保存v.indices.zip(v.values).sortWith((a, b) => { a._2 > b._2 }).take(10).map(x => (wordMap.get(x._1).get, x._2))//根据idf值从大到小排序,取前10个,并通过索引反查到词}} //[(文章1的关键词索引1:tf-idf值,文章1的关键词索引2:tf-idf值),(文章n的关键词索引1:tf-idf值,文章n的关键词索引2:tf-idf值)...],每组()表示一个新闻的关键词filename.zip(keyWords).collect().foreach(x => {println(x._1)x._2.foreach(x => println(x._1 + ":" + x._2 + " "))})

代码基于spark2.1.0中的ml库api进行编写,使用ansj进行对中文内容进行分词

通过wholeTextFiles读取目录下所有的文件,本次的试验文件点击,或者随便从网上复制几个新闻分别对每个文件的内容使用ansj进行分词,并把一些常用的中文停词过滤,还根据词性过滤了标记符号和空值,最终得到每个文档对应的独立字词将rdd转换成DataFrame后,通过HashingTF计算词频,同时会得用哈稀转化成固定长度的特征向量构建IDFModel 并接收由HashingTF产生的特征向量,得到每个词(索引值表示)的TF-IDF值由于在结果中,词已经被数值化,用索引值来表示,所以需要根据索引值反射获得原始的词,需要把索引值与词的对应关系保存到wordMap中,hashingTF.indexOf即是计算词的索引值,这个方法在ml.HashingTF中是不存在的,这里稍微修改了原始类,参考/apache/spark/pull/18736最后根据计算得到的tf-idf值进行排序,获取最大的前10个词并输出

运行结果

file:/G:/news/世界杯后的中超怎么看?恒大有了新玩法球员:10.995488782489861 队:10.079198050615705 预备队:8.246616586867397 奖金:7.330325854993241 球队:7.330325854993241 一线:6.414035123119086 恒:5.497744391244931 处罚:5.497744391244931 表现:5.497744391244931 下放:4.5814536593707755 file:/G:/news/人工智能为什么要从本科生抓起?ai:83.38245660054811 人工智能:17.409523905608946 本科:15.576942441860638 人才:15.576942441860638 研究:12.828070246238171 发展:10.995488782489861 本科生:10.995488782489861 专业:10.216512475319814 科学:10.079198050615705 国内:9.162907318741551 file:/G:/news/农业农村部猪价将处下降通道 养殖户需合理安排新闻:4.5814536593707755 农村:4.5814536593707755 农业:4.5814536593707755 市场:4.5814536593707755 部:4.5814536593707755 生猪:3.6651629274966204 减:3.6651629274966204 同比:3.6651629274966204 价:3.6651629274966204 唐:3.6651629274966204 file:/G:/news/欧盟《通用数据保护条例》影响医疗卫生领域医疗:11.911779514364017 患者:9.162907318741551 gdpr:8.246616586867397 收集:5.497744391244931 保健:4.5814536593707755 信息:4.086604990127926 安全:3.6651629274966204 欧盟:3.6651629274966204 了解:2.7488721956224653 使:2.7488721956224653

由于选取的几个新闻都是类型区别比较大,所以最终得到的关键词还是有比较明显的区别。分词不是十分准确,一些过滤规则应该根据业务做相应的调整。后面可以结合余弦相似性来判断不同文档的相似性来做自动分类。

参考

/book/85/ml/clean-feature/spark-fextract.md

/jiangpeng59/article/details/52786344

http://dblab./blog/1261-2/

如果觉得《spark TF-IDF特征提取生成文章关键词》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。