我是Apache Spark的新手,希望从一堆文本中找到类似的文字,试过自己如下 -
我有2个RDD -
第一个RDD包含不完整的文本,如下所示 -
[0,541 Suite 204, Redwood City, CA 94063]
[1,6649 N Blue Gum St, New Orleans,LA, 70116]
[2,#69, Los Angeles, Los Angeles, CA, 90034]
[3,98 Connecticut Ave Nw, Chagrin Falls]
[4,56 E Morehead Webb, TX, 78045]
第二个RDD包含正确的地址,如下所示 -
[0,541 Jefferson Avenue, Suite 204, Redwood City, CA 94063]
[1,6649 N Blue Gum St, New Orleans, Orleans, LA, 70116]
[2,25 E 75th St #69, Los Angeles, Los Angeles, CA, 90034]
[3,98 Connecticut Ave Nw, Chagrin Falls, Geauga, OH, 44023]
[4,56 E Morehead St, Laredo, Webb, TX, 78045]
编写了这段代码,花了很多时间,任何人都可以告诉我使用scala在Apache Spark中执行此操作的正确方法。
val incorrect_address_count = incorrect_address_rdd.count()
val all_address = incorrect_address_rdd.union(correct_address_rdd) map (_._2.split(" ").toSeq)
val hashingTF = new HashingTF()
val tf = hashingTF.transform(all_address)
.zipWithIndex()
val input_vector_rdd = tf.filter(_._2 < incorrect_address_count)
val address_db_vector_rdd = tf.filter(_._2 >= incorrect_address_countt)
.map(f => (f._2 - input_count, f._1))
.join(correct_address_rdd)
.map(f => (f._2._1, f._2._2))
val input_similarity_rdd = input_vector_rdd.cartesian(address_db_vector_rdd)
.map(f => {
val cosine_similarity = cosineSimilarity(f._1._1.toDense, f._2._1.toDense)
(f._1._2, cosine_similarity, f._2._2)
})
def cosineSimilarity(vectorA: Vector, vectorB: Vector) = {
var dotProduct = 0.0
var normA = 0.0
var normB = 0.0
var index = vectorA.size - 1
for (i <- 0 to index) {
dotProduct += vectorA(i) * vectorB(i)
normA += Math.pow(vectorA(i), 2)
normB += Math.pow(vectorB(i), 2)
}
(dotProduct / (Math.sqrt(normA) * Math.sqrt(normB)))
}
答案 0 :(得分:1)
您可以做两项重大改进。一个是预先计算的规范。他们不会改变。第二是使用稀疏向量。你去vector.size它是300K,如果你这样做。如果你使用Sparse,它会针对每个关键字进行迭代。(每行20-30个)。
另外我担心这是最有效的方式,因为计算不需要洗牌。如果你最后有一个很好的估计,你可以按分数过滤,事情会很快。(我的意思是哪个分数足够你。 )
def cosineSimilarity(vectorA: SparseVector, vectorB:SparseVector,normASqrt:Double,normBSqrt:Double) :(Double,Double) = {
var dotProduct = 0.0
for (i <- vectorA.indices){
dotProduct += vectorA(i) * vectorB(i)
}
val div = (normASqrt * normBSqrt)
if( div == 0 )
(dotProduct,0)
else
(dotProduct,dotProduct / div)
}