K-Means 算法

Posted 致于数据科学家的小陈

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了K-Means 算法相关的知识,希望对你有一定的参考价值。

简单总结一波k-means

认识

K-Means 是属于聚类算法中的一种, 聚类算法呢, 是属于 无监督学习. 不需要数据的标签(label). 主要用途是为了发现数据中的规律(模式), 就咱平时说的数据挖掘. 使用的场景, 从营销领域来看, 可用来做用户细分, 行为聚类, 精准营销, 推荐系统等, 当然在其他领域,诸如图像分割, 生物研究也可以的.

无监督: 就是只计算特征之间的关系不关注label. 场景的,如 聚类, PCA...

一言蔽之, 物以类聚, 人以群分. 核心是把相似的物体聚在一起, 处理上则是计算物体间的相似度.

K-Means 算法

是一种循环迭代式的算法.

初始化

  • 随机选择 K 个点, 作为初始点的中心, 每个点作为一个 group.

交替更新

  • 计算每个点到中心点的距离, 把最近的距离记录并将group赋给当前的点
  • 针对每一个group的点,计算其平均并作为这个group的新中心点

循环上两步即可, 从代码的角度讲, 停止循环有两个注意点

  • 外层循环,设置一个最大循环次数, 比如100次.
  • 计算中心点, 前后两次位置不变(完全分开了呀)

伪代码

为了说明意思, 搬的伪代码哈, 有空再好好写一波.

def dist_eclud(arr1, arr2):
"""计算两个点之间的欧式距离"""
return np.sqrt(np.sum((arr1 - arr2)**2))

def random_center(X, k):
"""随机初始化k个中心点,X 是(n, p)维的样本"""
# 获取样本矩阵的行列数
n, p = np.shape(X)
#创建 k 行 p 列的全为0 的矩阵
center = np.matrix(np.zeros([k, p]))
for j in range(p):
min_j = np.min(X[:,j])
# 计算极值
range_j = float(np.max(X[:,j]) - min_j)
# 得到 k 个随机中心点, 每个点是p维度
center[:,j] = np.mat(min_j + range_j * np.random.rand(k, 1))
return center

def fit(X, k):
# 获取样本数(行数)
n,p = np.shape(X)
# 创建一个n行p列的矩阵
cluster = np.mat(np.zeros([n,p]))
# 随机初始化k个中心点,每个点是p维
center = random_center(X, k)

while True:
for i in range(n):
# 初始化最小距离 (默认非常大)
min_dist = np.inf
# 中心点下标
min_index = 0
# 计算k个中心点到该样本的距离
for j in range(k):
dist_j = dist_eclud(center[j,:], X[i,:])
# 更新最小距离
if dist_j < min_dist:
min_dist = dist_j
min_index = j
# 判断: 如果中心点前后没有变化,说明不能再继续分, 则终止循环
if cluster[i, 0] != min_index:
break
# 将 index, k中心点, 最小距离存到数组
cluster[i, :] = min_index, min_dist**2
# 打印中心点
print(center)

# 更新中心点的位置
for i in range(k):
# 平铺cluster 为一个一维数组, 分别找到属于k类的数据
points = dataSet[np.nonzero(cluster[:,0].A == i)[0]]
#得到更新后的中心点
center[i,:] = np.mean(points, axis = 0)
return center, cluster

K-Means 算法特性

当然是考量每一次迭代的复杂度了.

第一步的选取 k 个点, 这里不考虑了, 关键是计算和迭代的部分.

首先,计算每个点到中心点的距离, 把最近的距离记录下来并把group赋给当前点. 假设有 n个样本点.则此过程的时间复杂度为:

\\(O(kn)\\)

因为有 k 个中心点. 每次计要把 n 个点 计算到 k 个点的距离

然后, 针对每一个 group 里的点, 计算平均作为这个 group 的新中心点. 则此过程的时间复杂度为:

\\(O(n)\\)

K-means 的几点思考

目标函数

已知观测集 \\((x_1, x_2, ... x_n)\\) 其中每个观测 xi 都是 d 维的实向量. k-平均聚类, 就是要把 这n个观测划分到 k 个集合中 ( k <= n) , 使得簇内平方和最小. 即找到使得下式满足的聚类 \\(S_i\\)

\\(arg \\ min _S \\ \\sum \\limits _i=1^k \\sum \\limits _x \\in S_i ||X-\\mu_i||^2\\)

\\(\\mu_i\\) 是 \\(S_i\\)

\\(\\sum \\limits _x \\in S_i ||X-\\mu_i||^2\\)

外层的求和, 是对每个类到其自身中心的距离, 总体上达到最小

关键: 是如何找到这些 xi

是否一定会收敛

是的

首先, 将N个数据分为 k 个聚类, 最多有 \\(k^N\\)

  • 如果旧的聚类和新的聚类相同, 则下一次迭代的结果也再次相同
  • 新,旧不同, 则更新的群集的目标函数值较低

其次, 算法的不同迭代, 最终会进入一个循环, 即k均值在有限的迭代次数中收敛

不同初始化对结果的影响

不同初始点,会带来不同的结果

K 如何选择

inertia: 群集中,所有点离其所属cluster中心的距离的总和.

不论数据集如何, 随着k的增加, inertia 呈递减趋势, 开始速度很快, 慢慢变小, 会存在一个拐点.

极限情况是, 每一个点都各自一类, 则总距离为0了, 也就没有了所谓 "聚类的存在

KMeans ++

  • 从数据集中随机选择一个中心
  • 对于每个 xi, 计算与**已经选择的最接近中心之间的距离 **D(xi)
  • 使用加权概率分布随机选择一个新的数据点作为新中心, 该点的概率与 \\(D(x_i)^2\\)
  • 重复步骤 2,3 直到选择了 k 个中心
  • 根据选择好了的初始中心, 继续使用k-means 聚类

这种算法, 其实就是在选择初始中心的时候, 尽可能 "分布在数据四周" , 后面不变.

KMeans 优缺点

优点

  • 容易理解和实现
  • 结果的解释性强
  • 计算复杂度低

缺点

  • 异常值 和 初始化 非常敏感
  • 对数据的分布不均匀 条件下, 效果不太理想 (样本不均衡就有点麻烦)
  • 默认前提假设是特征之间的联合分布是椭圆形的, S形, 环形就凉凉了 ( svm 线性不可分)
  • 即便 k 给定, 聚类的结果也不唯一. 最好要多调试几次, 选择 inertia 最小时的参数

耐心和恒心, 总会获得回报的.



以上是关于K-Means 算法的主要内容,如果未能解决你的问题,请参考以下文章

机器学习---算法---k-means算法

03-01 K-Means聚类算法

4.K-MEANS聚类算法

关于K-Means算法

K-Means聚类算法原理

K-Means聚类算法原理