数据分析 | Kmeans数据分析

1. 聚类步骤

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}^k\sum_i^{n_j}(x_i-c_j)^2 J (c 1 ​,c 2 ​,⋯,c k ​)=j =1 ∑k ​i ∑n j ​​(x i ​−c j ​)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)∂c j ​∂J ​=i =1 ∑n j ​​∂c j ​(x i ​−c j ​)2 ​=i =1 ∑n j ​​−2 (x i ​−c j ​)
令导函数等于零:
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 c j ​=n j ​∑i =1 n j ​​x i ​​=μj ​
故,我们需要求的是均值。

3. k值的选择

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

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

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

def k_SSE(X, clusters):

    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))

该方法考虑了簇的密集性与分散性两个信息,若数据集被分割为理想的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 )=m a x (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的分配是合理的。


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_

        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')

    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_SSE(X, 15)

k_silhouette(X, 10)

kmeans = KMeans(n_clusters = 3)
kmeans.fit(X)

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()

Original: https://blog.csdn.net/weixin_63641425/article/details/123155573
Author: Ouroboroszzs
Title: 数据分析 | Kmeans数据分析

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/549976/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球