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/
转载文章受原作者版权保护。转载请注明原作者出处!