【问题标题】:K-means Algorithm with multiple parameters具有多个参数的 K-means 算法
【发布时间】:2017-01-27 23:19:29
【问题描述】:

我在地图上有一组点。我正在尝试创建集群。除了距离之外,我还在考虑每个集群的最大成本(作为另一个参数)。

请找到下面的代码sn-p。

private void assignCluster(List<Cluster> finalClusters, List<Node> clusterNodes, int maxCostLimit) {
    double max = Double.MAX_VALUE;
    double min = max;
    int clusterIndex = 0;
    double distance = 0.0;

    for (Node node : clusterNodes) {
        min = max;
        for (int i = 0; i < finalClusters.size(); i++) {
            Cluster cluster = finalClusters.get(i);
            distance = Point.getDistanceBetweenPoints(node.getPoint(), cluster.getPoint());
            if (distance < min && (cluster.getTotalCost() + node.getCost()) <= maxCostLimit) {
                min = distance;
                clusterIndex = i;
            }
        }
        if (min != max) {
            Cluster cluster = finalClusters.get(clusterIndex);
            cluster.setTotalCost(cluster.getTotalCost() + node.getCost());
            cluster.addClusterNode(node);
        }
    }
}

如果我尝试创建集群,它将进入无限循环。或者,地图上的两个点被分配给两个不同的集群。在每次迭代中,这两个集群的质心都在变化。 请建议我,我怎样才能做到这一点?

编辑

Cluster.java

public class Cluster{
    private List<Node> clusterNodes = new ArrayList<Node>();
    private Integer totalCost = 0;
    private Point2D point;

         //getters and setters
}

Point.java

public class Point{
    private double x = 0;
    private double y = 0;

        // getters and setters

       //method to find the distance between 2 points
}

我指的是基本 Kmeans 算法的链接:http://www.dataonfocus.com/k-means-clustering-java-code/

【问题讨论】:

  • 你能发布你的类Cluster和Point的代码
  • 在我看来,您正陷入局部最优状态。如果我错了,请纠正,但我想你是随机生成你的质心 - 至少你应该这样做。所以我相信你需要一种机制来检查两次迭代之间的状态。例如,您应该能够检测到您的质心是否从 (A1,B1) 移动到 (A2,B2),然后又回到 (A1,B1)。在这种情况下,您需要创建一个新的质心。无论如何发布更多代码会有所帮助。
  • 您是否也可以发布更新质心的代码,一旦您致电assignCluster()
  • 调用assignCluster方法后如何生成簇质心?随着节点“成本”的引入,您有一些根本没有分配给集群的点,这就是您要寻找的吗?
  • 此代码甚至无法编译(缺少返回语句)。请更正。

标签: java algorithm k-means


【解决方案1】:

通常情况下,K-means 算法可以被证明永远不会重复从前一次迭代中将节点分配给集群。

也许这在您的情况下是可能的,因为您引入的成本的额外限制传统上在使用 K-means 时不存在,但也许它仍然不是,我我不确定。

我想知道您如何使用您提供了代码的 assignCluster() 方法。你是否有另一个循环围绕它不断调用assignCluster()finalClusters = 是最新的集群分配列表,clusterNodes = 是所有节点的列表,并一直循环直到它最终得到一个等于的分配上一个?

如果是这样,您确定cluster.addClusterNode() 正确地从其先前的集群中删除了该节点(我认为如果您按照上述方式实现了它应该是这样吗?)。要查看的另一件事可能是(cluster.getTotalDemand() + node.getCost()) 计算。我怀疑,如果您碰巧正在查看该节点已经在其中的集群,您可能不想在该计算中包含 node.getCost(),因为如果它也是 ,它将被计算为双倍包含在cluster.getTotalDemand()中。

我必须对您希望代码做什么,或者您如何实现未显示代码的其他方法做出一些假设......所以您必须指出我的代码中是否有任何错误假设。

【讨论】:

  • 基本 Kmeans 算法适用于距离。我添加了另一个参数成本。在将节点分配给集群时,我也在检查距离和 costLimit。它类似于创建相同大小的集群。
  • @NVG 每个节点的成本都一样吗?如果不是,您可以尝试更改它,使每个节点都具有相同的成本,看看在这种情况下您是否不再陷入无限循环?我怀疑只有在节点可能具有不同的成本时才可能进行交替分配……如果是这种情况,您可以通过保留节点分配到最近几次迭代的集群的历史记录(不止一个),并检查最新的分配是否等于任何最近的 X 个
  • 是的,我已经尝试将成本 1 分配给每个节点。还是一样的:-(
  • @NVG 你能贴出调用assignCluster 函数的循环代码吗?按照您提供的链接,这应该是 calculate 方法。我认为问题一定存在
  • 是的,计算方法中的while循环。
【解决方案2】:

查看您随问题提供的代码并通过链接,我看不出任何导致无限循环的原因(假设您正确调整了代码),但集群总数乘以每个集群的最大成本小于所有节点的总成本。您可以通过在进入循环之前遍历所有节点来检查。

另一个问题可能是,您忘记在 clearClusters() 方法中为每个集群重置 totalCost,但我认为这不会导致无限循环。

为什么你的类的质心是Point2D 而不是你自己的Point 类的对象?

【讨论】:

    猜你喜欢
    • 2013-07-03
    • 2010-12-05
    • 2017-04-20
    • 2013-04-22
    • 2011-09-15
    • 2015-08-16
    • 2017-04-27
    相关资源
    最近更新 更多