概述
在上一篇博客,我们使用spark CountVectorizer与IDF进行了关键词提取,博客地址:
spark CountVectorizer+IDF提取中文关键词(scala)
本篇博客在上一篇博客的基础上,介绍如何根据关键词获取文档的相似度,进行相似文本的推荐。在这里我们需要使用到两个算法:Word2Vec与LSH。
其中Word2Vec即将词转换为词向量,这样词之间的关系就可以向量距离去定量计算,距离越近的两个词相似性也较高,而spark中文档的词向量,即是这个文档所有词的词向量的平均值(这也就是为什么要使用关键词来计算文档的词向量,而不是直接计算文档的词向量的原因),Word2Vec的原理网上详细的教程 比较多,这里就不再累述了。
LSH可能使用得相对不那么频繁。LSH即Locality Sensitive has,局部敏感哈希,主要用来解决海量数据的相似性检索。由spark的官方文档翻译为:LSH的一般思想是使用一系列函数将数据点哈希到桶中,使得彼此接近的数据点在相同的桶中具有高概率,而数据点是远离彼此很可能在不同的桶中。spark中LSH支持欧式距离与Jaccard距离。
之所以使用Word2Vec+LSH,是因为Word2Vec将文档转换成了一个向量,而要求两篇文章的相似度,就是通过求其词向量的欧式距离,距离越近的则越相似。但对于海量的数据,要对文档两两求距离在寻找与当前文档最相似的文档,显然是不可能的。所以通过LSH来进行相似性检索。下面直接上代码(scala):
1、提取关键词后的初始数据集:
、
2、使用Word2Vec获取词向量:
//Word2Vec获取关键词词向量
val word2Vec = new Word2Vec()
.setInputCol("keywords")
.setOutputCol("wordvec")
.setVectorSize(15)
.setMinCount(0);
val wvModel = word2Vec.fit(keyWordsDf);
val w2vDf = wvModel.transform(keyWordsDf);
w2vDf.show(false);
3、获取LSH模型
val brp = new BucketedRandomProjectionLSH()
.setBucketLength(4.0)
.setNumHashTables(10)
.setInputCol("wordvec")
.setOutputCol("hashes")
val brpModel = brp.fit(w2vDf);
val tsDf = brpModel.transform(w2vDf);
4、使用LSH模型获取每个文档的相似文档(欧式距离在某个范围内)
val brpDf = brpModel.approxSimilarityJoin(tsDf, tsDf, 0.015, "EuclideanDistance");
brpDf.show(false);
5、整理计算结果
val getIdFun = udf((input:Row)=> {
input(0).toString.toInt;
});
val corrDf = brpDf.withColumn("id",getIdFun(col("datasetA")))
.withColumn("id_sim",getIdFun(col("datasetB")))
.drop("datasetA").drop("datasetB").drop("EuclideanDistance");
corrDf.show(false);
corrDf.createOrReplaceTempView("test");
val resDf = sparkSQL.sql("select id,concat_ws(',',collect_set(id_sim)) as sim from test where id != id_sim group by id");
resDf.show(false);
计算结果如下截图:
其中id为每篇文章的id,sim为相似的文档的id。可以看到,由于是推荐欧式距离在一定范围内的文档,所以对于每篇文档,推荐的结果的数量是不一致的。
最后
以上就是秀丽小鸽子为你收集整理的spark Word2Vec+LSH相似文本推荐(scala)的全部内容,希望文章能够帮你解决spark Word2Vec+LSH相似文本推荐(scala)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复