[英]How to write a while() loop for an Iterable<Object> in Scala?
[英]How to write for loop with object mutation Scala way?
我需要在Scala中编写一个带有对象突变的for循环。 在机器学习中,当进行聚类(将样本分配到最佳的独立组中)时,为了确定一组中的最佳组数,将使用不同的组号运行聚类算法,并为每个组号计算一些误差度量。 最佳组数是组数图使误差度量成为弯头的地方。 在Spark ML库中, KMeans
对象用于集群,其中组号作为参数传递。 因此,我计算误差度量以绘制肘图,如下所示:
var baseClusterer = new KMeans()
.setFeaturesCol("scaledFeatures")
.setPredictionCol("clusters")
.setSeed(0)
2 to 10 map {
baseClusterer = baseClusterer.setK(k)
baseClusterer.fit(scaledDF).computeCost(scaledDF)
}
我必须将Clusterer对象声明为var,并在每次迭代时对其进行变异。 有没有更多的scala方式来写这个?
您可以避免var这样做:
2 to 10 map { k =>
baseClusterer.setK(k).fit(scaledDF).computeCost(scaledDF)
}
注意:此版本是根据注释从原始版本修改而来的
如果要对其他数据重复此操作,则可能需要考虑创建一个集群列表,然后使用该列表:
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
值一起使用,以避免局部最小值。
如果我正确理解您的逻辑,也许您可以使用foldLeft,在该方法中,每个循环都将返回修改/更新的对象,如下所示:
val finalClusterer = (2 to 10).foldLeft(baseClusterer) { (accum, elem) =>
val newClusterer = accum.copy(k = k)
newClusterer.fit(scaledDF).computeCost(scaledDF)
}
这样一来,您最终将获得一个“ finalClusterer”,在其中始终以基数为原点进行操作。
编辑:我的代码使用baseClusterer作为案例类,因此复制方法。 如果您没有它,因为它似乎是一个Java类,也许您可以创建一个充当包装器的隐式类,然后可以在其中定义这样的方法,如下所示:
implicit class ClustererWrapper {
def copy {
...
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.