一、K-means 聚类介绍
1.含义
K-means 聚类是一种非常流行的无监督学习算法,用于将数据点划分为预定义的 K 个簇(或组),其中每个簇由其质心(即簇中所有点的均值)定义。K-means 算法的目标是使簇内的点尽可能紧密地聚集在一起,同时使不同簇之间的点尽可能远离。
2.基本步骤:
- 选择 K 值:首先,你需要决定将数据分成多少个簇,即 K 的值。K 的选择通常是基于问题的上下文或通过一些启发式方法(如肘部法则)来确定。
- 初始化质心:随机选择 K 个数据点作为初始的簇质心。质心可以是数据集中的任意点,但通常选择相距较远的点作为起始点,以避免局部最优解。
- 分配簇:对于数据集中的每个点,将其分配到最近的质心所在的簇。通常使用欧几里得距离来测量点与质心之间的距离。
- 更新质心:对于每个簇,重新计算其质心(即簇内所有点的均值)。
- 重复迭代:重复步骤 3 和 4,直到质心的位置不再显著变化或达到预设的迭代次数。
- 输出结果:最终,算法会输出 K 个簇和它们的质心。
二、代码实现
1.数据预处理
python
import pandas as pd
import numpy as np
from sklearn.cluster import KMeans
from sklearn import metrics
# 读取文件
beer = pd.read_table('data.txt', sep=' ', encoding='utf8', engine='python')
# 传入变量
X = beer.drop(columns=beer.columns[0])
- 使用pandas的read_table函数读取名为data.txt的文本文件,该文件中的数据通过空格分隔,并指定编码为utf8。
- 通过drop(columns=beer.columns[0])删除数据框beer的第一列,因为这一列不包含用于聚类的特征。剩下的列(特征)被存储在X中。
2.交叉验证
python
# 交叉验证
scores = []
max_range = np.arange(2,10)
for k in max_range:
labels = KMeans(n_clusters=k).fit(X).labels_
score = metrics.silhouette_score(X, labels) # 轮廓系数
scores.append(score)
K = max_range[np.argmax(scores)]
print(K)
print(scores)
- 使用一个循环来尝试不同的K值(从2到9),对于每个K值,使用KMeans类进行聚类,并计算聚类结果的轮廓系数得分。轮廓系数得分范围从-1到1,得分越高表示聚类效果越好。
- 将每个K值对应的轮廓系数得分存储在scores列表中。
- 使用np.argmax(scores)找到scores列表中的最大值索引,该索引对应的K值即为最优的聚类数。打印出最优的K值和对应的轮廓系数得分列表。
3.绘制得分结果
python
import matplotlib.pyplot as plt
plt.plot(list(range(2, 10)), scores)
plt.xlabel('x')
plt.ylabel('y')
plt.show()
- 使用matplotlib库绘制轮廓系数得分随K值变化的折线图,以便直观地观察不同K值下的聚类效果。
4.最终聚类
python
# 聚类
km = KMeans(n_clusters=K).fit(X)
beer['cluster'] = km.labels_
score = metrics.silhouette_score(X, beer.cluster)
print(score)
- 使用选定的最优K值对原始数据进行K-means聚类。
- 将聚类标签添加到原始数据框beer中,作为新列cluster。
- 再次计算并打印使用最优K值聚类后的轮廓系数得分,以验证聚类效果。
5.全部代码
这段代码主要执行了以下几个步骤,用于对啤酒数据集(存储在data.txt文件中)进行K-means聚类,并通过轮廓系数(Silhouette Score)来评估不同聚类数(K值)下的聚类效果,最终选择最优的K值进行聚类,并展示聚类结果和对应的轮廓系数得分。
python
import pandas as pd
import numpy as np
from sklearn.cluster import KMeans
from sklearn import metrics
# 读取文件
beer = pd.read_table('data.txt', sep=' ', encoding='utf8', engine='python')
# 传入变量
X = beer.drop(columns=beer.columns[0])
"""
根据分成不同的族,自动计算轮廓系数得分
"""
# 交叉验证
scores = []
max_range = np.arange(2,10)
for k in max_range:
labels = KMeans(n_clusters=k).fit(X).labels_
score = metrics.silhouette_score(X, labels) # 轮廓系数
scores.append(score)
K = max_range[np.argmax(scores)]
print(K)
print(scores)
# 绘制得分结果
import matplotlib.pyplot as plt
plt.plot(list(range(2, 10)), scores)
plt.xlabel('x')
plt.ylabel('y')
plt.show()
# 聚类
km = KMeans(n_clusters=K).fit(X)
beer['cluster'] = km.labels_
score = metrics.silhouette_score(X, beer.cluster)
print(score)
三、总结
K-means 聚类广泛应用于市场细分、图像分割、文档聚类等领域。例如,在市场营销中,可以将客户划分为不同的群体,以便进行更针对性的推广策略;在图像处理中,可以将图像分割成多个区域,以便进一步分析或压缩。但同时也拥有自己的优缺点。
- 优点:
- 简单易实现。
- 对大数据集具有较好的可扩展性。
- 当簇的密度大致相同且簇间分离良好时,效果非常好。
- 缺点:
- 需要预先指定 K 值,而 K 的选择通常不直观。
- 结果可能受到初始质心选择的影响,可能导致局部最优解。
- 对异常值(噪声)和簇的形状(非球形)敏感。