我正在研究对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的新手。我无法超越笛卡尔积,这是瓶颈。没有笛卡儿积,是否有可能解决这个问题。
答案 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中,我们必须在代码中进行手动优化,例如设置分区数,设置持久级别等。我也配置了这些参数。
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/]