如何用对象突变Scala方式编写for循环?

时间:2018-10-01 12:46:58

标签: scala

我需要在Scala中编写一个带有对象突变的for循环。在机器学习中,当进行聚类(将样本分配到最佳的独立组中)时,为了确定一组中的最佳组数,将使用不同的组号运行聚类算法,并为每个组号计算一些误差度量。最佳组数是组数图使误差度量成为弯头的地方。 在Spark ML库中,public function getTeam(Team $team) { // The team parameter is the given Team model instance. // We can use directly return response()->json($team); } 对象用于对组号作为参数进行传递的群集。因此,我计算误差度量以绘制肘形图,如下所示:

KMeans

我必须将集群对象声明为var,并在每次迭代时对其进行变异。有没有更多scala方式来编写此代码?

3 个答案:

答案 0 :(得分:3)

您可以避免var这样做:

2 to 10 map { k =>
     baseClusterer.setK(k).fit(scaledDF).computeCost(scaledDF)
}

答案 1 :(得分:2)

注意:此版本是根据评论从原始版本修改的

如果要对其他数据重复此操作,则可能需要考虑创建一个集群列表,然后使用该列表:

val clusterers = (2 to 10).map(k =>
  new KMeans()
    .setFeaturesCol("scaledFeatures")
    .setPredictionCol("clusters")
    .setSeed(0)
    .setk(k)
)

val costs = clusterers.map(_.fit(scaledDF).computeCost(scaledDF))

但是请参阅@BogdanVakulenko的答案,以找到重写原始版本的好方法。

还请注意,最好反复使用相同的k和不同的setSeed值来避免局部最小值。

答案 2 :(得分:0)

如果我正确理解了您的逻辑,也许您可​​以使用foldLeft,在该方法中,每个循环都将返回修改/更新的对象,如下所示:

val finalClusterer = (2 to 10).foldLeft(baseClusterer) { (accum, elem) =>
    val newClusterer = accum.copy(k = k)
    newClusterer.fit(scaledDF).computeCost(scaledDF)
}

这样一来,您最终将得到一个“ finalClusterer”,在其中始终以基数为原点进行操作。

编辑:我的代码使用baseClusterer作为case类,因此使用copy方法。如果您没有它,因为它好像是一个Java类,也许您可​​以创建一个充当包装器的隐式类,然后可以在其中定义这样的方法:

implicit class ClustererWrapper {
    def copy {
    ...
    }
}
相关问题