聚类算法K-means
认识聚类算法
使⽤不同的聚类准则,产⽣的聚类结果不同。
1.1 聚类算法在现实中的应⽤
⽤户画像,⼴告推荐,Data Segmentation,搜索引擎的流量推荐,恶意流量识别
基于位置信息的商业推送,新闻聚类,筛选排序
图像分割,降维,识别;离群点检测;信⽤卡异常消费;发掘相同功能的基因⽚段
1.2 聚类算法的概念
聚类算法:
⼀种典型的⽆监督学习算法,主要⽤于将相似的样本⾃动归到⼀个类别中。
在聚类算法中根据样本之间的相似性,将样本划分到不同的类别中,对于不同的相似度计算⽅法,会得到不同的聚类结果,常⽤的相似度计算⽅法有欧式距离法。
1.3 聚类算法与分类算法最⼤的区别
聚类算法是无监督的学习算法,⽽分类算法属于监督的学习算法。
聚类算法原理
k-means其实包含两层内容:
- K : 初始中⼼点个数(计划聚类数)
- means:求中⼼点到其他数据点距离的平均值
1 k-means聚类步骤
- 1、随机设置K个特征空间内的点作为初始的聚类中⼼
- 2、对于其他每个点计算到K个中⼼的距离,未知的点选择最近的⼀个聚类中⼼点作为标记类别
- 3、接着对着标记的聚类中⼼之后,重新计算出每个聚类的新中⼼点(平均值)
- 4、如果计算得出的新中⼼点与原中⼼点⼀样(质⼼不再移动),那么结束,否则重新进⾏第⼆步过程
通过下图解释实现流程:
案例理解
1、随机设置K个特征空间内的点作为初始的聚类中⼼(本案例中设置p1和p2
2、对于其他每个点计算到K个中⼼的距离,未知的点选择最近的⼀个聚类中⼼点作为标记类别
3、接着对着标记的聚类中⼼之后,重新计算出每个聚类的新中⼼点(平均值)
4、如果计算得出的新中⼼点与原中⼼点⼀样(质⼼不再移动),那么结束,否则重新进⾏第⼆步过程【经过判断,需要重复上述步骤,开始新⼀轮迭代】
5、当每次迭代结果不变时,认为算法收敛,聚类完成,K-Means⼀定会停下,不可能陷⼊⼀直选质⼼的过程。(一般会设置一个阈值,当每次迭代结果小于这个阈值的时候就认为结果不变了)
K-means聚类实现流程【掌握】
- 事先确定常数K,常数K意味着最终的聚类类别数
- 随机选定初始点为质⼼,并通过计算每⼀个样本与质⼼之间的相似度(这⾥为欧式距离),将样本点归到最相似的类中
- 接着,重新计算每个类的质⼼(即为类中⼼),重复这样的过程,直到质⼼不再改变
- 最终就确定了每个样本所属的类别以及每个类的质⼼
- 注意:
- 由于每次都要计算所有的样本与每⼀个质⼼之间的相似度,故在⼤规模的数据集上,K-Means算法的收敛速度⽐较慢
api初步使用
1 api介绍
sklearn.cluster.KMeans(n_clusters=8)
- 参数:
- n_clusters:开始的聚类中⼼数量
- 整型,缺省值=8,⽣成的聚类数,即产⽣的质⼼(centroids)数。
- n_clusters:开始的聚类中⼼数量
- ⽅法:
- estimator.fit(x)
- estimator.predict(x)
- estimator.fit_predict(x)
- 计算聚类中⼼并预测每个样本属于哪个类别,相当于先调⽤fit(x),然后再调⽤predict(x)
2 案例
随机创建不同⼆维数据集作为训练集,并结合k-means算法将其聚类,你可以尝试分别聚类不同数量的簇,并观察聚类效果:
聚类参数n_cluster传值不同,得到的聚类结果不同
2.1流程分析
2.2 代码实现
1.创建数据集
# X为样本特征,Y为样本簇类别, 共1000个样本,每个样本2个特征,共4个簇,
# 簇中⼼在[-1,-1], [0,0],[1,1], [2,2], 簇⽅差分别为[0.4, 0.2, 0.2, 0.2]
x,y=make_blobs(n_samples=1000,n_features=2,centers=[[-1,-1], [0,0],[1,1], [2,2]],cluster_std=[0.4, 0.2, 0.2, 0.2],random_state=66)
# 数据集可视化
plt.scatter(x[:,0],x[:,1],c=y)
plt.show()
2.使⽤k-means进⾏聚类,并使⽤CH⽅法评估(CH评估详见下文模型评估)
分成2类时:
ypre=KMeans(n_clusters=2,random_state=88).fit_predict(x)
plt.scatter(x[:,0],x[:,1],c=ypre)
plt.show()
#使用CH评估模型聚类分数
print("模型聚类得分:",calinski_harabasz_score(x,ypre))#模型聚类得分: 3087.3448842719868
分成3类时:
模型聚类得分: 2933.1636078543297
分成4类时:
模型聚类得分: 6060.979415031163
模型评估
学习⽬标
知道模型评估中的SSE、“肘”部法、SC系数和CH系数的实现原理
1 误差平方和(SSE \The sum of squares due to error):
举例:(下图中数据-0.2, 0.4, -0.8, 1.3, -0.7, 均为真实值和预测值的差
在k-means中的应⽤:
公式各部分内容:
上图中: k=2
SSE图最终的结果,对图松散度的衡量.(eg: SSE(左图)<SSE(右图))
SSE随着聚类迭代,其值会越来越⼩,直到最后趋于稳定:
如果质⼼的初始值选择不好,SSE只会达到⼀个不怎么好的局部最优解.
2 “肘”方法 (Elbow method) — 用来确定K值(分成几类最好?)
(1)对于n个点的数据集,迭代计算k from 1 to n,每次聚类完成后计算每个点到其所属的簇中⼼的距离的平⽅和;
(2)平⽅和是会逐渐变⼩的,直到k==n时平⽅和为0,因为每个点都是它所在的簇中⼼本身。
(3)在这个平⽅和变化过程中,会出现⼀个拐点也即“肘”点,下降率突然变缓时即认为是最佳的k值。
在决定什么时候停⽌训练时,肘形判据同样有效,数据通常有更多的噪⾳,在增加分类⽆法带来更多回报时,我们停止增加类别。
3 轮廓系数法(Silhouette Coefficient)
结合了聚类的凝聚度(Cohesion)和分离度(Separation),⽤于评估聚类的效果:
⽬的:
内部距离最⼩化,外部距离最⼤化
计算样本i到同簇其他样本的平均距离ai,ai 越⼩样本i的簇内不相似度越⼩,说明样本i越应该被聚类到该簇。
计算样本i到最近簇Cj 的所有样本的平均距离bij,称样本i与最近簇Cj 的不相似度,定义为样本i的簇间不相似度:bi=min{bi1, bi2, ..., bik},bi越⼤,说明样本i越不属于其他簇。
求出所有样本的轮廓系数后再求平均值就得到了平均轮廓系数。
平均轮廓系数的取值范围为[-1,1],系数越⼤,聚类效果越好:簇内样本的距离越近,簇间样本距离越远。
案例:
下图是500个样本含有2个feature的数据分布情况,我们对它进⾏SC系数效果衡量:
n_clusters = 2 The average silhouette_score is : 0.7049787496083262
n_clusters = 3 The average silhouette_score is : 0.5882004012129721
n_clusters = 4 The average silhouette_score is : 0.6505186632729437
n_clusters = 5 The average silhouette_score is : 0.56376469026194
n_clusters = 6 The average silhouette_score is : 0.4504666294372765
n_clusters 分别为 2,3,4,5,6时,SC系数如下,是介于[-1,1]之间的度量指标:
每次聚类后,每个样本都会得到⼀个轮廓系数,当它为1时,说明这个点与周围簇距离较远,结果⾮常好,当它为0,说明这个点可能处在两个簇的边界上,当值为负时,暗含该点可能被误分了。
从平均SC系数结果来看,K取3,5,6是不好的,那么2和4呢?k取2时的silhouette_score is : 0.7049787496083262,k取4时的silhouette_score is : 0.6505186632729437,是不是2比4好呢?
k=2的情况:
k=4的情况:
n_clusters = 2时,第0簇的宽度远宽于第1簇;
n_clusters = 4时,所聚的簇宽度相差不⼤,因此选择K=4,作为最终聚类个数。
4 CH系数(Calinski-Harabasz Index)(方差比标准)
Calinski-Harabasz:
类别内部数据的协⽅差越⼩越好,类别之间的协⽅差越⼤越好(换句话说:类别内部数据的距离平⽅和越⼩越好,类别之间的距离平⽅和越⼤越好),这样的Calinski-Harabasz分数s会⾼,分数s⾼则聚类效果越好。
通过量化簇间离散度与簇内离散度的比率来衡量聚类质量。
m为训练集样本数,k为类别数。
B 为类别之间的协⽅差矩阵,W 为类别内部数据的协⽅差矩阵;
协方差(Covariance)是统计学中用来衡量两个随机变量之间线性关系强度和方向的重要指标。它描述了两个随机变量之间的变化趋势是否一致,以及它们之间的线性相关性强度。
定义和公式
协方差的数学定义为:
tr为矩阵的迹(矩阵对角线之和:a11+a22+...ann)
使⽤矩阵的迹进⾏求解的理解:
矩阵的对⻆线可以表示⼀个物体的相似性
在机器学习⾥,主要为了获取数据的特征值,那么就是说,在任何⼀个矩阵计算出来之后,都可以简单化,只要获取矩阵的迹,就可以表示这⼀块数据的最重要的特征了,这样就可以把很多⽆关紧要的数据删除掉,达到简化数据,提⾼处理速度。
CH需要达到的⽬的:
⽤尽量少的类别聚类尽量多的样本,同时获得较好的聚类效果。
算法优化
k-means算法⼩结
优点:
1.原理简单(靠近中⼼点),实现容易
2.聚类效果中上(依赖K的选择)
3.空间复杂度o(N),时间复杂度o(IKN)
N为样本点个数,K为中⼼点个数,I为迭代次数
缺点:
1.对离群点,噪声敏感 (中⼼点易偏移)
2.很难发现⼤⼩差别很⼤的簇及进⾏增量计算
3.结果不⼀定是全局最优,只能保证局部最优(与K的个数及初值选取有关)
1 Canopy算法配合初始聚类
解决选择最初质心时选到较近的几个点的问题。
原理解释:
1.首先选择一个点,并以该点为圆心,T1为半径,绘制一个圆,然后以改点为圆心T2为半径再次绘制圆,
2.选择T2为半径的圆之外的点为圆心,以T1,T2为半径绘制圆,然后再以两个以T2为半径的圆之外的点做为圆心绘制圆,,,直到所有的点都被包含到圆形里面停止。
3.此时所有的圆心,都可以作为质心。
1.2 Canopy算法的优缺点
优点:
1.Kmeans对噪声抗⼲扰较弱,通过Canopy对⽐,将较⼩的NumPoint的Cluster直接去掉有利于抗⼲扰。
2.Canopy选择出来的每个Canopy的centerPoint作为K会更精确。
3.只是针对每个Canopy的内做Kmeans聚类,减少相似计算的数量。
缺点:
1.算法中 T1、T2的确定问题 ,如果T1、T2选择不合理,依旧可能落⼊局部最优解
2 K-means++
kmeans++⽬的,让选择的质⼼尽可能的分散。
其中:
D(x)是第一个质心到其他所有点的距离。
那么下一个质心的选择,就是P值最大的点作为质心,即距离当前质心最远的点作为下一个质心。
为⽅便后⾯表示,把其记为A:
如下图中,如果第⼀个质⼼选择在圆⼼,那么最优可能选择到的下⼀个点在P(A)这个区域(根据颜⾊进⾏划分)
3 ⼆分k-means
实现流程:
1.所有点作为⼀个簇
2.将该簇⼀分为⼆
3.选择能最⼤限度降低聚类代价函数(也就是误差平⽅和)的簇划分为两个簇。
4.以此进⾏下去,直到簇的数⽬等于⽤户给定的数⽬k为⽌。
隐含的⼀个原则
因为聚类的误差平⽅和能够衡量聚类性能,该值越⼩表示数据点越接近于他们的质⼼,聚类效果就越好。所以需要对误差平⽅和最⼤的簇进⾏再⼀次划分,因为误差平⽅和越⼤,表示该簇聚类效果越不好,越有可能是多个簇被当成了⼀个簇,所以我们⾸先需要对这个簇进⾏划分。
⼆分K均值算法可以加速K-means算法的执⾏速度,因为它的相似度计算少了并且不受初始化问题的影响,因为这⾥不存在随机点的选取,且每⼀步都保证了误差最⼩。
4 k-medoids(k-中⼼聚类算法)
K-medoids是对K-means的一种改进,不⼀样的地⽅在于中⼼点的选取
- K-means中,将中⼼点取为当前cluster中所有数据点的平均值,对异常点很敏感!
- K-medoids中,将从当前cluster 中选取到其他所有(当前cluster中的)点的距离之和最⼩的点作为中⼼点。
算法流程:
( 1 )总体n个样本点中任意选取k个点作为medoids
( 2 )按照与medoids最近的原则,将剩余的n-k个点分配到当前最佳的medoids代表的类中
( 3 )对于第i个类中除对应medoids点外的所有其他点,按顺序计算当其为新的medoids时,代价函数的值,遍历所有可能,选取代价函数最⼩时对应的点作为新的medoids
( 4 )重复2-3的过程,直到所有的medoids点不再发⽣变化或已达到设定的最⼤迭代次数
( 5 )产出最终确定的k个类
k-medoids对噪声鲁棒性好。
例:当⼀个cluster样本点只有少数⼏个,如(1,1)(1,2)(2,1)(1000,1000)。其中(1000,1000)是噪声。如果按照k-means质⼼⼤致会处在(1,1)(1000,1000)中间,这显然不是我们想要的。这时k-medoids就可以避免这种情况,他会在(1,1)(1,2)(2,1)(1000,1000)中选出⼀个样本点使cluster的绝对误差最⼩,计算可知⼀定会在前三个点中选取。
k-medoids只能对⼩样本起作⽤,样本⼤,速度就太慢了,当样本多的时候,少数⼏个噪⾳对k-means的质⼼影响也没有想象中的那么重,所以k-means的应⽤明显⽐k-medoids多。
5 Kernel k-means(了解)
kernel k-means实际上,就是将每个样本进⾏⼀个投射到⾼维空间的处理,然后再将处理后的数据使⽤普通的k-means算法思想进⾏聚类。
6 ISODATA(了解)
类别数⽬随着聚类过程⽽变化;
对类别数会进⾏合并,分裂,
“合并”:(当聚类结果某⼀类中样本数太少,或两个类间的距离太近时)
“分裂”:(当聚类结果中某⼀类的类内⽅差太⼤,将该类进⾏分裂)
7 Mini Batch K-Means(了解)
适合⼤数据的聚类算法
⼤数据量是什么量级?通常当样本量⼤于1万做聚类时,就需要考虑选⽤Mini Batch K-Means算法。
Mini Batch KMeans使⽤了Mini Batch(分批处理)的⽅法对数据点之间的距离进⾏计算。
Mini Batch计算过程中不必使⽤所有的数据样本,⽽是从不同类别的样本中抽取⼀部分样本来代表各⾃类型进⾏计算。
由于计算样本量少,所以会相应的减少运⾏时间,但另⼀⽅⾯抽样也必然会带来准确度的下降。
该算法的迭代步骤有两步:
(1)从数据集中随机抽取⼀些数据形成⼩批量,把他们分配给最近的质⼼
(2)更新质⼼
与Kmeans相⽐,数据的更新在每⼀个⼩的样本集上。对于每⼀个⼩批量,通过计算平均值得到更新质⼼,并把⼩批量⾥的数据分配给该质⼼,随着迭代次数的增加,这些质⼼的变化是逐渐减⼩的,直到质⼼稳定或者达到指定的迭代次数,停⽌计算。
总结
优化方法 | 思路 |
---|---|
Canopy+kmeans | Canopy 粗聚类配合 kmeans |
kmeans++ | 距离越远越容易成为新的质心 |
二分 k-means | 拆除 SSE 最大的簇 |
k-medoids | 和 kmeans 选取中心点的方式不同 |
kernel kmeans | 映射到高维空间 |
ISODATA | 动态聚类,可以更改 K 值大小 |
案例:探究⽤户对物品类别的喜好细分
学习⽬标
应⽤pca和K-means实现⽤户对物品类别的喜好细分划分
数据如下:
order_products__prior.csv:订单与商品信息
- 字段:order_id, product_id, add_to_cart_order, reordered
products.csv:商品信息
- 字段:product_id, product_name, aisle_id, department_id
orders.csv:⽤户的订单信息
- 字段:order_id,user_id,eval_set,order_number,….
aisles.csv:商品所属具体物品类别
- 字段: aisle_id, aisle
分析
- 1.获取数据
- 2.数据基本处理
- 2.1 合并表格
- 2.2 交叉表合并
- 2.3 数据截取
- 3.特征⼯程 — pca
- 4.机器学习(k-means)
- 5.模型评估(使用轮廓系数法)
- sklearn.metrics.silhouette_score(X, labels)
- 计算所有样本的平均轮廓系数
- X:特征值
- labels:被聚类标记的⽬标值
- sklearn.metrics.silhouette_score(X, labels)
3 完整代码
import pandas as pd
from sklearn.decomposition import PCA
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
- 1.获取数据
# 订单与商品信息
order_products=pd.read_csv(r"D:\learn\000人工智能数据大全\黑马数据\机器学习\探究⽤户对物品类别的喜好细分\order_products__prior.csv")
# 商品信息
products=pd.read_csv(r"D:\learn\000人工智能数据大全\黑马数据\机器学习\探究⽤户对物品类别的喜好细分\products.csv")
# ⽤户的订单信息
orders=pd.read_csv(r"D:\learn\000人工智能数据大全\黑马数据\机器学习\探究⽤户对物品类别的喜好细分\orders.csv")
# 商品所属具体物品类别
aisles=pd.read_csv(r"D:\learn\000人工智能数据大全\黑马数据\机器学习\探究⽤户对物品类别的喜好细分\aisles.csv")
- 2.数据基本处理
- 2.1 合并表格
table1=pd.merge(order_products,products,on='product_id')
table2=pd.merge(table1,orders,on='order_id')
table3=pd.merge(table2,aisles,on='aisle_id')
-
- 2.2 交叉表合并
cross_table=pd.crosstab(table3['user_id'],table3['aisle_id'])
print(cross_table.shape)#(206209, 134)
-
- 2.3 数据截取
new_data=cross_table[:10000]
- 3.特征⼯程 — pca
tranfromer=PCA(n_components=0.9)
pca_data=tranfromer.fit_transform(new_data)
print(pca_data.shape)#(10000, 26)
- 4.机器学习(k-means)
estimator=KMeans(n_clusters=2,random_state=66)
res=estimator.fit_predict(pca_data)
- 5.模型评估
score=silhouette_score(pca_data,res)
score#0.38823927772267264