K-means 是最常用的基于欧式距离的 机器学习 聚类算法,其认为两个目标的距离越近,相似度越大。K-means是无监督学习的基础算法。
一、牧师—村民模型
四个牧师,随机选了四个布道点,村民到离自己最近的布道点听课。
每个牧师统计自己的课上村民的地址,把布道点搬到中心位置。
就这样,牧师每个礼拜更新自己的位置,村民根据自己的情况选择布道点,最终稳定了下来。
二、K-means 的算法步骤
1、选择初始化的 n 个样本,作为初始聚类中心 a=a1,a2,a3...an;
2、针对数据集中每个样本 xi,计算它到 k 个聚类中心的距离,并将其分到距离最小的聚类中心所对应的类中;
3、针对每个类别 aj ,重新计算它的聚类中心(即属于该类的所有样本的质心);
4、重复上面 2 3 两步操作,直到达到某个中止条件(迭代次数、最小误差变化等)。
三、优缺点
1、容易理解,算法复杂度低;
2、K值需要人为设定,不同K值对结果影响较大;
3、对初始的簇中心敏感,不同选取方式会得到不同结果;
4、对异常值敏感,不适合太离散的分类。
四、代码示例
1. 生成随机样本
from matplotlib import pyplot as plt from sklearn.datasets._samples_generator import make_blobs X, _ = make_blobs(200, 2, centers=[[2, 3], [6, 8]]) plt.scatter(X[:, 0], X[:, 1]) plt.show()
2. 定义类,并初始化
class KMeans(): def init(self, k, iter_max): self.k = k #聚类数量 self.iter_max = iter_max #最大迭代次数 def fit(self, X): self.X = X #样本数据
3. 随机生成中心点
# 随机中心点 idxs = random.sample(range(len(self.X)), self.k) self.centers = self.X[idxs]
4. 分类和计算距离
def _classify(self): sum_dist = 0 self.classes = [[] for i in range(self.k)] self.labels = [] for x in X: dists = ((np.tile(x, (self.k, 1)) - self.centers)**2).sum(1) #找最小距离 label = np.argsort(dists)[0] self.labels.append(label) #累加最小距离 sum_dist += dists[label] #分类 self.classes[label].append(x) #判断是否收敛 if abs(self.sum_dist - sum_dist) >= 0.1 and self.iter_num<=self.iter_max: self.sum_dist = sum_dist else: return True
5. 更新中心点
def _up_centers(self): centers = [] for lst in self.classes.values(): arr = np.array(lst) centers.append(arr.mean(axis=0)) self.centers = np.array(centers)
6. 循环迭代
while True: #分类及最小距离 r = self._classify() self.iter_num += 1 if r: return self #更新中心点 self._up_centers()
7. 效果可视化
colors = ['red', 'blue', 'green', 'yellow'] for x, l in zip(X, kmeans.labels): plt.scatter(x[0], x[1], c=colors[l]) plt.show()
本文为 陈华 原创,欢迎转载,但请注明出处:http://edu.ichenhua.cn/read/249