MinHash Spark ML 中与 OR 条件的字符串相似度
String similarity with OR condition in MinHash Spark ML
我有两个数据集,第一个是大型参考数据集,第二个数据集将通过 MinHash 算法从第一个数据集中找到最佳匹配。
val dataset1 =
+-------------+----------+------+------+-----------------------+
| x'| y'| a'| b'| dataString(x'+y'+a')|
+-------------+----------+------+------+-----------------------+
| John| Smith| 55649| 28200| John|Smith|55649|
| Emma| Morales| 78439| 34200| Emma|Morales|78439|
| Janet| Alvarado| 89488| 29103| Janet|Alvarado|89488|
| Elizabeth| K| 36935| 38101| Elizabeth|K|36935|
| Cristin| Cruz| 75716| 70015| Cristin|Cruz|75716|
| Jack| Colello| 94552| 15609| Jack|Colello|94552|
| Anatolie| Trifa| 63011| 51181| Anatolie|Trifa|63011|
| Jaromir| Plch| 51237| 91798| Jaromir|Plch|51237|
+-------------+----------+------+------+-----------------------+
// very_large
val dataset2 =
+-------------+----------+------+-----------------------+
| x| y| a| dataString(x+y+a)|
+-------------+----------+------+-----------------------+
| John| Smith| 28200| John|Smith|28200|
| Emma| Morales| 17706| Emma|Morales|17706|
| Janet| Alvarado| 98809| Janet|Alvarado|98809|
| Elizabeth| Keatley| 36935|Elizabeth|Keatley|36935|
| Cristina| Cruz| 75716| Cristina|Cruz|75716|
| Jake| Colello| 15609| Jake|Colello|15609|
| Anatolie| Trifa| 63011| Anatolie|Trifa|63011|
| Rune| Eide| 41907| Rune|Eide|41907|
| Hortensia| Brumaru| 33836|Hortensia|Brumaru|33836|
| Adrien| Payet| 40463| Adrien|Payet|40463|
| Ashley| Howard| 12445| Ashley|Howard|12445|
| Pamela| Dean| 81311| Pamela|Dean|81311|
| Laura| Calvo| 82682| Laura|Calvo|82682|
| Flora| Parghel| 81206| Flora|Parghel|81206|
| Jaromír| Plch| 91798| Jaromír|Plch|91798|
+-------------+----------+------+-----------------------+
为了字符串相似性,创建了| (管道)分隔 dataString
。
这是 dataString (x' + y' + a')
和 dataString(x + y + a)
的相似性查找代码,工作正常,
val tokenizer = new RegexTokenizer().setPattern("\|").setInputCol("dataString").setOutputCol("dataStringWords")
val vectorizer = new CountVectorizer().setInputCol("dataStringWords").setOutputCol("features")
val pipelineTV = new Pipeline().setStages(Array(tokenizer, vectorizer))
val modelTV = pipelineTV.fit(dataset1)
val isNoneZeroVector = udf({v: Vector => v.numNonzeros > 0}, DataTypes.BooleanType)
val dataset1_TV = modelTV.transform(dataset1).filter(isNoneZeroVector(col("features")))
val dataset2_TV = modelTV.transform(dataset2).filter(isNoneZeroVector(col("features")))
val lsh = new MinHashLSH().setNumHashTables(20).setInputCol("features").setOutputCol("hashValues")
val pipelineLSH = new Pipeline().setStages(Array(lsh))
val modelLSH = pipelineLSH.fit(dataset1_TV)
val dataset1_LSH = modelLSH.transform(dataset1_TV)
val dataset2_LSH = modelLSH.transform(dataset2_TV)
val finalResult = modelLSH.stages.last.asInstanceOf[MinHashLSHModel].approxSimilarityJoin(dataset1_LSH, dataset2_LSH, 0.5)
finalResult.show
如上所述,代码给出了完美的结果,但我的要求是,我必须将 a
与 a'
或 b'
进行比较,即
x' + y' + (a' OR b')
x + y + ( a )
这里我不能加入这两个数据集,因为它们没有公共字段,否则会交叉加入。
那么有什么方法可以在 Apache Spark 2.2.0 中的分组数据中使用 OR 条件实现字符串相似性。
我认为不可能设置两个输入列(每个使用的元素 a'
或 b'
一个 dataString
列)然后在计算时使用 OR 但是您可以转换 dataset1
来表示 x' + y' + a'
和 x' + y' + b'
变体,然后进行距离计算。它不会给你完全相同的答案,就好像你根据 dataset2
中的相应行选择 a'
或 b'
(我想你知道如何做那个昂贵的操作)但是还是给人一些相似感。
val dataset1splitted =
dataset1
.withColumn( "a", explode( array( "a'", "b'" ) ) )
.drop( "a'", "b'", "dataString" )
.withColumn( "dataString", concat_ws( "|", $"x'", $"y'", $"a" ) )
我有两个数据集,第一个是大型参考数据集,第二个数据集将通过 MinHash 算法从第一个数据集中找到最佳匹配。
val dataset1 =
+-------------+----------+------+------+-----------------------+
| x'| y'| a'| b'| dataString(x'+y'+a')|
+-------------+----------+------+------+-----------------------+
| John| Smith| 55649| 28200| John|Smith|55649|
| Emma| Morales| 78439| 34200| Emma|Morales|78439|
| Janet| Alvarado| 89488| 29103| Janet|Alvarado|89488|
| Elizabeth| K| 36935| 38101| Elizabeth|K|36935|
| Cristin| Cruz| 75716| 70015| Cristin|Cruz|75716|
| Jack| Colello| 94552| 15609| Jack|Colello|94552|
| Anatolie| Trifa| 63011| 51181| Anatolie|Trifa|63011|
| Jaromir| Plch| 51237| 91798| Jaromir|Plch|51237|
+-------------+----------+------+------+-----------------------+
// very_large
val dataset2 =
+-------------+----------+------+-----------------------+
| x| y| a| dataString(x+y+a)|
+-------------+----------+------+-----------------------+
| John| Smith| 28200| John|Smith|28200|
| Emma| Morales| 17706| Emma|Morales|17706|
| Janet| Alvarado| 98809| Janet|Alvarado|98809|
| Elizabeth| Keatley| 36935|Elizabeth|Keatley|36935|
| Cristina| Cruz| 75716| Cristina|Cruz|75716|
| Jake| Colello| 15609| Jake|Colello|15609|
| Anatolie| Trifa| 63011| Anatolie|Trifa|63011|
| Rune| Eide| 41907| Rune|Eide|41907|
| Hortensia| Brumaru| 33836|Hortensia|Brumaru|33836|
| Adrien| Payet| 40463| Adrien|Payet|40463|
| Ashley| Howard| 12445| Ashley|Howard|12445|
| Pamela| Dean| 81311| Pamela|Dean|81311|
| Laura| Calvo| 82682| Laura|Calvo|82682|
| Flora| Parghel| 81206| Flora|Parghel|81206|
| Jaromír| Plch| 91798| Jaromír|Plch|91798|
+-------------+----------+------+-----------------------+
为了字符串相似性,创建了| (管道)分隔 dataString
。
这是 dataString (x' + y' + a')
和 dataString(x + y + a)
的相似性查找代码,工作正常,
val tokenizer = new RegexTokenizer().setPattern("\|").setInputCol("dataString").setOutputCol("dataStringWords")
val vectorizer = new CountVectorizer().setInputCol("dataStringWords").setOutputCol("features")
val pipelineTV = new Pipeline().setStages(Array(tokenizer, vectorizer))
val modelTV = pipelineTV.fit(dataset1)
val isNoneZeroVector = udf({v: Vector => v.numNonzeros > 0}, DataTypes.BooleanType)
val dataset1_TV = modelTV.transform(dataset1).filter(isNoneZeroVector(col("features")))
val dataset2_TV = modelTV.transform(dataset2).filter(isNoneZeroVector(col("features")))
val lsh = new MinHashLSH().setNumHashTables(20).setInputCol("features").setOutputCol("hashValues")
val pipelineLSH = new Pipeline().setStages(Array(lsh))
val modelLSH = pipelineLSH.fit(dataset1_TV)
val dataset1_LSH = modelLSH.transform(dataset1_TV)
val dataset2_LSH = modelLSH.transform(dataset2_TV)
val finalResult = modelLSH.stages.last.asInstanceOf[MinHashLSHModel].approxSimilarityJoin(dataset1_LSH, dataset2_LSH, 0.5)
finalResult.show
如上所述,代码给出了完美的结果,但我的要求是,我必须将 a
与 a'
或 b'
进行比较,即
x' + y' + (a' OR b')
x + y + ( a )
这里我不能加入这两个数据集,因为它们没有公共字段,否则会交叉加入。
那么有什么方法可以在 Apache Spark 2.2.0 中的分组数据中使用 OR 条件实现字符串相似性。
我认为不可能设置两个输入列(每个使用的元素 a'
或 b'
一个 dataString
列)然后在计算时使用 OR 但是您可以转换 dataset1
来表示 x' + y' + a'
和 x' + y' + b'
变体,然后进行距离计算。它不会给你完全相同的答案,就好像你根据 dataset2
中的相应行选择 a'
或 b'
(我想你知道如何做那个昂贵的操作)但是还是给人一些相似感。
val dataset1splitted =
dataset1
.withColumn( "a", explode( array( "a'", "b'" ) ) )
.drop( "a'", "b'", "dataString" )
.withColumn( "dataString", concat_ws( "|", $"x'", $"y'", $"a" ) )