本文主要是介绍spark Word2Vec+LSH相似文本推荐(scala),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
在上一篇博客,我们使用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)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!