news 2026/7/13 11:30:12

K-Means 算法 Python 实现:3 种可视化方案对比与 1 个完整动画代码

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
K-Means 算法 Python 实现:3 种可视化方案对比与 1 个完整动画代码

K-Means 算法 Python 实现:3 种可视化方案对比与 1 个完整动画代码

在数据科学领域,K-Means 算法因其简洁高效而广受欢迎。但真正理解其迭代过程,往往需要直观的可视化支持。本文将带你用 Python 实现三种不同的可视化方案,并提供一个完整的动画演示代码,让你不仅掌握算法原理,还能生动展示聚类过程。

1. 环境准备与数据加载

首先确保你的 Python 环境已安装必要的库:

pip install numpy matplotlib scikit-learn

我们使用经典的test.txt数据集进行演示。这个二维数据集包含 80 个样本点,非常适合可视化展示:

import numpy as np from matplotlib import pyplot as plt from sklearn.datasets import make_blobs # 加载数据集 def load_data(file_path): data = [] with open(file_path) as f: for line in f.readlines(): point = list(map(float, line.strip().split())) data.append(point) return np.array(data) # 生成示例数据(备选) def generate_sample_data(): X, _ = make_blobs(n_samples=300, centers=4, cluster_std=0.6) return X

提示:实际项目中,建议先用sklearn.datasets.make_blobs生成可控的测试数据,验证算法正确性后再应用于真实数据。

2. 三种可视化方案实现

2.1 静态分步图解法

这种方案适合教学演示,能清晰展示算法每个关键步骤:

def plot_steps(data, centers, assignments, step): plt.figure(figsize=(10, 6)) colors = ['r', 'g', 'b', 'c', 'm', 'y', 'k'] # 绘制数据点 for i in range(len(centers)): cluster_data = data[assignments == i] plt.scatter(cluster_data[:,0], cluster_data[:,1], c=colors[i], s=50, alpha=0.6) # 绘制中心点 plt.scatter(centers[:,0], centers[:,1], marker='x', s=200, c='k', linewidths=3) plt.title(f'K-Means 第 {step} 步') plt.grid(True) plt.show()

典型输出效果:

  1. 初始随机中心点
  2. 第一次聚类结果
  3. 中心点更新后状态
  4. 最终收敛状态

2.2 动态迭代动画

使用 Matplotlib 的FuncAnimation实现流畅的迭代过程演示:

from matplotlib.animation import FuncAnimation class KMeansAnimator: def __init__(self, data, k=4): self.data = data self.k = k self.fig, self.ax = plt.subplots(figsize=(10, 6)) self.colors = plt.cm.rainbow(np.linspace(0, 1, k)) # 初始化中心点 self.centers = data[np.random.choice(len(data), k, replace=False)] self.assignments = np.zeros(len(data)) def update(self, frame): self.ax.clear() # 分配点到最近中心 distances = np.sqrt(((self.data - self.centers[:, np.newaxis])**2).sum(axis=2)) self.assignments = np.argmin(distances, axis=0) # 绘制聚类结果 for i in range(self.k): cluster_data = self.data[self.assignments == i] self.ax.scatter(cluster_data[:,0], cluster_data[:,1], color=self.colors[i], s=50, alpha=0.6) self.ax.scatter(self.centers[i,0], self.centers[i,1], marker='x', s=200, c='k', linewidths=3) # 更新中心点位置 new_centers = np.array([self.data[self.assignments == i].mean(axis=0) for i in range(self.k)]) # 绘制中心点移动轨迹 for i in range(self.k): self.ax.plot([self.centers[i,0], new_centers[i,0]], [self.centers[i,1], new_centers[i,1]], 'k--', alpha=0.3) self.centers = new_centers self.ax.set_title(f'K-Means 迭代 {frame+1}') return self.ax # 使用示例 data = load_data('test.txt') animator = KMeansAnimator(data) animation = FuncAnimation(animator.fig, animator.update, frames=10, interval=1000) plt.show()

2.3 中心点轨迹图

这种可视化专注于展示中心点的移动路径,揭示算法收敛过程:

def plot_centroid_path(data, k=4, max_iter=10): centers_history = [] centers = data[np.random.choice(len(data), k, replace=False)] centers_history.append(centers.copy()) for _ in range(max_iter): # 分配点到最近中心 distances = np.sqrt(((data - centers[:, np.newaxis])**2).sum(axis=2)) assignments = np.argmin(distances, axis=0) # 更新中心点 new_centers = np.array([data[assignments == i].mean(axis=0) for i in range(k)]) centers_history.append(new_centers.copy()) centers = new_centers # 绘制轨迹 plt.figure(figsize=(10, 6)) colors = plt.cm.rainbow(np.linspace(0, 1, k)) for i in range(k): path = np.array([step[i] for step in centers_history]) plt.plot(path[:,0], path[:,1], 'o-', c=colors[i], markersize=8, linewidth=2, label=f'中心点 {i+1}') plt.scatter(data[:,0], data[:,1], c='gray', s=30, alpha=0.3) plt.title('K-Means 中心点移动轨迹') plt.legend() plt.grid(True) plt.show()

3. 完整动画代码实现

下面是一个可直接运行的完整 K-Means 动画实现,包含交互式控件:

import numpy as np import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation from matplotlib.widgets import Slider, Button class InteractiveKMeans: def __init__(self, data, k=4): self.data = data self.k = k self.fig, self.ax = plt.subplots(figsize=(10, 7)) plt.subplots_adjust(bottom=0.25) # 初始化参数 self.centers = data[np.random.choice(len(data), k, replace=False)] self.assignments = np.zeros(len(data)) self.colors = plt.cm.tab10(np.linspace(0, 1, k)) # 创建控件 ax_iter = plt.axes([0.2, 0.1, 0.6, 0.03]) self.slider = Slider(ax_iter, '迭代次数', 1, 20, valinit=1, valstep=1) ax_reset = plt.axes([0.8, 0.025, 0.1, 0.04]) self.reset_btn = Button(ax_reset, '重置', color='lightgoldenrodyellow') # 绑定事件 self.slider.on_changed(self.update) self.reset_btn.on_clicked(self.reset) self.animation = FuncAnimation(self.fig, self.animate, frames=20, interval=500, repeat_delay=2000) def reset(self, event): self.slider.reset() self.centers = self.data[np.random.choice(len(self.data), self.k, replace=False)] self.update(0) def update(self, val): iterations = int(self.slider.val) self.centers = self.data[np.random.choice(len(self.data), self.k, replace=False)] for _ in range(iterations): distances = np.sqrt(((self.data - self.centers[:, np.newaxis])**2).sum(axis=2)) self.assignments = np.argmin(distances, axis=0) self.centers = np.array([self.data[self.assignments == i].mean(axis=0) for i in range(self.k)]) self.draw_clusters() def animate(self, frame): distances = np.sqrt(((self.data - self.centers[:, np.newaxis])**2).sum(axis=2)) self.assignments = np.argmin(distances, axis=0) self.centers = np.array([self.data[self.assignments == i].mean(axis=0) for i in range(self.k)]) self.draw_clusters() return self.ax def draw_clusters(self): self.ax.clear() for i in range(self.k): cluster_data = self.data[self.assignments == i] self.ax.scatter(cluster_data[:,0], cluster_data[:,1], color=self.colors[i], s=50, alpha=0.6) self.ax.scatter(self.centers[i,0], self.centers[i,1], marker='x', s=200, c='k', linewidths=3) self.ax.set_title(f'K-Means 聚类 (k={self.k})') self.ax.grid(True) def show(self): plt.show() # 使用示例 data = load_data('test.txt') visualizer = InteractiveKMeans(data, k=4) visualizer.show()

4. 可视化方案对比与选型

三种方案各有优劣,下面是详细对比:

方案类型优点缺点适用场景
静态分步图制作简单,步骤清晰缺乏连续性,需要手动切换教学演示、文档说明
动态迭代动画直观展示迭代过程,视觉效果好实现较复杂,性能开销大现场演示、视频教程
中心点轨迹图突出算法收敛特性丢失了数据点分配细节算法分析、参数调优

在实际项目中,我通常会根据需求组合使用这些技术。例如,用静态图解释算法原理,用动画展示实际运行过程,最后用轨迹图分析算法收敛情况。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/13 11:28:37

正交补空间 vs 直和补:从唯一性看2种补空间的3个核心差异

正交补空间与直和补空间的本质差异:唯一性视角下的三维解析当我们第一次接触线性代数中的子空间概念时,补空间往往是最令人困惑的部分之一。特别是当教材同时引入"正交补空间"和"直和补空间"这两个相似却本质不同的概念时&#xff0…

作者头像 李华
网站建设 2026/7/13 11:28:06

STM32与TB6593FNG的直流电机控制方案设计

1. 硬件选型与系统架构设计 在直流电机控制系统中,TB6593FNG驱动芯片与STM32L031C6微控制器的组合堪称黄金搭档。这套方案特别适合对功耗敏感的中小型直流电机应用场景,如便携医疗设备、智能家居执行器和微型机器人等。 TB6593FNG采用HSSOP-24封装&…

作者头像 李华
网站建设 2026/7/13 11:26:12

电流采样电阻 0.1%精度选型:高边/低边检测 3 种场景误差对比分析

电流采样电阻0.1%精度选型:高边/低边检测3种场景误差对比分析在电源管理、电机驱动和BMS系统设计中,电流采样精度直接影响系统性能和可靠性。当采样电阻精度要求达到0.1%级别时,工程师面临的核心挑战已不仅是电阻本体的选择——高边与低边检测…

作者头像 李华
网站建设 2026/7/13 11:25:44

直流负载管理优化与PIC18F87J11智能控制实践

1. 直流负载管理的核心挑战与优化方向 在工业自动化和电力电子系统中,直流负载管理一直是个棘手问题。我曾在某自动化产线改造项目中,亲眼目睹传统机械继电器在切换大电流直流负载时产生的电弧烧蚀触点,导致系统平均无故障时间(MT…

作者头像 李华