简介:在本教程中,我们将学习如何在Sklearn库中应用K-means聚类。
在本教程中,我们将学习如何在Sklearn库中应用K-means聚类法。首先,我们将简要介绍什么是聚类,接着了解什么是K-means算法。然后,我们将通过K-means算法的工作原理,之后我们将实现和端到端的代码,在其中我们将实现这个算法,使用'Mall_Customers.csv'数据集进行客户细分。然后,我们将研究两种方法,即肘部方法和剪影方法,通过这两种方法,我们可以计算出给定数据集中的最佳集群数量。
什么是聚类?
聚类是将一组数据分割成不同的组,使同一组中的数据点与那些位于组/群中的数据点具有相似的特征。我们在这里的主要目标是将具有相似特征的组分离出来,给它们分配独特的群组:
- 存在于同一聚类中的点应该有类似的属性
- 存在于不同聚类中的点应尽可能地不相似。
什么是K-Means算法?
K-Means聚类属于无监督机器学习算法的范畴,这些算法将未标记的数据集分为不同的聚类。K定义了需要创建的预设聚类的数量,例如,如果K=2,将有2个聚类,同样,如果K=3,将有3个聚类。实施k-means的主要目标是定义k个聚类,使聚类内的总变化(或误差)达到最小。
聚类中心是属于该聚类的所有数据点的算术平均值。每个给定的点和它的聚类中心之间的平方距离被称为变异。k-means聚类的目标是确定这k个聚类及其中心,同时减少总误差。

K-means算法是如何工作的?
K-means算法的基本工作原理的步骤如下:
第1步:为了决定聚类的数量,我们选择一个合适的K值。
第2步:现在随机选择K点/中心点。
第3步:每个数据点将被分配到其最近的中心点,这将形成一个预定的集群。
第4步:现在我们将计算方差,并为每个聚类定位一个新的中心点。
第5步:第三步将重复进行,也就是说,每个数据点将被分配到新的最近的中心点。
第6步:如果发生了重新分配,那么第4步将被执行,否则执行结束。
第7步:最后,模型准备就绪
Python Sklearn中K均值聚类的例子
我们可以通过Sklearn.cluster模块的KMeans()函数在Python中轻松实现K-Means聚类。在这个例子中,我们将使用购物中心的客户数据集,根据客户的年龄、年收入、消费分数等将其划分为不同的集群。
导入库
让我们导入我们需要的重要库。
在[1]中:
from
加载数据集
让我们把数据集加载到一个数据框架中,并看看其中的一些行。通过形状函数,我们可以看到它有4列和200行。
In[2]:
df
Out[2]:
| 性别 | 年龄 | 年收入(k$) | 支出得分(1-100) | |
|---|---|---|---|---|
| 0 | 男性 | 19 | 15 | 39 |
| 1 | 男 | 21 | 15 | 81 |
| 2 | 女性 | 20 | 16 | 6 |
| 3 | 女 | 23 | 16 | 77 |
| 4 | 女性 | 31 | 17 | 40 |
在[3]:
df
出[3]。
(200, 4)
目标
客户细分涉及到根据其属性中的一些共同模式将集群分组。为了保持这个例子的简单性,并在一个二维图上可视化聚类,我们将只使用两个属性年收入和消费分数。别担心,在这之后我们还将向你展示如何使用超过2个属性进行聚类,并在主成分分析(PCA)的帮助下在二维图上可视化结果。
应用特征缩放
像K-means这样的聚类算法需要将数据的特征缩放作为数据预处理的一部分来产生良好的结果。这是因为聚类技术使用数据点之间的距离计算。因此,将不同单位的数据放在一个共同的尺度下是合适的。
- 欲了解更多详情,你可以阅读以下文章
Sklearn特征缩放与StandardScaler、MinMaxScaler、RobustScaler和MaxAbsScaler的关系
在我们的例子中,我们使用了MinMaxScaler,如下所示。在新的数据框架df_scale中,可以看到年收入和支出分数这两个属性都被规范化了。
In[4]:
scaler = MinMaxScaler()
scale = scaler.fit_transform(df[['Annual Income (k$)','Spending Score (1-100)']])
df_scale = pd.DataFrame(scale, columns = ['Annual Income (k$)','Spending Score (1-100)']);
df_scale.head(5)
Out[4]:
| 年收入(k$) | 支出得分(1-100) | |
|---|---|---|
| 0 | 0.000000 | 0.387755 |
| 1 | 0.000000 | 0.816327 |
| 2 | 0.008197 | 0.051020 |
| 3 | 0.008197 | 0.775510 |
| 4 | 0.016393 | 0.397959 |
应用Kmeans与2个集群(K=2)
让我们看看如何在Sklearn中应用K-Means,将数据集分成2个集群(0和1)。输出显示了数据集中的数据点所对应的聚类(第0或第1)。
In[5]:
km
输出[5]:
array([0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1,
0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1,
1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0,
0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1,
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
0, 1])
为了找到两个聚类的中心点,可以使用cluster_centers_属性,如下图所示
在[6]中:
km
Out[6]:
array([[0.36929553, 0.31163817],
[0.37861485, 0.73950929]])
最后,让我们把结果可视化。从图中可以看出,数据有可能被分成更多的簇,而不是只有2个。但如何知道有多少个簇?让我们在下一节中了解这个问题。
在[7]:
df
出[7]:
<AxesSubplot:xlabel='Spending Score (1-100)', ylabel='Annual Income (k$)'>

寻找K均值中的最佳集群数
K-Means聚类的棘手之处在于,你事先并不知道给定的数据可以被分成多少个簇(因此它是一种无监督学习算法)。这可以通过试错法来完成,但让我们看看更合适的技术。
i) 带集群内平方误差之和(WCSS)的肘部方法
肘部法是一种流行的技术,用于确定最佳的集群数量。在这里,我们计算不同k值的群内平方误差之和(WCSS),并选择WSS首次开始减少的k。在WSS与k的关系图中,可以观察到这是一个肘部。
- 一个数据点的平方误差是一个点离其聚类中心距离的平方。
- WSS得分是所有给定数据点的平方误差的总和。
- 可以使用欧几里得距离或曼哈顿距离等距离指标。
继续我们的例子,我们计算K=2到k=12的WCS,并在每次迭代中计算WCS。
在[8]中:
K=range(2,12)
wss = []
for k in K:
kmeans=cluster.KMeans(n_clusters=k)
kmeans=kmeans.fit(df_scale)
wss_iter = kmeans.inertia_
wss.append(wss_iter)
现在让我们绘制WCSS与K集群的关系图。从下面可以看出,在K=5处有一个弯头,也就是说,在这个点之后,WCSS不会随着K值的增加而减少很多。
在[9]中:
plt
出[9]。

ii) 剪影法
剪影值衡量一个数据点在其聚类中的相似度。它的范围在+1和-1之间,数值越高表示聚类越好。
下面我们计算了k=2到12的剪影值,可以看出,k=5的值最大。这与肘部方法是一致的。
In[10]:
import sklearn.cluster as cluster
import sklearn.metrics as metrics
for i in range(2,13):
labels=cluster.KMeans(n_clusters=i,random_state=200).fit(df_scale).labels_
print ("Silhouette score for k(clusters) = "+str(i)+" is "
+str(metrics.silhouette_score(df_scale,labels,metric="euclidean",sample_size=1000,random_state=200)))
Out[10]:
Silhouette score for k(clusters) = 2 is 0.33340205479521
Silhouette score for k(clusters) = 3 is 0.4514909309424474
Silhouette score for k(clusters) = 4 is 0.49620078745146784
Silhouette score for k(clusters) = 5 is 0.5594854531227246
Silhouette score for k(clusters) = 6 is 0.5380652777999084
Silhouette score for k(clusters) = 7 is 0.43787929453711455
Silhouette score for k(clusters) = 8 is 0.43074523601514214
Silhouette score for k(clusters) = 9 is 0.4421331695270676
Silhouette score for k(clusters) = 10 is 0.44563877983976935
Silhouette score for k(clusters) = 11 is 0.44293254541345917
Silhouette score for k(clusters) = 12 is 0.4427512711673661
应用5个簇的Kmeans (K=5)
现在我们已经确定了K的最佳值是5
在[11]中:
# We will use 2 Variables for this example
最后,让我们绘制k=5个簇的图,我们可以看到现在的K-Means结果看起来不错。
在[12]中:
df['Clusters'] = kmeans.labels_
sns
Out[12]:

在Python Sklearn中用主成分分析进行K均值聚类
在上面的例子中,我们只用了两个属性来进行聚类,因为在二维图中,我们更容易将结果可视化。在三维图中,我们无法看到超过3个属性的东西,而在现实世界的场景中,可能有上百个属性。那么,我们怎样才能将聚类结果可视化呢?
嗯,可以通过在数据集上应用主成分分析(PCA),将其维度减少到只有两个,同时仍然保留信息。然后,聚类可以应用于这个转换后的数据集,然后在一个二维图中可视化。此外,PCA还可以帮助避免维度的诅咒。
所以,让我们看看下面这个实际情况,我们将在同一个数据集上使用3个属性。
加载数据集
让我们再次像以前一样在数据框中加载数据集。
In[13]:
df
Out[13]:
| 性别 | 年龄 | 年收入(千美元) | 支出得分(1-100) | |
|---|---|---|---|---|
| 0 | 男性 | 19 | 15 | 39 |
| 1 | 男 | 21 | 15 | 81 |
| 2 | 女性 | 20 | 16 | 6 |
| 3 | 女 | 23 | 16 | 77 |
| 4 | 女性 | 31 | 17 | 40 |
应用特征缩放
这一次,我们将对我们所需的年龄、年收入和消费分数等列进行特征缩放。
In[14]:
scaler = MinMaxScaler()
scale = scaler.fit_transform(df[['Age','Annual Income (k$)','Spending Score (1-100)']])
df_scale = pd.DataFrame(scale, columns = ['Age','Annual Income (k$)','Spending Score (1-100)']);
df_scale.head(5)
Out[14]:
| 年龄 | 年收入(k$) | 支出得分(1-100) | |
|---|---|---|---|
| 0 | 0.019231 | 0.000000 | 0.387755 |
| 1 | 0.057692 | 0.000000 | 0.816327 |
| 2 | 0.038462 | 0.008197 | 0.051020 |
| 3 | 0.096154 | 0.008197 | 0.775510 |
| 4 | 0.250000 | 0.016393 | 0.397959 |
应用PCA
现在让我们把数据集的维度减少到两个部分。
在[15]:
from
出[15]:
| 主成分1 | 主成分2 | |
|---|---|---|
| 0 | -0.192221 | 0.319683 |
| 1 | -0.458175 | -0.018152 |
| 2 | 0.052562 | 0.551854 |
| 3 | -0.402357 | -0.014239 |
| 4 | -0.031648 | 0.155578 |
寻找K的最佳值
i) 肘部方法与平方误差之和(WCSS)的关系
让我们再次使用带有平方误差群内和(WCSS)的弯头法来确定K的最佳值。从图中看,在5和6之间有一个弯头。
在[16]中:
K
在[17]中:
plt
Out[17]:

二)剪影法
使用剪影法,可以看出K=5时剪影值最大。因此,可以得出结论,数据集可以用6个聚类进行适当分割。
In[18]:
import
Out[18]:
Silhouette score for k(clusters) = 2 is 0.4736269407502857
Silhouette score for k(clusters) = 3 is 0.44839082753844756
Silhouette score for k(clusters) = 4 is 0.43785291876777566
Silhouette score for k(clusters) = 5 is 0.45130680489606634
Silhouette score for k(clusters) = 6 is 0.4507847568968469
Silhouette score for k(clusters) = 7 is 0.4458795480456887
Silhouette score for k(clusters) = 8 is 0.4132957148795121
Silhouette score for k(clusters) = 9 is 0.4170428610065107
Silhouette score for k(clusters) = 10 is 0.4309783655094101
Silhouette score for k(clusters) = 11 is 0.42535265774570674
应用5个聚类的Kmeans(K=5)
通过传递k=5的值,用SKlearn KMeans()应用K均值聚类。
在[19]中:
kmeans
在可视化聚类时,可以看到它产生了良好的结果。
在[20]中:
pca_df['Clusters'] = kmeans.labels_
sns
Out[20]:

结论
我们希望你喜欢我们的教程,现在能更好地理解如何在Python中使用Sklearn(Scikit Learn)实现K-means聚类。在这里,我们已经说明了一个使用数据集建立K-means聚类模型以实现客户细分的端到端例子(KMeans Clustering in Python)。