K均值算法详解及实现

算法原理

  1. 随机选取k个点作为初始聚类中心
  2. 计算各个数据点到初始聚类中心的距离,比较其距离将每个数据点归类到最近的聚类中心
  3. 样本全部划分后重新计算k个类的聚类中心
  4. 重复1~3的步骤,直至这k个聚类中心不再改变(收敛)

对数据的要求

  1. 对于 缺失值需要处理(填充或者删除)
  2. 分类变量需要编码(涉及距离计算)
  3. 数据需要标准化或者归一化处理(消除量纲的影响。涉及距离计算的算法都需要考虑)

算法的优缺点

一、优点

  1. 原理简单,容易实现
  2. 对于大数据集,可保持伸缩性与高效性
  3. 当簇接近高斯分布时,算法的效果较好

一、缺点

  1. k值难以确定
  2. 对于噪声与孤立数据(异常点)敏感
  3. 随机初始值的选取对结果影响很大
  4. 结果不一定是全局最优,只能保证局部最优(与初始点的选取有着很大的关系)

算法需要注意的点

1. 初始点的选择对KNN算法最后的结果有什么影响?
不合理的初始点的选取会导致长时间无法收敛且得到局部最优

2. 每个类别的中心初始点如何选择?
①随机法②选择各批次距离近可能的k个点③选择层次聚类或者Canopy处理

3. k值怎么确定?
①比较类内距离,类间距离确定k(平均轮廓系数(大)或类内距离/类间距离(小))
轮廓系数: s ( i ) = ( a ( i ) b ( i ) ) m a x ( a ( i ) , b ( i ) ) [ 1 , 1 ] s_{(i)} = \frac{(a_{(i)}-b_{(i)})}{max(a_{(i)},b_{(i)})}\in[-1,1]
注:该值越大聚类效果越好。其中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 是否输出详细信息

猜你喜欢

转载自blog.csdn.net/weixin_41851055/article/details/106101928