# 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)
``````

• 写回答

#### 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 爬取网页信息并附加完整代码
• ¥15 CST2023安装报错