当前位置: 首页 > ai >正文

吴恩达强化学习复盘(2)K-Means初始化|K的选择|算法优化

K-Means初始化

K-Means 算法的第一步是随机选择位置作为初始聚类中心(new one through newk),但如何进行随机猜测是需要探讨的问题。一般需要多次尝试初始猜测,以期望找到更好的聚类结果。

K 值选择及初始聚类中心选取方法

  • K 值选择原则:运行 K-Means 算法时,通常应选择类的数量 K 小于训练示例数量 M。因为若 K 大于 M,将没有足够的训练样本保证每个类中心至少有一个训练样本。例如之前的例子中 K 等于 2,M 等于 30。
  • 初始聚类中心选取:最常用的选择聚类中心的方法是从训练样例中随机选取 K 个训练样本,将这些样本的位置作为初始聚类中心。如在一个训练集中随机选两个样本,分别设置为两个类的中心(假设 K = 2)。之前视频中采用的随机点初始化类中心的方法与这里不同,这里介绍的从训练样本中选取的方法更为常用。

随机初始化对聚类结果的影响

不同的随机初始化可能导致不同的聚类结果。在一个有三个簇的数据集示例中,一种随机初始化可能得到较好的聚类结果,将数据很好地聚成三个不同的簇;但另一种初始化可能导致较差的结果,陷入局部最优。例如,若在某组点中初始化两个类中心,在另一组点中初始化一个类中心,运行 K-Means 后得到的聚类效果不佳,此时算法试图最小化的畸变函数(成本函数 J)陷入了局部最小值。不同的随机初始化还可能产生其他不理想的局部最优聚类情况。

多次随机初始化优化策略

  • 策略原理:为了增加找到全局最优或更好局部最优的机会,可以多次运行 K-Means 算法,每次使用不同的随机初始化。例如运行三次 K-Means 算法得到三个不同的聚类结果,通过计算这三个结果对应的成本函数 J,选择成本函数 J 最小的那个聚类结果,因为该结果中聚类中心到对应类中样本的距离平方和相对较小,即畸变最小。
  • 具体算法步骤:若要进行 100 次随机初始化,需按如下步骤操作。首先,使用从训练样本中选取 K 个样本作为初始聚类中心的方法,进行 100 次随机初始化;然后,基于每次的随机初始化运行 K-Means 算法直至收敛,得到相应的类分配和聚类中心;最后,计算每次运行得到的结果的成本函数,选择成本最低的那组聚类结果作为最终结果。
  • 运行次数建议:实际应用中,运行次数通常在 50 到 1000 次之间。运行次数超过 1000 次计算成本会过高,且收益递减;而尝试至少 50 或 100 次随机初始化,往往能比仅进行一次随机初始化获得更好的结果,更有可能避免陷入较差的局部最小值,找到更好的聚类效果。作者在使用 K-Means 算法时,几乎总是采用多个随机初始化的方法,因为这样能更好地最小化畸变成本函数,为聚类找到更好的聚类中心选择。

K值的选择

K 值选择的模糊性

K-Means 算法需要输入一个参数 K,即期望找到的类(簇)的数量。然而,在很多聚类问题中,确定合适的 K 值是比较困难的,因为对于同一个数据集,不同的人可能会认为存在不同数量的类,且都有其合理性。这是因为聚类属于无监督学习算法,没有特定的标签作为正确答案来指导聚类,数据本身也往往无法明确指示其中包含的类的数量。例如,对于某一数据集,很难确定它是包含两个、四个还是三个簇。

选择 K 值的方法 —— 肘部法

  • 方法原理:学术文献中有一些自动选择聚类数的技术,其中一种常见的方法是肘部法(elbow method)。该方法通过使用不同的 K 值运行 K-Means 算法,然后绘制畸变函数(成本函数 J)关于簇数 K 的函数曲线。当簇数较少(如只有一个簇)时,成本函数 J 的畸变值较高,随着簇数增加,畸变值会下降。
  • 判断依据:肘部法的核心是观察曲线是否存在一个 “肘部”,即曲线在某点之前下降速度较快,之后下降速度变慢。如果出现这样的 “肘部”,则可以选择 “肘部” 对应的 K 值作为合适的聚类数。例如,若曲线显示在达到三个聚类之前,成本函数下降迅速,之后下降变缓,那么可以选择 K = 3。但作者个人很少使用这种方法,因为在许多应用中,成本函数曲线往往是平滑递减的,没有明显的 “肘部”。

错误的 K 值选择方法

选择 K 值以最小化成本函数 J 不是一个可行的方法。因为增加类的数量几乎总是会使成本函数 J 降低,这样会导致几乎总是选择最大可能的 K 值,无法得到有意义的聚类结果。

实际应用中 K 值的选择

  • 依据下游目的选择:在实际应用中,通常是为了实现某个后续或下游的目的而运行 K-Means 算法进行聚类。因此,建议根据 K-Means 算法在实现该下游目的时的表现来评估和选择 K 值。
  • T 恤尺寸示例:以 T 恤尺寸为例,在数据集上运行 K-Means 算法可以找到不同数量的簇,如三个簇可对应小、中、大三种 T 恤尺码,五个簇可对应特小、小、中、特大、大等尺码。选择三个簇还是五个簇,需要综合考虑 T 恤业务中的各种因素,如 T 恤的合身程度(更多尺码可能使合身度更好)和制造与运输成本(制造和运输更多种类的 T 恤成本更高)。通过运行 K-Means 算法得到不同 K 值(如 K = 3 和 K = 5)的聚类结果,权衡这些因素来决定对 T 恤业务最有意义的 K 值。
  • 图像压缩应用:在程序练习中,K-Means 算法可应用于图像压缩。在这种应用中,存在压缩图像质量(图像看起来的好坏程度)和压缩程度(图像大小)之间的权衡。可以根据这种权衡,手动决定基于期望的图像质量和压缩大小的最佳 K 值。

成本函数的优化

监督学习算法提出一个成本函数,然后使用梯度下降法(Greater Descent)或其他方法来优化该成本函数。作为非监督算法的K-Means 同样在优化一个特定的成本函数,尽管其优化算法不是梯度下降法。K-Means 算法的核心目标是最小化样本点到其所属聚类中心的距离平方和,这个距离平方和也就是畸变函数(distortion function),它是 K-Means 算法的优化目标。

优化公式的定义

假设我们有 m 个样本 \{x^{(1)}, x^{(2)}, \cdots, x^{(m)}\},每个样本 x^{(i)} 是一个 n 维向量,要将这些样本划分为 K 个聚类。用 c^{(i)} 表示样本 x^{(i)}所属的聚类编号(1 \leq c^{(i)} \leq K),\mu_k表示第 k 个聚类的中心(也是一个 n 维向量)。那么,K-Means 算法的优化目标就是最小化畸变函数 J,其公式如下:


J(c, \mu) = \frac{1}{m} \sum_{i=1}^{m} \left\| x^{(i)} - \mu_{c^{(i)}} \right\|^2

其中:

  • \left\| x^{(i)} - \mu_{c^{(i)}} \right\|^2 表示样本 x^{(i)} 到其所属聚类中心\mu_{c^{(i)}} 的欧氏距离的平方。
  • \sum_{i=1}^{m} \left\| x^{(i)} - \mu_{c^{(i)}} \right\|^2 是所有样本到其所属聚类中心的距离平方和。
  • \frac{1}{m} 是为了取平均值,使得畸变函数的值与样本数量无关,便于比较不同数据集上的聚类效果。

优化步骤

K-Means 算法通过迭代的方式来逐步优化畸变函数 J,主要分为两个步骤:

分配步骤(Assignment Step)

固定聚类中心 \mu_1, \mu_2, \cdots, \mu_K,更新每个样本的所属聚类 c^{(i)},使得畸变函数 J 最小化。具体来说,对于每个样本 x^{(i)},将其分配到距离最近的聚类中心所属的聚类中,即:


c^{(i)} = \arg\min_{k} \left\| x^{(i)} - \mu_k \right\|^2

其中,\arg\min_{k} 表示使得后面的表达式取得最小值的 k 值。

更新步骤(Update Step)

固定每个样本的所属聚类 c^{(1)}, c^{(2)}, \cdots, c^{(m)},更新每个聚类的中心 \mu_k,使得畸变函数 J 最小化。具体来说,对于每个聚类 k,将其中心更新为该聚类中所有样本的均值,即:


\mu_k = \frac{\sum_{i: c^{(i)} = k} x^{(i)}}{\left| \{ i: c^{(i)} = k \} \right|}

其中,\sum_{i: c^{(i)} = k} x^{(i)} 表示所有属于聚类 k 的样本的总和,\left| \{ i: c^{(i)} = k \} \right| 表示属于聚类 k 的样本数量。

Python 代码示例

下面是一个简单的 Python 代码示例,用于更直观解释 K-Means 算法并优化畸变函数

import numpy as npdef kmeans(X, K, max_iterations=100):# 随机初始化聚类中心indices = np.random.choice(len(X), K, replace=False)centroids = X[indices]for _ in range(max_iterations):# 分配步骤distances = np.array([np.linalg.norm(X - centroid, axis=1) for centroid in centroids])labels = np.argmin(distances, axis=0)# 更新步骤new_centroids = np.array([X[labels == k].mean(axis=0) for k in range(K)])# 判断是否收敛if np.allclose(centroids, new_centroids):breakcentroids = new_centroidsreturn labels, centroids# 示例数据
X = np.array([[1, 2], [1, 4], [1, 0], [4, 2], [4, 4], [4, 0]])
K = 2# 运行K-Means算法
labels, centroids = kmeans(X, K)
print("聚类标签:", labels)
print("聚类中心:", centroids)    

    http://www.xdnf.cn/news/330.html

    相关文章:

  • 基于模板匹配的信用卡号码识别系统
  • Fastdata极数:全球AR/VR行业发展趋势报告2025
  • C#.net core部署IIS
  • 【愚公系列】《Python网络爬虫从入门到精通》056-Scrapy_Redis分布式爬虫(Scrapy-Redis 模块)
  • ai学习中收藏网址【1】
  • Nginx 文件上传大小限制及 `client_max_body_size` 最大值详解
  • C++ 基于多设计模式下的同步异步⽇志系统-1准备工作
  • 数据库表设计
  • C 语 言 --- 指 针 4(习 题)
  • 【java实现+4种变体完整例子】排序算法中【选择排序】的详细解析,包含基础实现、常见变体的完整代码示例,以及各变体的对比表格
  • 企业网站安装 SSL安装的必要性
  • Nvidia显卡架构演进
  • Shiro-550 动调分析与密钥正确性判断
  • PHP中的ReflectionClass讲解【详细版】
  • Git 版本控制工具
  • 每天五分钟深度学习PyTorch:0填充函数在搭建神经网络中的应用
  • Spring Boot 中基于 Reactor 的服务器端事件(SSE)推送机制实践
  • 成人大学报考-助你跨越信息鸿沟
  • Charles破解 激活码 Java
  • 美信监控易告警:功能强大
  • 变压器运输如何避免冲击损坏? 宏集ASPION G-Log2 冲击记录仪实测解析
  • C++指针(二)
  • python_level1.2
  • 使用Jasypt对配置文件内容加密
  • 布隆过滤器如何删除数据
  • C++ (菱形继承,通用接口 ,多态介绍)
  • vxe-Table 行数据过多导致列隐藏展示卡顿问题解决方案
  • C++ 20 信号量详解
  • “图生生”商品图优化升级,多元素组合效果更优!
  • 2025,常见的AI编程工具有哪些?