找回密码
 会员注册
查看: 28|回复: 0

Python实现K-means聚类——多维数据聚类散点图绘制

[复制链接]

10

主题

0

回帖

31

积分

新手上路

积分
31
发表于 2024-9-7 15:22:57 | 显示全部楼层 |阅读模式
文章目录吐槽正题本文背景文章目的K-means聚类步骤:K-means分类Python代码上述代码结果可视化展示不入流的小期待吐槽客观吐槽:CSDN的富文本编辑器真是超级无敌难用。首先要吐槽一下CSDN的富文本编辑器,好难用,好难用,好难用,好难用好难用,好难用,好难用,好难用!!!!!!!!!!!!!!!!!!前边的开头文字编辑了三四次,每次都是不小心按了ctrl+z,就完全消失了。正题本文背景因需要想对某多维数据利用K-means聚类,并绘制散点图。几番查询发现,网上现有中文K-means介绍大多基于二维变量,在绘制散点图时直接以变量作为横纵最标轴即可,甚少有关于多维变量散点图的绘制说明。我涉算法不深,绘制该多维数据散点图颇费了些时间,特此记录,同时分享与大家,望能对同是入门小白的同学们有所帮助。文章目的利用Python自带包解决K-means多维数据聚类散点图绘制问题。K-means聚类步骤:数据导入数据标准化变量相关性检验K值的确定1)手肘图或轮廓系数法。手肘图有基于平均离差法的,有基于SSE的,也有说可以直接从主成分/因子分析的碎石图判断的,我觉得几种方法本质上没啥区别,都以最明显拐点处的K值为准。2)轮廓系数图通常以轮廓系数最大时的K值为准。3)可以两者结合确定最佳的K。聚类算法,确定数据的类别标签、聚类中心绘制散点图1)若数据本身是二维的,直接以二维变量构建直角坐标系,为每类数据分配不同的颜色,绘制散点图即可;2)若数据是多维的,绘制散点图之前需先将数据降维,平面图降为二维直角坐标系,立体图降为三维坐标系,并将聚类中心一并降维;将降维后的数据、聚类中心按照类别分配不同颜色,绘制在一张图中。K-means分类Python代码K-means多维数据聚类上述所有流程如下,需求匹配度一致的同学可自取直用。(期待:代码小白,不知道是否我的代码有问题,如果一次性直接运行,耗运行速度很慢,相当耗费时间。如果有大佬路过稍作指点,将不胜感激。)(Tips:耗时最直接的解决办法,一个步骤一个步骤的运行,后续所有的步骤都基于标准化后的数据df_normalized_data数据集,且互相之间没有特别的相互影响,可运行完一步,注销掉相关代码,再运行下一步。)importpandasaspdimportnumpyasnpimportmatplotlib.pyplotaspltimportseabornassnsfromsklearn.clusterimportKMeansfromscipy.spatial.distanceimportcdistfrompandasimportDataFramefromsklearnimportmetricsfromsklearn.decompositionimportPCA#导入数据,默认第一行为索引,index_col设定第一列也为索引df_raw=pd.read_excel('data_SD_2.xlsx',sheet_name=0,index_col=0)#数据0-1标准化df_normalized_data=df_raw.apply(lambdaxx-np.min(x))/(np.max(x)-np.min(x)))#print(df_normalized_data)#利用皮尔逊相关系数查看多重共线性及可视化df_corr=df_normalized_data.corr()fig,ax=plt.subplots(figsize=(15,10))sns.heatmap(data=df_corr,annot=True,fmt='.2f',annot_kws={'size':7},cmap='Greens')#若不喜欢绿色,可以通过cmap更改颜色cax=plt.gcf().axes[-1]cax.tick_params(labelsize=7)plt.title('皮尔逊相关系数矩阵',fontsize=7)plt.xticks(fontsize=7)plt.yticks(fontsize=7)plt.show()#-----------------判断可以聚为几类:手肘图、轮廓系数法--------------------#手肘图法1——基于平均离差K=range(1,18)meanDispersions=[]forkinK:kemans=KMeans(n_clusters=k,init='k-means++')kemans.fit(df_normalized_data)#计算平均离差m_Disp=sum(np.min(cdist(df_normalized_data,kemans.cluster_centers_,'euclidean'),axis=1))/df_normalized_data.shape[0]meanDispersions.append(m_Disp)plt.rcParams['font.family']=['sans-serif']plt.rcParams['font.sans-serif']=['SimHei']#使折线图显示中文plt.plot(K,meanDispersions,'bx-')plt.xlabel('k')plt.ylabel('平均离差')plt.title('')plt.show()#手肘图法2——基于SSEdistortions=[]#用来存放设置不同簇数时的SSE值foriinrange(1,15):kmModel=KMeans(n_clusters=i)kmModel.fit(df_normalized_data)distortions.append(kmModel.inertia_)#获取K-means算法的SSE#绘制曲线plt.plot(range(1,15),distortions,marker="o")plt.rcParams['font.sans-serif']=['SimHei']plt.rcParams['axes.unicode_minus']=Falseplt.xlabel("簇数量")plt.ylabel("簇内误差平方和(SSE)")plt.show()#轮廓系数法K=range(2,10)#构建空列表,用于存储个中簇数下的轮廓系数S=[]forkinK:kmeans=KMeans(n_clusters=k)kmeans.fit(df_normalized_data)labels=kmeans.labels_#调用字模块metrics中的silhouette_score函数,计算轮廓系数S.append(metrics.silhouette_score(df_normalized_data,labels,metric='euclidean'))#中文和负号的正常显示plt.rcParams['font.sans-serif']=['MicrosoftYaHei']plt.rcParams['axes.unicode_minus']=False#设置绘图风格plt.style.use('ggplot')#绘制K的个数与轮廓系数的关系plt.plot(K,S,'b*-')plt.xlabel('簇的个数')plt.ylabel('轮廓系数')#显示图形plt.show()#-----------------开始K-means聚类的一系列过程---------------------#K-means聚类kms=KMeans(n_clusters=5,init='k-means++')data_fig=kms.fit(df_normalized_data)#模型拟合centers=kms.cluster_centers_#计算聚类中心labs=kms.labels_#为数据打标签df_labels=DataFrame(kms.labels_)#将标签存放为DataFramedf_labels.to_excel('datalabels.xlsx')#输出数据标签,其实输出可有可无#将聚类结果为0,1,2,3,4的数据筛选出来并打上标签df_A_0=df_normalized_data[kms.labels_==0]df_A_1=df_normalized_data[kms.labels_==1]df_A_2=df_normalized_data[kms.labels_==2]df_A_3=df_normalized_data[kms.labels_==3]df_A_4=df_normalized_data[kms.labels_==4]m=np.shape(df_A_0)[1]df_A_0.insert(df_A_0.shape[1],'label',0)#打标签df_A_1.insert(df_A_1.shape[1],'label',1)df_A_2.insert(df_A_2.shape[1],'label',2)df_A_3.insert(df_A_3.shape[1],'label',3)df_A_4.insert(df_A_4.shape[1],'label',4)df_labels_data=pd.concat([df_A_0,df_A_1,df_A_2,df_A_3,df_A_4])#数据融合df_labels_data.to_excel('data_labeled.xlsx')#输出带有标签的数据#输出最终聚类中心df_centers=DataFrame(centers)df_centers.to_excel('data_final_center.xlsx')#--------------------到这里K-means聚类的流程算是结束了------------------------#------------------------下面介绍如何绘制聚类散点图-----------------------------#对二分类的散点图绘制,网上教程很多,此篇文章主要介绍多分类的散点图绘制问题#首先,对原数据进行PCA降维处理,获得散点图的横纵坐标轴数据pca=PCA(n_components=2)#提取两个主成分,作为坐标轴pca.fit(df_normalized_data)data_pca=pca.transform(df_normalized_data)data_pca=pd.DataFrame(data_pca,columns=['PC1','PC2'])data_pca.insert(data_pca.shape[1],'labels',labs)#centerspca对K-means的聚类中心降维,对应到散点图的二维坐标系中pca=PCA(n_components=2)pca.fit(centers)data_pca_centers=pca.transform(centers)data_pca_centers=pd.DataFrame(data_pca_centers,columns=['PC1','PC2'])#Visualizeit:plt.figure(figsize=(8,6))plt.scatter(data_pca.values[:,0],data_pca.values[:,1],s=3,c=data_pca.values[:,2],cmap='Accent')plt.scatter(data_pca_centers.values[:,0],data_pca_centers.values[:,1],marker='o',s=55,c='#8E00FF')plt.show()123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134上述代码结果可视化展示皮尔逊相关系数图:手肘图——基于平均离差:手肘图——基于SSE:分析:从两个手肘图来看,拐点并不明显。硬要选一个的话,K=3是最佳选择。结合下面轮廓系数图也是K=3。然而现实往往聚类的结果并不全部如所愿,因为根据现实情况理论上我的数据可以聚为5类(各种原因)。于是我是这样做的(科学性与否请大家自行判断,也特别期待大佬帮忙斧正):从轮廓系数图来看,K=3的确是最好的选择,然而K=4和K=5的轮廓系数并没有明显区别,且后续在K>5后,轮廓系数又出现了非常明显的断崖式下降;结合手肘图中K=3和K=5的无论是SSE还是平均离差都有不小的降幅,最终选定K=5。轮廓系数图:(原图不便展示,下图来源于网络中趋势最接近的图片)散点图绘制:(原图不便展示,下图来源于网络中趋势最接近的图片)分析:多维数据的聚类散点图绘制,是需要将原始数据降维到二维或三维坐标系中的,降维方法本文选取的主成分方法,但其他方法同样可以使用。希望所踩过的坑能发挥一些余热.~_~.不入流的小期待最后,非常不好意思推荐一下我的佛系小团子,希望看完文章有所收获的朋友们能动动小手帮我加个人气.~_~.生活是生活,学习是学习,工作是工作,分享是分享。希望大家都学业顺利,生活快乐!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2025-1-11 05:41 , Processed in 0.459795 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表