启者
我正在使用DataSet API在Apache Flink中使用Batch,我想计算DataSet中所有元素的“相似性”。
让函数CalculateSimilarity(e1,e2)计算并返回元素e1和e2的相似度。
将数据集与自身交叉工作正常,但是,我浪费了大量时间并且没有必要的微积分处理。我真的不需要计算所有元素的笛卡尔积,因为,有可能做出一些改进:
i)不需要计算相同元素的相似性。例如CalculateSimilarity(A,A)
ii)计算相似度(A,B)⇔计算相似度(B,A)。相似之处(A,B)和(B,A)是等价物,我只需要计算其中一个。
使用flink,我怎么能应用一个转换,我可以计算出必要的相似性,而不是所有的相似性(交叉)?
如果我上面不清楚,这是一个简单的例子:
Dt =具有4个元素的数据集
Dt = {e1,e2,e3,e4}
我使用cross(Dt.cross(Dt)),它返回所有这些组合:((e1,e1),(e1,e2),(e1,e3),(e1,e4),(e2,e1), (E2,E2),(E2,E3),(E2,E4),(E3,E1),...,(E4,E4))。
但是,我只需要这种组合:(e1,e2),(e1,e3),(e1,e4),(e2,e3),(e2,e4),(e3,e4)。
感谢您的帮助!
答案 0 :(得分:0)
您可以做的是手动构建一个避免排列的连接模式。你可以通过为每个元素分配一个增加的索引(0到元素的数量 - 1)然后让每个元素只与索引低于或等于它自己的元素连接来做到这一点:
val env = ExecutionEnvironment.getExecutionEnvironment
val input = env.fromElements(1, 2, 3, 4, 5, 6).rebalance()
// we first assign an increasing index from 0 to input.size - 1 to each element
val indexedInput = input.zipWithIndex
// here we generate the join set where we say that (idx, element) will be joined with all
// elements whose index is at most idx
val joinSet = indexedInput.flatMap{
input => for (i <- 0 to input._1.toInt) yield (i.toLong, input._2)
}
// doing the join operation
val resultSet = indexedInput.join(joinSet).where(_._1).equalTo(_._1).apply{
(a, b) => (a._2, b._2)
}
您应该尝试更快地运行哪些程序,因为zipWithIndex
将触发单独的作业执行。