欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

数据分析|Kmeans数据分析

时间:2023-04-24
Kmeans聚类分析

一、模型介绍

1、聚类步骤2、原理介绍3、k值的选择

01 拐点法02 轮廓系数法 二、代码实现 一、模型介绍 1、聚类步骤 从数据中随机挑选k个样本点作为原始的簇中心计算剩余样本与簇中心的距离,并把各样本标记为离k个簇中心最近的类别重新计算各簇中样本点的均值,并以均值作为新的k个簇中心不断重复第二步和第三步,直到簇中心变化趋于稳定,形成最终的k个簇 2、原理介绍

Kmeans聚类的目标函数:
J ( c 1 , c 2 , ⋯   , c k ) = ∑ j = 1 k ∑ i n j ( x i − c j ) 2 J(c_1,c_2,cdots,c_k)=sum_{j=1}^ksum_i^{n_j}(x_i-c_j)^2 J(c1​,c2​,⋯,ck​)=j=1∑k​i∑nj​​(xi​−cj​)2
即k个簇内样本的离差平方和之和达到最小。对目标函数求偏导(与k无关)
∂ J ∂ c j = ∑ i = 1 n j ( x i − c j ) 2 ∂ c j = ∑ i = 1 n j − 2 ( x i − c j ) frac{partial J}{partial c_j}=sum_{i=1}^{n_j}frac{(x_i-c_j)^2}{partial c_j}=sum_{i=1}^{n_j}-2(x_i-c_j) ∂cj​∂J​=i=1∑nj​​∂cj​(xi​−cj​)2​=i=1∑nj​​−2(xi​−cj​)
令导函数等于零:
c j = ∑ i = 1 n j x i n j = μ j c_j = frac{sum_{i=1}^{n_j}x_i}{n_j}=mu_j cj​=nj​∑i=1nj​​xi​​=μj​
故,我们需要求的是均值。

3、k值的选择

随着k值的增加,簇内离差平方和应该不断变小,直至趋向于0。

01 拐点法

当簇内离差平方和所构成的折线图中,斜率由大突然变小,并且之后的斜率变化缓慢,则认为突然变化的点就是寻找的目标点。

python没有专门的库函数用于计算拐点,这里引用刘顺祥老师的自定义函数方案:

def k_SSE(X, clusters): # 选择连续的K种不同的值 K = range(1,clusters+1) # 构建空列表用于存储总的簇内离差平方和 TSSE = [] for k in K: # 用于存储各个簇内离差平方和 SSE = [] kmeans = KMeans(n_clusters=k) kmeans.fit(X) # 返回簇标签 labels = kmeans.labels_ # 返回簇中心 centers = kmeans.cluster_centers_ # 计算各簇样本的离差平方和,并保存到列表中 for label in set(labels): SSE.append(np.sum((X.loc[labels == label,]-centers[label,:])**2)) # 计算总的簇内离差平方和 TSSE.append(np.sum(SSE))

02 轮廓系数法

该方法考虑了簇的密集性与分散性两个信息,若数据集被分割为理想的k个簇,那么对应的簇内样本会很密集,而簇间样本会很分散,轮廓系数计算可表示为:
S ( i ) = b ( i ) − a ( i ) m a x ( a ( i ) , b ( i ) ) S(i)=frac{b(i)-a(i)}{max(a(i),b(i))} S(i)=max(a(i),b(i))b(i)−a(i)​
a ( i ) a(i) a(i)体现簇内的密集性,代表样本i与同簇内其他样本距离的平均值; b ( i ) b(i) b(i)反应了簇间的分散性,即样本i与其他非同簇样本点的距离的平均值,然后取其中的最小值。

当 S ( i ) S(i) S(i)接近与-1时,说明样本i的分配不合理,需要将其分配到其他簇中;当 S ( i ) S(i) S(i)近似为0时,说明样本i落在了模糊地带,即簇的边界;当 S ( i ) S(i) S(i)近似为1时,说明样本i的分配是合理的。

# 构造自定义函数,用于绘制不同k值和对应轮廓系数的折线图def k_silhouette(X, clusters): K = range(2,clusters+1) # 构建空列表,用于存储个中簇数下的轮廓系数 S = [] for k in K: kmeans = KMeans(n_clusters=k) kmeans.fit(X) labels = kmeans.labels_ # 调用字模块metrics中的silhouette_score函数,计算轮廓系数 S.append(metrics.silhouette_score(X, labels, metric='euclidean')) # 中文和负号的正常显示 plt.rcParams['font.sans-serif'] = ['Microsoft YaHei'] plt.rcParams['axes.unicode_minus'] = False # 设置绘图风格 plt.style.use('ggplot') # 绘制K的个数与轮廓系数的关系 plt.plot(K, S, 'b*-') plt.xlabel('簇的个数') plt.ylabel('轮廓系数') # 显示图形 plt.show() # 自定义函数的调用k_silhouette(X, 15)

二、代码实现

KMeans(n_cluster=8, init='k-means++', n_init=10,max_iter=300, tol=0.0001)

n_cluster:用于 指定聚类的簇数init:用于指定初始的簇中心设置方法,如果为’k-means++’,表示设置的初始簇中心之间相距较远;若为’random’,则表示从数据集中随机挑选k个样本作为初始簇中心;若为数组,则表示用户指定的具体簇中心。n_init:指定Kmeans算法的运行次数,每次都会选择不同的簇中心,默认为10

# 读取球员数据players = pd.read_csv(r'players.csv')players.head()

# 绘制得分与命中率的散点图sns.lmplot(x = '得分', y = '命中率', data = players, fit_reg = False, scatter_kws = {'alpha':0.8, 'color': 'steelblue'})plt.show()

from sklearn import preprocessing# 数据标准化处理X = preprocessing.minmax_scale(players[['得分','罚球命中率','命中率','三分命中率']])# 将数组转换为数据框X = pd.Dataframe(X, columns=['得分','罚球命中率','命中率','三分命中率'])# 使用拐点法选择最佳的K值k_SSE(X, 15)

# 使用轮廓系数选择最佳的K值k_silhouette(X, 10)

# 将球员数据集聚为3类kmeans = KMeans(n_clusters = 3)kmeans.fit(X)# 将聚类结果标签插入到数据集players中players['cluster'] = kmeans.labels_# 构建空列表,用于存储三个簇的簇中心centers = []for i in players.cluster.unique(): centers.append(players.ix[players.cluster == i,['得分','罚球命中率','命中率','三分命中率']].mean())# 将列表转换为数组,便于后面的索引取数centers = np.array(centers)# 绘制散点图sns.lmplot(x = '得分', y = '命中率', hue = 'cluster', data = players, markers = ['^','s','o'], fit_reg = False, scatter_kws = {'alpha':0.8}, legend = False)# 添加簇中心plt.scatter(centers[:,0], centers[:,2], c='k', marker = '*', s = 180)plt.xlabel('得分')plt.ylabel('命中率')# 图形显示plt.show()

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。