K-means算法聚类个数k应该如何的选择,目前常用有肘部法则和轮廓系数法等。肘部法则通过寻找损失值下降平稳的拐点来确定k值,而轮廓系统则是通过寻找轮廓系数的最大值来进行计算:
数据如下,是杭州一号线地铁站的三维向量:
应用kmeans,分别通过肘部法则和轮廓系数选择相应的k值
from sklearn.cluster import KMeans
import numpy as np
import matplotlib.pyplot as plt
from scipy.spatial.distance import cdist
from sklearn.metrics import silhouette_score
import xlrd
import mpl_toolkits.mplot3d.axes3d as p3
from sklearn.cluster import SpectralClustering
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
#读入数据
wb=xlrd.open_workbook('谱聚类数据.xls')
s=np.array([[wb.sheets()[0].cell_value(rowx=i+1, colx=j+1) for j in range(3)] for i in range(28)])
K=range(2,16)
#应用肘部法则确定 kmeans方法中的k
sse_result=[]
for k in K:
kmeans=KMeans(n_clusters=k)
kmeans.fit(s)
sse_result.append(sum(np.min(cdist(s,kmeans.cluster_centers_,'euclidean'),axis=1))/s.shape[0])
plt.plot(K,sse_result,'gx-')
plt.xlabel('k')
plt.ylabel(u'平均畸变程度')
plt.title(u'肘部法则确定最佳的K值')
plt.show()
#应用轮廓系数确定k
score=[]
for k in K:
kmeans=KMeans(n_clusters=k)
kmeans.fit(s)
score.append(silhouette_score(s,kmeans.labels_,metric='euclidean'))
plt.plot(K,score,'r*-')
plt.xlabel('k')
plt.ylabel(u'轮廓系数')
plt.title(u'轮廓系数确定最佳的K值')
plt.show()
#聚类成4个类
y_pred = SpectralClustering(n_clusters=4, gamma=0.1).fit_predict(s)
fig = plt.figure()
ax = p3.Axes3D(fig)
ax.view_init(7, -80)
for l in np.unique(y_pred):
ax.scatter(s[y_pred == l, 0], s[y_pred == l, 1], s[y_pred == l, 2],color=plt.cm.jet(float(l) / np.max(y_pred + 1)),s=20, edgecolor='k')
plt.title('谱聚类')
plt.show()
结果如下
以上做法参考了
https://zhuanlan.zhihu.com/p/98918878
http://www.bubuko.com/infodetail-2293604.html
说完了这些,我来谈点趣事,如图
事情的起因是2021年1月,有位同学找我组队新苗
然后我就把我的个人信息和获奖情况给了她,这是申报表
然后她组建了一个新苗群(现已被她解散,我已无法获得聊天记录,我现在只有和她私聊的记录),不过我加了一个她请的另一个队友可以证明这个群
我们就在这个群里聊天,我通过查找,找到了原始数据来源网站,不过这个地铁族网站现已经挂了
我帮她办的第一件事:
不过这个指标在她发表论文中并未用到,她只用了5个指标,应该是被她抛弃了
我选了3
当时随便写的代码哈
//输入
//临平站 南苑站 余杭高铁站站 翁梅站 乔司站 乔司南站 客运中心站 九堡站 九和路站 七堡站 彭埠站 火车东站站 闸弄口站 打铁关站 西湖文化广场站 武林广场站 凤起路站 龙翔桥站 定安路站 城站站 婺江路站 近江站 江陵路站 滨和路站 西兴站 滨康路站 湘湖站 下沙西站 金沙湖站 高沙路站 文泽路站 文海南路站 云水站 下沙江滨站 R 19.7 17.2 1.3 35.2 32.9 3.0 18.4 32.0 35.4 20.5 35.3 2.9 40.5 19.6 33.6 17.6 31.7 10.1 28.2 11.1 31.9 29.9 11.6 39.8 40.4 33.2 20.4 5.2 25.7 26.8 16.4 0.9 24.8 37.1 23.2 AB 30.8 19.8 2.5 6.1 14.0 0.0 5.0 7.7 7.9 4.5 12.3 3.2 9.5 7.7 29.7 24.6 26.1 39.2 31.7 30.0 9.7 19.2 37.5 5.3 8.4 12.4 6.5 7.7 13.4 19.7 5.2 1.0 4.7 3.3 13.7 A3 4.6 6.7 0.2 0.4 0.0 0.0 1.6 0.0 0.0 0.8 1.2 0.0 5.4 1.8 1.8 2.0 8.7 2.4 6.7 2.3 4.0 3.7 1.2 6.0 0.0 1.8 0.0 0.0 0.0 7.4 38.5 49.5 27.6 2.6 5.5 M 0.7 5.4 1.0 11.1 4.3 8.1 0.0 11.4 4.3 0.0 6.3 0.0 0.0 8.7 0.0 0.0 0.0 0.0 0.2 0.0 0.6 0.0 0.0 0.0 2.9 6.8 0.0 2.8 0.0 5.2 0.0 4.3 3.7 14.3 3.0 W 0.0 0.0 0.0 0.0 0.0 15.6 2.1 3.6 2.4 0.0 0.0 0.0 0.0 2.1 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 11.3 0.0 0.0 0.0 0.0 0.0 0.0 1.1 S 15.4 10.8 31.8 9.6 11.3 5.9 29.2 4.7 9.9 6.7 8.3 55.0 10.7 18.1 7.2 13.4 10.8 13.0 10.4 23.7 11.3 9.0 10.9 8.4 8.1 9.4 8.9 5.1 7.8 7.3 8.8 8.8 10.0 7.6 12.6 U 0.2 0.0 0.0 0.0 0.0 3.3 0.0 0.1 0.0 0.0 0.0 0.0 0.3 0.0 0.0 0.8 0.2 0.0 0.0 0.2 0.2 0.0 0.0 0.0 1.8 1.8 4.2 0.0 0.0 0.0 3.0 0.0 0.7 0.0 0.5 G 4.5 7.8 11.4 4.6 5.6 1.7 8.2 6.6 9.7 0.3 3.5 7.2 7.5 9.4 4.8 7.9 1.0 4.6 0.8 7.6 5.8 7.8 7.1 1.7 2.0 6.8 7.3 16.4 3.6 1.9 4.8 11.9 3.3 8.1 6.0 E 0.0 9.7 27.6 10.1 10.4 40.7 13.8 10.9 6.9 45.4 10.1 10.2 1.2 8.2 0.0 4.5 0.0 0.0 0.0 0.0 13.1 6.5 6.5 13.7 10.4 5.4 27.5 20.1 21.2 9.3 0.0 0.0 1.6 2.9 10.2
#include<bits/stdc++.h>
#define rep(i,x,y) for(auto i=(x);i<=(y);++i)
using namespace std;
double a[40][10],ans[40];
string s[10],ss[40];
int main(){
rep(i,1,34) cin>>ss[i];
rep(j,1,9){
cin>>s[j];
rep(i,1,35)
cin>>a[i][j];
}
rep(i,1,35) rep(j,1,9) a[i][0]+=a[i][j];
rep(i,1,35) rep(j,1,9) a[i][j]/=a[i][0];
rep(i,1,35){
double p=0;
rep(j,1,1)
p+=a[i][j];
if(p==0) ans[i]+=0;
else ans[i]-=p*log(p);
}
rep(i,1,35){
double p=0;
rep(j,2,3)
p+=a[i][j];
if(p==0) ans[i]+=0;
else ans[i]-=p*log(p);
}
rep(i,1,35){
double p=0;
rep(j,4,5)
p+=a[i][j];
if(p==0) ans[i]+=0;
else ans[i]-=p*log(p);
}
rep(i,1,35){
double p=0;
rep(j,6,8)
p+=a[i][j];
if(p==0) ans[i]+=0;
else ans[i]-=p*log(p);
}
rep(i,1,35){
double p=0;
rep(j,9,9)
p+=a[i][j];
if(p==0) ans[i]+=0;
else ans[i]-=p*log(p);
}
rep(i,1,35) ans[i]/=log(5);
rep(i,1,34) cout<<ss[i],printf("%20.3f\n",ans[i]);
}
//输出
//临平站 0.684
//南苑站 0.926
//余杭高铁站站 0.580
//翁梅站 0.884
//乔司站 0.888
//乔司南站 0.684
//客运中心站 0.811
//九堡站 0.915
//九和路站 0.851
//七堡站 0.662
//彭埠站 0.883
//火车东站站 0.436
//闸弄口站 0.662
//打铁关站 0.930
//西湖文化广场站 0.632
//武林广场站 0.778
//凤起路站 0.630
//龙翔桥站 0.581
//定安路站 0.628
//城站站 0.628
//婺江路站 0.838
//近江站 0.790
//江陵路站 0.736
//滨和路站 0.747
//西兴站 0.792
//滨康路站 0.877
//湘湖站 0.801
//下沙西站 0.925
//金沙湖站 0.829
//高沙路站 0.884
//文泽路站 0.610
//文海南路站 0.523
//云水站 0.788
//下沙江滨站 0.816
我帮她办的第二件事:
这事很小,不过也能发
我帮她办的第三件事:
最重要的就是上面的谱聚类分析,确认k值
一模一样是吧
总结
我看了她那篇文章,总结来说就是主成分分析法+谱聚类,我的贡献就是上面的部分,后面我并未直接参与文章的文字编写,但这就是她说的我没有贡献,后面直接背着我把文章发了。我人微言轻,如果我同学或老师能有解决办法,请联系我,我将不胜感激。最后,我希望那位同学向我道歉。