K 均值聚类(K-Means)演示,通过生成笑脸和爱心两种形状的模拟数据,展示了无监督学习中聚类算法的效果。以下是详细讲解:
一、核心目标
生成两种空间上分离的形状(笑脸和爱心)数据,然后用 K 均值聚类算法自动将它们分为两类,验证聚类算法对 “空间分离明显的数据” 的分类能力。
import numpy as np # 用于数值计算和数组操作
import matplotlib.pyplot as plt # 用于数据可视化
from sklearn.cluster import KMeans # 导入K均值聚类算法
from sklearn.datasets import make_blobs # 生成聚类数据的工具(此处未使用)
2. 生成笑脸形状数据
通过分部分构建笑脸的几何结构,再添加噪声使其更接近真实数据:
三、结果解读
运行代码后,会看到两个子图:
眼睛:用正态分布生成两个密集点集
python
运行
eye1 = np.random.normal(loc=[-1, 1], scale=0.2, size=(50, 2)) # 左眼(围绕(-1,1)) eye2 = np.random.normal(loc=[1, 1], scale=0.2, size=(50, 2)) # 右眼(围绕(1,1))
loc
:中心点坐标;scale
:标准差(控制分散程度);size=(50,2)
:50 个二维点。
嘴巴:用三角函数生成下半圆,再添加噪声
python
运行
theta = np.linspace(np.pi, 2*np.pi, 100) # 角度范围:180°~360°(下半圆) mouth_x = 1.5 * np.cos(theta) # x坐标(余弦函数控制水平方向) mouth_y = 0.5 * np.sin(theta) - 0.5 # y坐标(正弦函数控制垂直方向,下移0.5) mouth = np.column_stack((mouth_x, mouth_y)) # 合并为二维点集 mouth += np.random.normal(loc=0, scale=0.1, size=mouth.shape) # 添加轻微噪声
脸部轮廓:用三角函数生成圆形轮廓,上移 0.5 单位,添加噪声
python
运行
theta = np.linspace(0, 2*np.pi, 200) # 角度范围:0°~360°(全圆) face_x = 2.5 * np.cos(theta) # 圆形x坐标(半径2.5) face_y = 2.5 * np.sin(theta) + 0.5 # 圆形y坐标,整体上移0.5 face = np.column_stack((face_x, face_y)) # 合并为二维点集 face += np.random.normal(loc=0, scale=0.2, size=face.shape) # 添加噪声
合并笑脸:用
np.vstack
垂直堆叠所有部分的点python
运行
smile = np.vstack((eye1, eye2, mouth, face)) # 总点数:50+50+100+200=400
3. 生成爱心形状数据
基于经典心形曲线公式生成,平移到右侧与笑脸分离:
爱心轮廓:用参数方程生成心形曲线,平移到右侧
python
运行
t = np.linspace(0, 2*np.pi, 200) # 角度范围:0°~360° # 经典心形曲线公式 heart_x = 16 * np.sin(t)**3 heart_y = 13 * np.cos(t) - 5 * np.cos(2*t) - 2 * np.cos(3*t) - np.cos(4*t) heart_x += 10 # x方向右移10单位(与笑脸分离) heart_y += 2 # y方向上移2单位 heart = np.column_stack((heart_x, heart_y)) # 合并为二维点集 heart += np.random.normal(loc=0, scale=0.8, size=heart.shape) # 添加噪声
爱心内部点:生成更小的爱心内部点,使形状更丰满
python
运行
t_inner = np.linspace(0, 2*np.pi, 150) # 150个内部点 heart_x_inner = 10 * np.sin(t_inner)**3 # 缩小版x坐标 heart_y_inner = 8 * np.cos(t_inner) - 3 * np.cos(2*t_inner) - ... # 缩小版y坐标 heart_x_inner += 10 # 同样右移10单位 heart_y_inner += 2 # 上移2单位 heart_inner = np.column_stack((heart_x_inner, heart_y_inner)) # 合并 heart_inner += np.random.normal(loc=0, scale=0.6, size=heart_inner.shape) # 噪声
4. 合并所有数据并执行 K 均值聚类
合并数据:将笑脸和爱心的点集合并为一个数据集
X
python
运行
X = np.vstack((smile, heart)) # 总数据量:400+350=750个二维点
K 均值聚类:指定分为 2 类(
n_clusters=2
)python
运行
kmeans = KMeans(n_clusters=2, random_state=42) # 创建模型,固定随机种子 y_kmeans = kmeans.fit_predict(X) # 训练模型并预测每个点的聚类标签(0或1)
5. 可视化结果
创建左右两个子图,对比原始数据和聚类结果:
左侧子图(原始数据):
用蓝色标记笑脸点,红色标记爱心点,清晰展示两种形状的空间分布。python
运行
plt.subplot(121) # 1行2列的第1个子图 plt.scatter(smile[:, 0], smile[:, 1], c='blue', alpha=0.6, label='笑脸') plt.scatter(heart[:, 0], heart[:, 1], c='red', alpha=0.6, label='爱心') plt.title('原始数据') plt.axis('equal') # 等比例坐标轴,避免形状失真 plt.legend() # 显示标签
右侧子图(聚类结果):
用不同颜色展示聚类结果(0 和 1 类),黑色 “X” 标记聚类中心。python
运行
plt.subplot(122) # 1行2列的第2个子图 plt.scatter(X[:, 0], X[:, 1], c=y_kmeans, cmap='viridis', alpha=0.6) # 按聚类标签着色 plt.scatter(kmeans.cluster_centers_[:, 0], kmeans.cluster_centers_[:, 1], s=300, c='black', marker='X', label='聚类中心') # 聚类中心 plt.title('K均值聚类结果') plt.axis('equal') plt.legend()
显示图形:
python
运行
plt.tight_layout() # 自动调整布局,避免标签重叠 plt.show() # 显示图形
合并爱心:堆叠轮廓点和内部点
python
运行
heart = np.vstack((heart, heart_inner)) # 总点数:200+150=350
- 左侧:清晰区分的蓝色笑脸(左侧)和红色爱心(右侧)。
- 右侧:K 均值算法自动将数据分为两类,颜色与原始形状完全对应,且两个黑色 “X” 分别位于笑脸和爱心的中心区域。
四、核心知识点
- 数据生成:用三角函数构建几何形状,正态分布添加噪声,模拟真实世界的 “带有轻微扰动的结构化数据”。
- K 均值聚类:通过迭代优化找到聚类中心,使同类点距离中心更近,异类点距离中心更远。
- 可视化价值:直观展示聚类效果,验证算法对空间分离数据的处理能力。
-
这说明:当数据在空间上明显分离时,K 均值聚类能非常准确地将其划分为不同类别,聚类中心也会落在每个类别的 “密集区域中心”。