1.scikit-learn库实现K-means算法
import pandas as pd from sklearn.cluster import KMeans import matplotlib.pyplot as plt "通过pandas导入相关数据" df = pd.read_csv(r'C:\Users\Administrator\Desktop\三年5000车\起点最多城市切分\8-删除异常运输链.csv',encoding="GB2312") x = df[['途径城市数量(不重复城市)','途经省份数量','里程','复杂度']] #选择聚类的指标 "超参数" k = 5 "训练模型" model = KMeans(n_clusters=k, #簇的个数,即你想聚成几类 init='k-means++', #初始簇中心的获取方法 n_init=10, #获取初始簇中心的更迭次数,为了弥补初始质心的影响,算法默认会初始10个质心,实现算法,然后返回最好的结果。 max_iter=300, #最大迭代次数(因为kmeans算法的实现需要迭代) tol=0.0001, # 容忍度,即kmeans运行准则收敛的条件 precompute_distances='auto', #是否需要提前计算距离,这个参数会在空间和时间之间做权衡,如果是True 会把整个距离矩阵都放到内存中,auto 会默认在数据样本大于featurs*samples 的数量大于12e6 的时候False,False 时核心实现的方法是利用Cpython 来实现的 verbose=0, # 冗长模式 random_state=None, #随机生成簇中心的状态条件。 copy_x=True, #对是否修改数据的一个标记,如果True,即复制了就不会修改数据。bool 在scikit-learn 很多接口中都会有这个参数的,就是是否对输入数据继续copy 操作,以便不修改用户的输入数据。 n_jobs=1, #并行设置 algorithm='auto' #kmeans的实现算法,有:’auto’, ‘full’, ‘elkan’, 其中 ‘full’表示用EM方式实现 ) km = model.fit(x) #进行聚类 df['聚类结果'] = km.labels_ #km.labels_ 获得聚类标签(数字形式) result = model.predict(x) #可以用来获得聚类标签,也可以用来预测新数据 centers = model.cluster_centers_ #获得簇的中心点坐标 "结果可视化(聚类指标少于等于三个指标时可用)" plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签 plt.rcParams['axes.unicode_minus']=False #用来正常显示负号 "三个聚类指标时" ax = plt.axes(projection='3d') #中心点颜色标记 mark4 = ['b','g','r','k'] mark5 = ['b','g','r','k','y',] mark6 = ['b','g','r','k','y','c'] mark7 = ['b','g','r','k','y','c','m'] #画出各个数据点,用不同颜色表示分类 for x,y,z,c in zip(df['载重'],df['总里程'],df['途经省份数量'],df['聚类结果']): ax.scatter3D(x,y,z,color = mark5[c]) #画出中心点,用不同颜色表示分类 for j, center in enumerate(centers): ax.scatter3D(center[0], center[1],center[2],color = mark5[j]) ax.set_xlabel('途径城市数量') ax.set_ylabel('途经省份数量') ax.set_zlabel('趟次里程') "两个聚类指标时" #画出中心点 for i, center in enumerate(centers): plt.scatter(center[0],center[1],color = mark5[i]) plt.xlabel('途经省份数量') plt.ylabel('总里程') plt.show()
2.聚类数量效果评估
(1)肘方法(拐点处为聚类效果最好的聚类数量)
import numpy as np from sklearn.cluster import KMeans import matplotlib.pyplot as plt import pandas as pd #读取数据 df = pd.read_csv(r"H:\数据处理结果\三年数据合并.csv",encoding="GB2312") X = df[['途径城市数量(不重复城市)','途经省份数量','里程','复杂度']] #X为DataFrame数据 X = np.array(X) #转换成numpy array,否则在 X[group,:] 处会报错,或者改成X[group] distance = [] k = [] #簇的数量 for n_clusters in range(1,10): cls = KMeans(n_clusters).fit(X) #曼哈顿距离 def manhattan_distance(x,y): return np.sum(abs(x-y)) distance_sum = 0 for i in range(n_clusters): group = cls.labels_ == i members = X[group,:] for v in members: distance_sum += manhattan_distance(np.array(v), cls.cluster_centers_[i]) distance.append(distance_sum) k.append(n_clusters) plt.scatter(k, distance) plt.plot(k, distance) plt.xlabel("k") plt.ylabel("distance") plt.show()
(2)轮廓系数(数值越高,聚类效果越好)
from sklearn.cluster import KMeans import pandas as pd from sklearn.metrics import silhouette_score import matplotlib.pyplot as plt df = pd.read_csv(r"D:\数据\货运数据\中心城市切分运输链\三年数据\5000辆车抽样\5000辆车抽样-1.csv",encoding="GB2312") X = df[['途径城市数量(不重复城市)','途经省份数量','里程','复杂度']] Scores = [] # 存放轮廓系数 for k in range(2,10): kmeans = KMeans(n_clusters=k) # 构造聚类器 kmeans.fit(X) Scores.append(silhouette_score(X,kmeans.labels_,metric='euclidean')) X = range(2,10) plt.rcParams['font.sans-serif'] = ['SimHei'] plt.rcparams['axes.unicode_minus'] = False plt.xlabel('k值——簇数量') plt.ylabel('轮廓系数') plt.plot(X,Scores,'o-') plt.show()