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、提取关键词后的初始数据集:

spark 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);

计算结果如下截图:

spark Word2Vec+LSH相似文本推荐(scala)_第2张图片

其中id为每篇文章的id,sim为相似的文档的id。可以看到,由于是推荐欧式距离在一定范围内的文档,所以对于每篇文档,推荐的结果的数量是不一致的。

你可能感兴趣的:(spark)