Jaccard与Spark和Scala的帮助相似的RDD没有笛卡尔?

时间:2018-03-09 01:56:18

标签: scala apache-spark cartesian-product

我正在研究对RDD。我的目标是计算jaccard相似度 在rdd值集合之间,根据jaccard相似度阈值对它们进行聚类。我的RDD的结构是:

val a= [Key,Set(String)]   //Pair RDD

For example:-    
India,[Country,Place,....]  
USA,[Country,State,..]  
Berlin,[City,Popluatedplace,..]   

在找到jaccard相似性后,我会将类似的实体聚类到一个群集中。在上面的例子中,印度和美国将基于一些阈值聚集成一个集群,而柏林将集中在另一个集群中。

所以我拿了rdd的笛卡尔乘积

val filterOnjoin = a.cartesian(a).filter(f => 
(!f._1._1.toString().contentEquals(f._2._1.toString()))) 
//Cartesianproduct of rdd a and filtering rows with same key at both 
//the position.
//e.g. ((India,Set[Country,Place,....]),(USA,Set[Country,State,..])) 

并在jaccard相似度的帮助下比较这组值。

val Jsim = filterOnjoin.map(f => (f._1._1, (f._2._1, 
Similarity.sim(f._1._2, f._2._2)))) //calculating jaccard similarity.
//(India,USA,0.8)

代码在较小的数据集上正常运行。随着数据集大小的增加,笛卡尔积产品需要花费太多时间。对于100 MB数据(rdd" a"的大小),其执行数据随机播放读取大约25 GB。对于3.5 GB数据,其在TB中。

我已经浏览了各种链接。像火花调整方法和一些堆栈溢出。但是大部分帖子都是用来播放较小的RDD的。但是这里rdd的大小是相同的而且很大。

我遵循的链接: -
来自rddx的所有可能组合的Spark: produce RDD[(X, X)] of all possible combinations from RDD[X]

Spark repartition is slow and shuffles too much data

Map key, value pair based on similarity of their value in Spark

我是Spark和Scala的新手。我无法超越笛卡尔积,这是瓶颈。没有笛卡儿积,是否有可能解决这个问题。

1 个答案:

答案 0 :(得分:0)

由于笛卡儿积在rdd上是一项昂贵的操作,我试图通过使用Spark MLib中的HashingTF和MinHashLSH库来找到jaccard相似性来解决上述问题。在rdd" a"中找到Jaccard相似性的步骤在问题中提到:

  • 将rdd转换为dataframe

     import sparkSession.implicits._  
     val dfA = a.toDF("id", "values")
    
  • 借助HashingTF创建特征向量

      val hashingTF = new HashingTF()
     .setInputCol("values").setOutputCol("features").setNumFeatures(1048576)  
    
  • 功能转换

    val featurizedData = hashingTF.transform(dfA) //Feature Transformation  
    
  • 创建minHash表。更多的是表数的值,更准确 结果将是,但通信成本和运行时间很高。

     val mh = new MinHashLSH()
            .setNumHashTables(3) 
            .setInputCol("features")
            .setOutputCol("hashes")
    
  • 近似相似性连接需要两个数据集,并且近似返回距离小于用户定义阈值的数据集中的行对。近似相似性连接支持连接两个不同的数据集和自连接。自联将产生一些重复对。

      val model = mh.fit(featurizedData)  
      //Approximately joining featurizedData with Jaccard distance smaller 
      //than 0.45
     val dffilter = model.approxSimilarityJoin(featurizedData, featurizedData, 
                    0.45)    
    

因为在spark中,我们必须在代码中进行手动优化,例如设置分区数,设置持久级别等。我也配置了这些参数。

  • 将storaagelevel从persist()更改为persist(StorageLevel.MEMORY_AND_DISK), 它帮助我删除OOM错误。
  • 同时在进行连接操作时,根据rdd重新分区数据 尺寸。在16.6 GB的数据集上,在进行简单的连接操作时,我使用的是200 划分。在增加到600时,它也解决了我与OOM相关的问题。

PS:在16.6数据集上进行实验时配置常量参数setNumFeatures(1048576)和setNumHashTables(3)。您可以根据数据集增加或减少这些值。分区数也取决于您的数据集大小。通过这些优化,我得到了我想要的结果。

有用的链接: -
[https://spark.apache.org/docs/2.2.0/ml-features.html#locality-sensitive-hashing]
[https://eng.uber.com/lsh/]
[https://data-flair.training/blogs/limitations-of-apache-spark/]