K均值聚类(K-means clustering)是一种常用的无监督学习方法,用于将一组数据点划分为K个簇(cluster)。
它的目标是将相似的数据点归到同一个簇中,同时使得不同簇之间的数据点尽可能不相似。K均值聚类算法的基本步骤如下:
- 随机选择K个数据点作为初始簇中心。
- 对于每个数据点,计算其与各个簇中心的距离,并将其归到距离最近的簇。
- 根据步骤2的结果,更新每个簇的中心,新的簇中心是簇内所有数据点的均值。
- 重复步骤2和3,直到簇中心的变化小于某个阈值或达到最大迭代次数。
python
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
import numpy as np
import math
python
X,y=make_blobs(n_samples=1000,n_features=2,centers=4,random_state=0)
plt.scatter(X[:,0],X[:,1],s=50,c=y)
plt.show()
python
from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=4,n_init=20)
kmeans.fit(X)
centroids = kmeans.cluster_centers_
labels = kmeans.labels_
python
# 获取聚类中心
centroids
array([[ 1.99871335, 0.79038817],
[ 0.97790397, 4.28661633],
[-1.31360134, 7.86561393],
[-1.51473374, 2.8755229 ]])
python
# 获取每个数据点的标签
labels[:2]
array([2, 1], dtype=int32)
python
plt.scatter(X[:,0], X[:,1], c=labels, cmap='viridis')
plt.scatter(centroids[:, 0], centroids[:, 1], s=300, c='red', marker='X')
plt.title('K-means Clustering')
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.show()
衡量K均值聚类效果的一种常见方法是计算轮廓系数(Silhouette Coefficient)。
轮廓系数是一个介于-1到1之间的值,用于评估聚类的紧密程度和分离程度。
轮廓系数越接近1,表示聚类效果越好;轮廓系数越接近-1,表示聚类效果越差;轮廓系数接近0,则表示聚类重叠。
轮廓系数的计算方式如下:
- 对于每个样本,计算它与同簇其他样本的平均距离(称为a值)。
- 对于每个样本,找到与其最近的另一个簇,计算该样本与该簇内所有样本的平均距离(称为b值)。
- 对于每个样本,计算轮廓系数:(b - a) / max(a, b)。
python
# 在sklearn中,可以使用silhouette_score函数来计算轮廓系数
python
from sklearn.metrics import silhouette_score
python
# 计算轮廓系数
silhouette_avg = silhouette_score(X, labels)
python
silhouette_avg
0.4962703221079925
除了轮廓系数,还有一些其他指标可以用来评估聚类的效果,例如:
- 内部凝聚度(Within-Cluster Sum of Squares, WCSS):衡量簇内样本的紧密程度,WCSS越小,簇内样本越紧密。
- 戴维森堡丁指数(Davies-Bouldin Index):衡量簇之间的分离程度,值越小,簇之间分离得越好。
- 调整兰德指数(Adjusted Rand Index, ARI):如果已知真实标签,可以使用ARI来评估聚类结果与真实标签的相似度。
选择哪种评估指标取决于你的具体应用场景和需求。
如果是对聚类效果的初步评估,轮廓系数通常是一个不错的选择。
如果你有真实的标签数据,可以使用ARI来评估聚类的准确性。
python
from sklearn.metrics import adjusted_rand_score
python
ari = adjusted_rand_score(y, labels)
python
ari
0.8304756406041541
确定聚类点的个数(即确定最佳的聚类数K)是一个关键问题,也是聚类分析中的一个挑战。以下是一些常用的方法来确定最佳的聚类数:
- 肘部法则(Elbow Method) :
- 计算不同K值下的内部凝聚度(WCSS)。
- 绘制WCSS随着K值增加的变化曲线。
- 曲线的"肘部"通常被认为是最佳的K值,因为在这一点之后,增加聚类数带来的改善变得不那么显著。
- 轮廓系数(Silhouette Coefficient) :
- 对于不同的K值,计算所有样本的轮廓系数。
- 选择使平均轮廓系数最大的K值作为最佳的聚类数。
- 间隙统计(Gap Statistic) :
- 计算不同K值下的聚类效果与参考分布(通常是随机数据)之间的间隙。
- 选择使间隙最大的K值作为最佳的聚类数。
- 信息准则(Information Criterion) :
- 使用类似于决策树的方法,如赤池信息准则(AIC)或贝叶斯信息准则(BIC)。
- 选择使信息准则最小的K值作为最佳的聚类数。
- 基于密度的方法 :
- 使用DBSCAN(Density-Based Spatial Clustering of Applications with Noise)等基于密度的聚类算法,它们不需要预先指定聚类数。
- 层次聚类(Hierarchical Clustering) :
- 使用层次聚类方法构建聚类树。
- 根据树状图或距离阈值来确定最佳的聚类数。
在实际应用中,可能需要结合多种方法来确定最佳的聚类数,因为每种方法都有其优势和局限性。以下是一个使用肘部法则和轮廓系数来确定最佳聚类数的示例:
python
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
import matplotlib.pyplot as plt
python
# 使用肘部法则
wcss = []
for i in range(1, 11):
kmeans = KMeans(n_clusters=i, init='k-means++', max_iter=300, n_init=10, random_state=0)
kmeans.fit(X)
wcss.append(kmeans.inertia_)
plt.plot(range(1, 11), wcss)
plt.title('Elbow Method')
plt.xlabel('Number of clusters')
plt.ylabel('WCSS')
plt.show()
python
# 使用轮廓系数
silhouette_scores = []
for i in range(2, 11):
kmeans = KMeans(n_clusters=i, init='k-means++', max_iter=300, n_init=10, random_state=0)
kmeans.fit(X)
cluster_labels = kmeans.predict(X)
silhouette_scores.append(silhouette_score(X, cluster_labels))
plt.plot(range(2, 11), silhouette_scores)
plt.title('Silhouette Score')
plt.xlabel('Number of clusters')
plt.ylabel('Silhouette Score')
plt.show()
在这个示例中,我们首先使用肘部法则绘制了WCSS随着聚类数增加的变化曲线,然后使用轮廓系数绘制了不同聚类数下的平均轮廓系数。根据这两个图表,我们可以观察到最佳的聚类数。通常,我们会寻找WCSS曲线的"肘部"和轮廓系数的最高点,这些点通常指示最佳的聚类数。
关于K-均值聚类算法:
- 无监督学习:K-均值是一种无监督机器学习算法,用于将未标记的数据集分为若干个簇。
- 简单易实现:算法原理简单,实现起来较为容易,适合处理大规模数据集。
- 迭代优化:通过迭代过程不断更新簇中心,直到满足停止条件(如达到最大迭代次数或簇中心变化小于阈值)。
- 簇数量预定义:需要预先指定簇的数量K,这对于算法的结果有重要影响。
- 基于距离:算法基于数据点之间的距离来进行聚类,通常使用欧氏距离。
- 可能陷入局部最优:K-均值算法可能陷入局部最优解,初始中心的选择对结果有很大影响。
在应用中需要注意的一些问题:
- 选择合适的K值:确定最佳的簇数量K是K-均值聚类中的一个关键问题,可以使用肘部法则、轮廓系数等方法来估计。
- 初始化中心:初始中心的选择可能会影响最终聚类结果,可以使用多次随机初始化或K-means++等方法来改善。
- 噪声和离群点:K-均值对噪声和离群点敏感,可能会对聚类结果产生负面影响,需要对数据进行预处理。
- 变量尺度:不同特征的尺度可能会对聚类结果产生影响,需要进行标准化或归一化处理。
- 非凸聚类:K-均值适用于凸数据集,对于非凸聚类或具有复杂形状的簇,K-均值可能不是最佳选择。
- 解释性:K-均值聚类的结果可能不具有很好的解释性,特别是在高维数据中。
- 计算复杂度:随着数据量和簇数量的增加,计算复杂度会上升,可能需要考虑算法的效率。
- 适用性:K-均值聚类适用于数值型数据,对于非数值型数据,可能需要转换为数值型数据或使用其他聚类算法。
- 超参数调整:K-均值算法中的一些超参数(如最大迭代次数、距离度量等)可能需要根据具体问题进行调整。
- 评估聚类质量:使用适当的评估指标(如轮廓系数、WCSS等)来评估聚类结果的质量。
python
数据预处理
K-均值聚类算法对噪声和离群点的敏感性是因为它们对聚类中心的计算有显著影响。为了减少这种影响,可以在聚类之前对数据进行预处理。以下是一些处理噪声和离群点的方案:
- 离群点检测 :
- 使用箱线图(Box Plot)等方法检测离群点,并移除它们。
- 使用DBSCAN等基于密度的聚类方法来识别噪声点。
- 数据标准化 :
- 对数据进行标准化或归一化,使得每个特征对聚类中心的贡献相同。
- 例如,使用最小-最大标准化或Z-score标准化。
- 特征选择 :
- 移除与聚类无关的特征,特别是那些可能引入噪声的特征。
- 使用主成分分析(PCA)等降维技术来减少特征数量。
- 数据清洗 :
- 手动检查数据,移除明显错误的或异常的数据点。
- 使用数据清洗工具或库(如OpenRefine)来自动化清洗过程。
- 使用鲁棒性更强的距离度量 :
- 使用马氏距离(Mahalanobis Distance)等鲁棒性更强的距离度量,减少离群点的影响。
- 软聚类方法 :
- 使用模糊C-均值(FCM)或基于密度的聚类方法,这些方法允许样本属于多个簇,从而减少离群点的影响。
- 预处理步骤 :
- 在聚类之前,使用平滑技术或滤波器(如中值滤波)来减少噪声。
- 异常值处理 :
- 使用异常值检测算法(如LOF、IF等)来识别和处理异常值。
- 聚类后处理 :
- 在聚类完成后,分析聚类结果,检查簇的大小和密度,手动或自动地调整聚类结果。
- 使用专业软件或库 :
- 使用专门设计用于处理噪声和离群点的软件或库,如Robust PCA。
在实际应用中,可能需要结合多种方法来处理噪声和离群点,以获得最佳的聚类结果。此外,预处理步骤可能需要根据具体的数据集和聚类任务进行调整。
- 使用专门设计用于处理噪声和离群点的软件或库,如Robust PCA。
K-means++
K-means++是一种用于初始化K-均值聚类算法中簇中心的方法。在标准的K-均值算法中,初始簇中心是随机选择的,这可能导致算法收敛到局部最优解,尤其是当簇的形状和大小差异较大时。K-means++旨在通过一种更合理的方法来选择初始中心,从而提高算法的稳定性和聚类质量。
K-means++的初始化过程如下:
- 随机选择第一个中心:从数据集中随机选择一个样本作为第一个簇中心。
- 选择后续中心:对于剩下的每个中心,选择的原则是选择那些与已有中心距离最远的样本。具体来说,每个样本被选为下一个中心的概率与它到最近中心的距离的平方成正比。
- 重复选择 :重复步骤2,直到选择了K个中心。
K-means++的主要优点是它减少了初始中心选择对聚类结果的影响,特别是当数据集具有不同的簇大小和密度时。通过这种方法,K-means++通常能够找到更好的局部最优解,从而提高聚类的整体质量。
在Python的sklearn库中,可以通过设置KMeans
初始化参数init='k-means++'
来使用K-means++初始化方法。例如:
python
from sklearn.cluster import KMeans
# 使用K-means++初始化
kmeans = KMeans(n_clusters=3, init='k-means++', n_init=10, max_iter=300, random_state=42)
kmeans.fit(X)
# 获取聚类结果
labels = kmeans.labels_
# 在这个例子中,`init='k-means++'`指定了使用K-means++来初始化簇中心,`n_init=10`表示算法会使用K-means++初始化10次,并选择最好的聚类结果。
数据集的凸性
在聚类分析中,数据集的凸性是一个重要的概念,它关系到聚类算法的适用性和聚类结果的质量。
- 凸数据集 :
- 如果数据集的每个点都位于某个凸多边形内部,那么这个数据集就是凸的。
- 凸数据集意味着数据点之间的最小距离沿着连接这些点的线段上。
- 在凸数据集中,K-均值算法能够较好地工作,因为它能够找到将数据点分为几个紧凑的簇的聚类中心。
- 非凸聚类 :
- 非凸聚类指的是数据集的簇不是凸的,而是具有不规则的形状或重叠的边界。
- 非凸聚类意味着数据点之间的最小距离不沿着连接这些点的线段上,而是沿着更复杂的路径。
- 在非凸聚类中,K-均值算法可能无法找到理想的聚类中心,因为它倾向于将簇中心定位在簇的中心,而不是沿着边界。
- 具有复杂形状的簇 :
- 具有复杂形状的簇是指簇的边界不是简单的直线或平面,而是具有多个拐点或弯曲的形状。
- 这样的簇通常出现在高维空间中,其中数据点可以形成复杂的几何形状。
- K-均值算法在处理这类簇时可能会遇到困难,因为它在寻找聚类中心时可能无法捕捉到簇的复杂形状。
在实际应用中,数据集可能同时包含凸簇和非凸簇,或者数据点在某些维度上是凸的,而在其他维度上是非凸的。因此,选择合适的聚类算法时需要考虑数据集的特性,并且在可能的情况下,可以结合使用多种聚类算法来获得更好的聚类结果。对于非凸聚类或具有复杂形状的簇,可以考虑使用基于密度的聚类算法(如DBSCAN)、层次聚类、模糊C-均值(FCM)或其他能够处理非凸数据集的聚类算法。
自动选择最佳簇数量
有一些工具和方法可以帮助自动选择最佳簇数量,而不需要手动调整参数。以下是一些常用的自动选择最佳簇数量的方法:
- Elbow Method Visualization :
- 手动绘制WCSS(Within-Cluster Sum of Squares)随K值变化的曲线。
- 观察曲线在何时开始变平缓,这个点通常对应于最佳的K值。
- Silhouette Score :
- 对于不同的K值,计算所有样本的轮廓系数。
- 选择使平均轮廓系数最大的K值作为最佳簇数量。
- Gap Statistic :
- 计算不同K值下的聚类效果与参考分布之间的间隙。
- 选择使间隙最大的K值作为最佳簇数量。
- AutoKMeans :
- 这是一个Python库,它提供了一种自动选择最佳簇数量的方法。
- 使用网格搜索和交叉验证来找到最佳的K值。
- Hierarchical Clustering with Dendrograms :
- 使用层次聚类构建聚类树。
- 根据树状图或距离阈值来确定最佳簇数量。
- Mean-Shift and Gaussian Mixture Models :
- 这些算法可以自动选择最佳簇数量。
- 通过优化某种性能指标(如BIC或AIC)来确定K值。
- Auto-Ensemble :
- 这是一个Python库,它提供了一种自动选择最佳簇数量的方法。
- 它通过多种聚类算法和评估指标来找到最佳的K值。
- Agglomerative Clustering :
- 使用层次聚类算法,根据树状图或距离阈值来确定最佳簇数量。
在实际应用中,可能需要结合多种方法来确定最佳簇数量。此外,不同的应用场景可能需要不同的评估指标和策略。例如,在时间序列分析中,可能需要考虑时间序列的长度,而在图像处理中,可能需要考虑图像的分辨率。
- 使用层次聚类算法,根据树状图或距离阈值来确定最佳簇数量。
业务应用
K-均值聚类算法广泛应用于实际业务中,尤其是在需要将大量数据划分为有意义类别的情况下。以下是一个结合业务的K-均值聚类算法应用示例:
业务场景: 电子商务平台商品分类
问题描述: 电子商务平台上有大量的商品,每种商品都有多个属性,如价格、品牌、尺寸、颜色等。为了更好地组织商品,并为用户提供更准确的搜索和推荐服务,需要对这些商品进行有效的分类。
解决方案: 使用K-均值聚类算法对商品进行分类。
步骤:
- 数据准备 :
- 收集商品的多个属性数据,如价格、品牌、尺寸、颜色等。
- 选择合适的特征集,例如,只使用价格和品牌作为聚类的特征。
- 选择初始簇数 :
- 可以使用肘部法则、轮廓系数或自动选择最佳簇数量的方法来估计最佳的簇数K。
- 应用K-均值算法 :
- 使用选择的K值,应用K-均值算法对商品进行聚类。
- 初始化聚类中心,并迭代更新聚类中心和分配每个商品到最近的簇。
- 评估聚类质量 :
- 使用轮廓系数、内部凝聚度等指标来评估聚类质量。
- 检查每个簇的商品是否具有相似的特征,如价格范围、品牌等。
- 结果应用 :
- 根据聚类结果,为每个簇创建一个商品类别。
- 在网站的商品展示、搜索和推荐系统中使用这些类别。
- 根据用户的历史行为和偏好,推荐相似的商品给用户。
- 迭代优化 :
- 定期重新聚类商品,以反映市场变化和用户行为的变化。
- 根据业务需求和用户反馈调整聚类参数和特征选择。
优点:
- K-均值算法简单高效,能够快速处理大量数据。
- 可以根据业务需求灵活选择聚类特征和评估指标。
- 结果可以应用于多个业务场景,如商品分类、搜索优化和个性化推荐。
注意事项:
- 需要对数据进行预处理,例如处理缺失值、标准化特征等。
- 初始聚类中心的选择对结果有影响,可能需要多次尝试找到最佳初始中心。
- 业务需求和数据特性可能会影响聚类结果,需要根据实际情况调整聚类参数和特征选择。
在商品推荐中应用聚类结果通常涉及以下步骤:
- 数据收集 :
- 收集用户行为数据,如购买历史、浏览历史、搜索历史等。
- 收集商品数据,包括商品特征、价格、库存、类别等。
- 用户聚类 :
- 使用K-均值或其他聚类算法对用户进行聚类,基于用户的相似行为和偏好。
- 每个簇代表一组具有相似偏好的用户。
- 商品聚类 :
- 同样使用K-均值或其他聚类算法对商品进行聚类,基于商品的相似特征和属性。
- 每个簇代表一组具有相似特征的商品。
- 推荐策略 :
- 根据用户所在的聚类,推荐与之相似的商品聚类中的商品。
- 例如,如果用户A属于用户聚类C1,那么推荐商品聚类C1中的商品给用户A。
- 个性化调整 :
- 考虑用户的个性化偏好,例如用户A在聚类C1中,但更喜欢聚类C2中的商品,那么在推荐时可以考虑增加聚类C2中的商品比例。
- 反馈循环 :
- 收集用户对推荐商品的反馈,如点击率、购买率等。
- 基于反馈调整聚类结果和推荐策略,以提高推荐准确性。
- 性能评估 :
- 定期评估推荐系统的性能,例如使用准确率、召回率、F1分数等指标。
- 根据评估结果调整聚类参数和推荐策略。
- 实时更新 :
- 随着用户行为和商品信息的变化,定期更新聚类结果和推荐列表。
通过在商品推荐中应用聚类结果,可以更准确地识别用户的偏好,并提供更个性化的推荐。这种方法不仅提高了推荐的准确性,还能帮助用户发现更多符合他们兴趣的商品。
- 随着用户行为和商品信息的变化,定期更新聚类结果和推荐列表。
python