You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自制KMeans聚类算法运行结果不一致的问题求助

自制KMeans聚类算法运行结果不一致的问题求助

我正在尝试实现一个简化版的KMeans聚类算法,但有时候运行结果会出现异常,不是每次都能得到合理的聚类效果,这是怎么回事呢?

以下是我的KMeans实现代码:

import numpy as np
import random

import matplotlib.pyplot as plt

class KMeans:
    def __init__(
        self,
        n_clusters,
        max_iter
    ):
        self.n_clusters = n_clusters
        self.max_iter = max_iter
    
    def _get_distance(self, x, cluster_location):
        """calculate the euclidean distance from each points to the clusters center
        """
        return np.linalg.norm(x[:,np.newaxis,:]-cluster_location, axis = 2)
        
    def fit(self, x:np.ndarray) -> None:
        """Steps for k-means clustering
        1. initiate cluster location
        2. calculate distance from each points to cluster point
        3. assign each points to a cluster
        4. update the cluster location using the mean of the associated points
        5. repeat 2-4 until convergence or max_iter reached

        Args:
            x (_type_): _description_

        Returns:
            _type_: _description_
        """
        self.x = x
        data_dim = x.shape[1]

        # 1. initiate cluster location
        cluster_locations = np.random.uniform(x.min(), x.max(), size=(self.n_clusters,data_dim))
        # print("initial:\n",cluster_locations)

        for _ in range(self.max_iter):
            # 2. calculate distance from each points to cluster point
            distances = self._get_distance(x, cluster_locations)

            # 3. assign each points to a cluster
            clusters = np.argmin(distances, axis=1)

            # 4. update the cluster location using the mean of the associated points
            for cluster in range(self.n_clusters):
                # Check if cluster has any points
                cluster_mask = clusters == cluster
                if np.any(cluster_mask):
                    cluster_locations[cluster] = np.mean(x[cluster_mask], axis=0)
                else:
                    # If cluster is empty, reinitialize with a random point
                    cluster_locations[cluster] = x[np.random.randint(x.shape[0])]                        

        self.cluster_locations = cluster_locations
        self.clusters = clusters
        return None

    def visualize(self, data, clusters):
        _, ax = plt.subplots(1,1,figsize=(5,5))

        cluster_color = [(random.random(),random.random(),random.random()) for _ in range(self.n_clusters)]

        for cluster in range(self.n_clusters):
            to_plot = data[np.where(clusters == cluster)[0]]
            ax.scatter(to_plot[:,0], to_plot[:,1], color=cluster_color[cluster])
        ax.scatter(self.cluster_locations[:,0], self.cluster_locations[:,1], marker="x", color='r', s=30)

        plt.show()

我是这样使用这个类的:

from sklearn.datasets import make_blobs

random_state = 42
n_samples = 100

x, _ = make_blobs(n_samples=n_samples, random_state=random_state)
my_kmeans = KMeans(3, 50)
my_kmeans.fit(x)
my_kmeans.visualize(x, my_kmeans.clusters)

大部分时候,运行结果是合理的:
合理输出示例:三个样本簇被正确区分,红色叉号标记的质心位置准确处于每个簇的中心区域。

但每隔几次运行,就会得到异常的结果:
异常输出示例:其中一个质心位置明显偏离对应簇,导致部分样本被错误划分,聚类效果完全不符合预期。

我是不是在实现过程中漏掉了什么关键细节?

备注:内容来源于stack exchange,提问作者Amri Rasyidi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 17:48:06