1. 基本概念
聚类是一种无监督学习方法,旨在根据样本特征之间的相似性或距离远近,将数据划分为若干个“类”或“簇”。其核心思想是:同一簇内的样本应尽可能相似,而不同簇间的样本差异应尽可能大。常见的聚类算法种类繁多,总体可归纳为以下类型:
1.1 距离与相似度
在聚类过程中,衡量样本间关系的关键在于距离或相似度的定义方式。不同的距离计算方法会直接影响最终的聚类结果,因此选择合适的度量标准是聚类分析中的基础问题。
1.2 类或簇的含义
“类”或“簇”是指一组具有较高内部相似性的数据点集合。理想情况下,每个簇代表数据空间中一个相对独立的分布区域,能够反映某种潜在的数据结构或模式。
1.3 类与类之间的距离度量
除了样本点之间的距离外,类与类之间也需要定义距离,以支持如层次聚类等需要合并或分裂簇的操作。常用的方法包括最短距离法、最长距离法、平均距离法和重心法等。
2. 层次聚类算法基本理论
层次聚类通过构建一棵树状结构(即聚类树)来表示数据点逐步聚合的过程,可分为凝聚式(自底向上)和分裂式(自顶向下)两种策略。其中,凝聚式更为常见,它从每个样本作为一个独立簇开始,逐步合并最近的簇,直到满足终止条件。
2.1 Python代码实现层次聚类示例
import numpy as np
import matplotlib.pyplot as plt
from scipy.cluster.hierarchy import linkage, dendrogram, fcluster
# 1. 定义距离矩阵
# 输入的5×5距离矩阵(样本0-4)
distance_matrix = np.array([
[0, 7, 2, 9, 3],
[7, 0, 5, 4, 6],
[2, 5, 0, 8, 1],
[9, 4, 8, 0, 5],
[3, 6, 1, 5, 0]
])
# 2. 生成层次聚类的"链接矩阵"(凝聚式,基于距离矩阵)
from scipy.spatial.distance import squareform
condensed_dist = squareform(distance_matrix)
# 执行凝聚式层次聚类(方法:平均链接,也可选single/complete等)
linkage_matrix = linkage(condensed_dist, method='average') # method可选:single/complete/average
plt.figure(figsize=(8, 5))
dendrogram(
linkage_matrix,
labels=[f"样本{i}" for i in range(5)], # 样本标签
leaf_rotation=0, # 标签旋转角度
leaf_font_size=12,
color_threshold=3, # 聚类颜色阈值(可调整)
above_threshold_color='gray'
)
plt.title('层次聚类树状图(平均链接)')
plt.xlabel('样本')
plt.ylabel('距离')
plt.tight_layout()
plt.show()
# 4. 从层次聚类中提取指定簇数的聚类结果
n_clusters = 2 # 目标簇数
clusters = fcluster(linkage_matrix, t=n_clusters, criterion='maxclust')
print(f"各样本的聚类结果(簇数={n_clusters}):")
for i in range(5):
print(f"样本{i} → 簇{clusters[i]}")
3. K均值聚类方法
K均值是一种广泛使用的划分型聚类算法,其目标是将数据划分为k个簇,使得每个点归属于离其最近的簇中心,且簇内平方和最小。该方法操作简单,适用于大规模数据集,在实际应用中具有较高的实用性。
3.1 K均值算法的主要特性
优点:
- 逻辑清晰、运行高效:算法流程直观,主要包括样本分配与中心更新两个步骤交替迭代,时间复杂度通常为 O(nkt),其中 n 表示样本数量,k 为簇的数量,t 为迭代次数;适合处理大量数据。
- 易于实现和调整参数:只需设定簇数 k 和选用某种距离度量(如欧氏距离),参数少,工程部署成本低。
- 结果解释性强:每个簇的中心由样本均值构成,可作为该簇的代表性向量,便于理解各簇的实际意义,例如在用户分群中可用于刻画典型用户行为特征。
缺点:
- 对初始中心敏感:初始簇中心若随机选取,可能导致结果不稳定,甚至陷入局部最优解。可通过 K-Means++ 方法优化初始中心选择,缓解此问题。
- 需预先确定簇数 k:k 的选择缺乏统一标准,依赖经验判断,虽可借助肘部法则或轮廓系数辅助决策,但仍存在主观性,选择不当会影响聚类质量。
- 对数据形状有要求:仅适用于球形分布、密度均匀的簇结构,对于非球形(如环形)或密度差异较大的数据效果不佳。
- 抗噪能力弱:由于簇中心采用均值计算,异常值会对中心位置产生较大影响,导致整体聚类结果发生偏移。
3.2 使用Python实现K均值聚类
import numpy as np
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
# 定义数据集X,包含5个二维样本点
X = np.array([
[0, 2], # 样本0(将作为第一个初始簇中心)
[0, 0], # 样本1(将作为第二个初始簇中心)
[1, 0], # 样本2
[5, 0], # 样本3
[5, 2] # 样本4
])
# 生成每个样本的标签名称
sample_labels = [f"样本{i}" for i in range(5)]
# 手动设定初始簇中心:选择前两个样本点作为起始中心
init_centers = X[:2]
print("=== 手动指定的初始簇中心 ===")
print(f"初始中心1(样本0):{init_centers[0]}")
print(f"初始中心2(样本1):{init_centers[1]}")
# 构建K-Means模型,并设置参数
kmeans = KMeans(
n_clusters=2, # 设定聚类数量为2,与提供的初始中心数一致
init=init_centers, # 使用手动指定的初始中心
n_init=1, # 因为已指定初始值,故仅执行一次聚类过程
random_state=42 # 固定随机状态以确保结果可重复
)
# 对数据进行拟合并预测每个样本所属的簇
y_pred = kmeans.fit_predict(X)
# 输出聚类完成后的主要结果信息
print("\n=== K均值聚类最终结果 ===")
print(f"最终簇中心坐标:\n{kmeans.cluster_centers_}")
print(f"簇内平方和(SSE):{kmeans.inertia_:.2f}") # 衡量簇内紧密程度
print("\n各样本被划分到的簇:")
for sample, label in zip(sample_labels, y_pred):
print(f"{sample} → 簇{label}")
# 可视化展示:绘制聚类结果图(包括初始与最终中心)
plt.figure(figsize=(10, 7))
# 绘制所有样本点,颜色根据其所属簇进行区分
scatter = plt.scatter(
X[:, 0], X[:, 1],
c=y_pred, s=120, cmap='viridis', alpha=0.8, edgecolors='black'
)
# 标注初始簇中心(使用蓝色三角形表示)
plt.scatter(
init_centers[:, 0],
init_centers[:, 1],
c='blue', s=300, marker='^', label='初始中心(样本0/1)', edgecolors='black'
)
# 标注最终收敛后的簇中心(使用红色星号表示)
plt.scatter(
kmeans.cluster_centers_[:, 0],
kmeans.cluster_centers_[:, 1],
c='red', s=300, marker='*', label='最终簇中心', edgecolors='black'
)
# 在每个样本点旁边添加标签编号
for i, sample in enumerate(sample_labels):
plt.text(X[i,0]+0.1, X[i,1]+0.1, sample, fontsize=12, fontweight='bold')
# 设置图表样式与说明元素
plt.xlabel('特征1', fontsize=12)
plt.ylabel('特征2', fontsize=12)
plt.title('K均值聚类结果(初始中心为前两个样本)', fontsize=14)
plt.grid(alpha=0.3) # 添加轻微网格线提升可读性
plt.legend(loc='upper right') # 显示图例
plt.axis('equal') # 保持坐标轴比例一致,防止图形拉伸变形
plt.tight_layout()
plt.show()

注意:当前的样本0和样本4分别对应书籍中提到的样本1和样本5。
