K-means算法
算法原理
- 随机选取k个点作为初始聚类中心
- 计算各个数据点到初始聚类中心的距离,比较其距离将每个数据点归类到最近的聚类中心
- 样本全部划分后重新计算k个类的聚类中心
- 重复1~3的步骤,直至这k个聚类中心不再改变(收敛)
对数据的要求
- 对于 缺失值需要处理(填充或者删除)
- 分类变量需要编码(涉及距离计算)
- 数据需要标准化或者归一化处理(消除量纲的影响。涉及距离计算的算法都需要考虑)
算法的优缺点
一、优点
- 原理简单,容易实现
- 对于大数据集,可保持伸缩性与高效性
- 当簇接近高斯分布时,算法的效果较好
一、缺点
- k值难以确定
- 对于噪声与孤立数据(异常点)敏感
- 随机初始值的选取对结果影响很大
- 结果不一定是全局最优,只能保证局部最优(与初始点的选取有着很大的关系)
算法需要注意的点
1. 初始点的选择对KNN算法最后的结果有什么影响?
不合理的初始点的选取会导致长时间无法收敛且得到局部最优
2. 每个类别的中心初始点如何选择?
①随机法②选择各批次距离近可能的k个点③选择层次聚类或者Canopy处理
3. k值怎么确定?
①比较类内距离,类间距离确定k(平均轮廓系数(大)或类内距离/类间距离(小))
轮廓系数:
注:该值越大聚类效果越好。其中b(i)是该簇中i样本到b簇所有点的平均距离,遍历所有其它簇找到最近的这个平均距离,记做b(i),即为i的邻居类,用于量化簇之间分离度。其中a(i)是样本点i与其同一簇内所有其它元素距离的平均值,记做a(i),用于量化簇内凝聚度
②按需选择、观察法或者手肘法
手肘法: 随着k的增大,样本会被划分的更加精细,每个簇的聚合度会逐渐提高,那么误差平方和SSE自然会逐渐变小。并且当k小于真实聚类时,由于k的增大会大幅增加每个簇的聚合程度,故SSE下降幅度会很大,而当k达到真实聚类时,在增加k所得到的聚合程度回报会迅速变小,所以SSE下降幅度会骤减,然后趋于k的增加与趋于平缓
4. k-means是否会一直陷入选择质心的循环停不下来?
不会。有数学证明一定会收敛(利用SSE的概念,每个点到自身所属质心距离平方和是个凸函数,有局部最优解)
5. 如何对k-means的效果进行评估?
轮廓系数、手肘法或者收敛阈值
6. 如何快速收敛数据集较大的k-means?
①第一次迭代的时候正常进行,选取k个初始点,然后计算所有的节点到这些k的距离,再分到不同的组计算新的质心
②后续迭代的时候,在第m次开始,每次不再计算每个点到所有k个质心的距离,仅仅计算上一次迭代中离这个节点最近的某几个(2到3)个质心的距离,决定分组的归属。对于其它质心,因为距离实在太远所以归属到哪些组的可能性会非常非常小,所以不再重复计算距离
③用正常的迭代终止方法,结束迭代
注:
①如何选择m次?(过早会导致后面的那个归属到远距离组的可能性会增加,过晚收敛速度不够)
比较每个质心偏移量,接近优化的阈值20%,结束收敛的阈值10%
②最近的质心个数怎么选取?(过多收敛速度不明显,过少可能出现分组错误)
排序距离选最近的20%那些质心点
算法实现(python)
import pandas as pd
from sklearn import preprocessing
from sklearn.cluster import KMeans
#读取数据
data = pd.read_excel(r'E:/wyz/Desktop/data.xlsx')
#填充缺失值(均值填充)
for i in list(data.columns):
data[i] = data[i].fillna(data[i].mean())
#数据标准化
data1 = preprocessing.scale(data)
data2 = pd.DataFrame(data1,columns = list(data.columns))
#聚类成3类
clf = KMeans(n_clusters=3)
clf.fit(data3)
K-means参数详解
参数 | 默认值及输入类型 | 介绍 |
---|---|---|
n_clusters | 默认值:8 输入:整型 |
聚类的数量 |
max_iter | 默认值:300 输入:整型 |
执行一次k-means算法所进行的最大迭代数 |
n_init | 默认值:10 输入:整型 |
用不同的聚类中心初始化值运行算法的次数,最终解是在inertia意义下选出的最优结果 |
init | 默认值:k-means++ 输入:k-means++、random、传递一个ndarray向量 |
此参数指定初始化方法: 1、k-means++用一种特殊的方法选定初始质心从而能加速迭代过程的收敛 (1)从输入的数据点集合(要求有k个聚类)中随机选择一个点作为第一个聚类中心; (2)对于数据集中的每一个点x,计算它与最近聚类中心(指已选择的聚类中心)的距离D(x); (3)选择一个新的数据点作为新的聚类中心,选择的原则是:D(x)较大的点,被选取作为聚类中心的概率较大; (4)重复2和3直到k个聚类中心被选出来 2、random随机从训练数据中选取初始质心 3、如果传递的是一个ndarray,则应该形如 (n_clusters, n_features) 并给出初始质心 |
precompute_distances | 默认值:auto 输入:auto、True 或者 False |
是否需要提前计算距离,计算速度更快但占用更多内存: (1)auto:如果 样本数乘以聚类数大于 12million 的话则不预计算距离 (2)True:总是预先计算距离 (3)False:永远不预先计算距离 |
tol | 默认值:1e-4 输入:float |
与inertia结合来确定收敛条件 |
n_jobs | 输入:整型 | 指定计算所用的进程数。内部原理是同时进行n_init指定次数的计算: (1)若值为 -1,则用所有的CPU进行运算。若值为1,则不进行并行运算 (2)若值小于-1,则用到的CPU数为(n_cpus + 1 + n_jobs)。因此如果 n_jobs值为-2,则用到的CPU数为总CPU数减1 |
copy_x | 默认值:True 输入:bool型 |
当我们precomputing distances时,将数据中心化会得到更准确的结果。如果把此参数值设为True,则原始数据不会被改变。如果是False,则会直接在原始数据上做修改并在函数返回值时将其还原。但是在计算过程中由于有对数据均值的加减运算,所以数据返回后,原始数据和计算前可能会有细小差别 |
algorithm | 默认值:Auto 输入:auto、full和elkan |
algorithm: 优化算法的选择,有auto、full和elkan三种选择: (1)full就是一般意义上的K-Means算法 (2)elkan是使用的elkan K-Means算法 (3)auto则会根据数据值是否是稀疏的(稀疏一般指是有大量缺失值),来决定如何选择full和elkan。如果数据是稠密的,就选择elkan K-means,否则就使用普通的Kmeans算法 |
max_iter | 默认值:300 输入:整型 |
最大迭代数 |
random_state | 输入:整型或 numpy.RandomState 类型 | 用于初始化质心的生成器(generator)。如果值为一个整数,则确定一个seed。此参数默认值为numpy的随机数生成器 |
max_iter | 默认值:0 | 是否输出详细信息 |