孤独腹地 2021-11-13 16:07 采纳率: 100%
浏览 42
已结题

kmeans++聚类聚成这样合理吗

kmeans++聚类聚成这样合理吗
聚类的算法代码如下

class Kmeans:
    def __init__(self, k, threshold=1e-5):
        self.k = k
        self.threshold = threshold
    
    def centroid_init(self,X):
        centroids = []
        centroids.append(X[np.random.choice(X.shape[0])])
        for i in range(self.k-1):
            D = []
            for x in X:
                D.append(np.min([np.linalg.norm(x - c) for c in centroids]))
            centroids.append(X[np.argmax(D)])
        return np.array(centroids)
                              
    def train(self, X):
        # 初始化聚类中心
        self.centroids = self.centroid_init(X)
        y_pred = np.zeros(shape=(X.shape[0],))
        while True:
            # 涂色
            for i, x in enumerate(X):
                y_pred[i] = self.predict(x)
            
            # 计算新的聚类中心
            new_centroids = self.centroids.copy()
            for i in range(self.k):
                new_centroids[i] = X[y_pred==i].mean()
            
            # 如果聚类中心位置基本没有变化,那么终止
            if np.max(np.abs(new_centroids - self.centroids)) < self.threshold:
                break
            
            # 否则更新聚类中心,重复上述步骤
            self.centroids = new_centroids
        return y_pred

    def predict(self, x):
        dis = []
        # 计算每个样本与中心的距离
        for c in self.centroids:
            dis.append(np.linalg.norm(x - c))
        # 将样本索引添加到距离最小的中心对应的分类中
        return np.argmin(dis)

下图左边是原数据分布,右边是上面的算法生成的聚类分布

img

  • 写回答

1条回答 默认 最新

  • 孤独腹地 2021-11-13 21:22
    关注

    唉,终究是解决了,求均值的时候X[y_pred==i].mean()没加axis=0
    顺便把新实现的代码贴一下吧

    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn.datasets import make_blobs
    
    class Kmeans:
        def __init__(self, k, init='pp-soft', max_iter=300, thresh=1e-5):
            self.k = k
            self.thresh = thresh
            self.max_iter = max_iter
            self.init = init
    
        def random_centroid_init(self,X):
            # 随机选取K个样本作为聚类中心
            return X[np.random.choice(X.shape[0], size=self.k)]
        
        def max_centroid_init(self,X):
            centroids = []
            centroids.append(X[np.random.choice(X.shape[0])])
            for i in range(self.k-1):
                index = np.argmax([np.min(self.dist(x)) for x in X])
                centroids.append(X[index])
            return np.array(centroids)
    
        def soft_centroid_init(self,X):
            centroids = []
            centroids.append(X[np.random.choice(X.shape[0])])
            for i in range(self.k-1):
                D = [np.min(self.dist(x)) for x in X]
                number = np.random.choice(int(np.sum(D)))
                for i,d in enumerate(D):
                    number -= d
                    if number<0:
                        centroids.append(X[i])
                        break
            return np.array(centroids)
    
        def dist(self, x):
            return [np.linalg.norm(x - c) for c in self.centroids]
    
        def fit_predict(self, X):
            # 初始化聚类中心
            if self.init == 'random':
                self.centroids = self.random_centroid_init(X)
            elif self.init == 'pp-max':
                self.centroids = self.max_centroid_init(X)
            else:
                self.centroids = self.soft_centroid_init(X)
            for _ in range(self.max_iter):
                # 涂色
                y_pred = np.array([np.argmin(self.dist(x)) for x in X])
                
                # 计算新的聚类中心
                new_centroids = self.centroids.copy()
                for i in range(self.k):
                    new_centroids[i] = np.mean(X[y_pred==i],axis=0)
                
                # 如果聚类中心位置基本没有变化,那么终止
                if np.max(np.abs(new_centroids - self.centroids)) < self.thresh:
                    break
                
                # 否则更新聚类中心,重复上述步骤
                self.centroids = new_centroids
            return y_pred
        
    X, y = make_blobs(n_samples=1000, n_features=2, centers=3)
    
    model = Kmeans(3)
    y_pred = model.fit_predict(X)
    
    plt.figure()
    plt.subplot(121)
    plt.scatter(X[:, 0], X[:, 1], c=y)
    plt.subplot(122)
    plt.scatter(X[:, 0], X[:, 1], c=y_pred)
    plt.show()
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 系统已结题 11月21日
  • 已采纳回答 11月13日
  • 创建了问题 11月13日

悬赏问题

  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记