该系列文章为, 观看 "吴恩达机器学习" 系列视频的学习笔记. 虽然每个视频都很简单, 但不得不说每一句都非常的简洁扼要, 浅显易懂. 非常适合我这样的小白入门.
本章含盖
14.1 无监督学习
14.2 K-Means 算法
14.3 优化目标
14.4 随机初始化
14.5 选取聚类数量
14.1 无监督学习
聚类算法(非监督学习算法). 我们将要让计算机学习无标签数据, 而不是此前的标签数据.
在一个典型的监督学习中, 我们有一个有标签的训练集, 我们的目标是找到能够区分正样本和负样本的决策边界, 在这里的监督学习中, 我们有一系列标签, 我们需要据此拟合一个假设函数. 与此不同的是, 在非监督学习中, 我们的数据没有附带任何标签, 我们拿到的数据就是这样的:
在这里我们有一系列点, 却没有标签. 因此, 我们的训练集可以写成只有 x(1),x(2)..... 一直到 x^(m). 我们没有任何标签 y. 因此, 图上画的这些点没有标签信息.
也就是说, 在非监督学习中, 我们需要将一系列无标签的训练数据, 输入到一个算法中, 然后我们告诉这个算法, 快去为我们找找这个数据的内在结构. 我们可能需要某种算法帮助我们寻找一种结构.
图上的数据看起来可以分成两个分开的点集(称为簇), 一个能够找到我圈出的这些点集的算法, 就被称为聚类算法.
当然, 此后我们还将提到其他类型的非监督学习算法, 它们可以为我们找到其他类型的结构或者其他的一些模式, 而不只是簇.
聚类算法的用途:
在这门课程的早些时候, 我曾经列举过一些应用:
比如市场分割. 也许你在数据库中存储了许多客户的信息, 而你希望将他们分成不同的客户群, 这样你可以对不同类型的客户分别销售产品或者分别提供更适合的服务.
社交网络分析: 事实上有许多研究人员正在研究这样一些内容, 他们关注一群人, 关注社交网络, 例如 Facebook,Google+, 或者是其他的一些信息, 比如说: 你经常跟哪些人联系, 而这些人又经常给哪些人发邮件, 由此找到关系密切的人群. 因此, 这可能需要另一个聚类算法, 你希望用它发现社交网络中关系密切的朋友.
我有一个朋友正在研究这个问题, 他希望使用聚类算法来更好的组织计算机集群, 或者更好的管理数据中心. 因为如果你知道数据中心中哪些计算机经常协作工作. 那么, 你可以重新分配资源, 重新布局网络. 由此优化数据中心, 优化数据通信.
最后, 我实际上还在研究如何利用聚类算法了解星系的形成. 然后用这个知识, 了解一些天文学上的细节问题. 好的, 这就是聚类算法. 这将是我们介绍的第一个非监督学习算法. 在下一个视频中, 我们将开始介绍一个具体的聚类算法.
14.2 K-Means 算法
K - 均值是最普及的聚类算法, 算法接受一个未标记的数据集, 然后将数据聚类成不同的组.
K-Means 算法:
假设我们有一个无标签的数据集, 我想将其分为两蔟
现在, 我执行 K-Means 算法, 具体操作如下:
1, 第一步随机生成两点. 这两点就叫做聚类中心
K - 均值是一个迭代算法, 它会做两件事:
1 蔟分配;2 移动聚类中心
K - 均值是一个迭代算法, 假设我们想要将数据聚类成 n 个组, 其方法为:
1, 首先选择 K 个随机的点, 称为聚类中心(cluster centroids);
2, 对于数据集中的每一个数据, 按照距离 K 个中心点的距离, 将其与距离最近的中心点关联起来, 与同一个中心点关联的所有点聚成一类.
如:
第一次迭代
第二次迭代:(注意, 相对于 第一次迭代 有的点的颜色已经变了)
3, 计算每一个组的平均值, 将该组所关联的中心点移动到平均值的位置.
如:(注意, 聚类中心 相对于 第二步 已经改变位置了)
第一次迭代:
第二次迭代:
重复步骤 2-4 直至中心点不再变化.
K-Means 算法的输入:
1,K(簇类个数)
2, 一系列无标签的数据集
同时, 在非监督学习的 K-Means 算法中, 我们约定 x^(i) 是一个 n 维实数向量. 也就是我的训练样本是 n 维向量, 而不是 n+1 维, 去除了 x_0
用μ^1 ,μ^2 ,...,μ^k 来表示聚类中心, 用 c^(1) ,c^(2) ,...,c^(i) ,...,c^(m) 来存储与第 i 个实例数据最近的聚类中心的索引, K - 均值算法的伪代码如下:
算法分为两个步骤,
1 蔟分配
第一个 for 循环是赋值步骤, 即: 对于每一个样例 i, 计算其应该属于的类.
寻找最小值的 k, 我们习惯用 距离的平方 表示(这是一个约定的惯例).
2 移动聚类中心
第二个 for 循环是聚类中心的移动, 即: 对于每一个类 K, 重新计算该类的质心.
一个问题: 假设 u_k 是某个簇的均值. 那么, 如果存在一个没有点的聚类中心, 会怎么样?(这种情况确实存在, 但实际情况中很少见)
这时, 最常见的做法就是, 直接移除那个聚类中心. 但是, 如果你这么做, 你最终会得到 K-1 个簇, 而不是 K 个簇.
有时, 你确实需要有 K 个簇. 这时, 你就可以随机重新初始化这个聚类中心.
但是, 通常情况下最常见的做法是, 直接移除这个没有点的聚类中心.
K-Means 算法的另一个常见应用:
它可以用来解决分离不佳的簇的问题. 如, 右图看起来并不能很好地分成几个簇. 虽然这些数据不像我们刚才的能够明确的分成 3 簇, 但 K-Means 算法还是能够将这些数据分为几个簇.
即, K - 均值算法也可以很便利地用于将数据分为许多不同组, 即使在没有非常明显区分的组群的情况下也可以.
上图所示的数据集包含身高和体重两项特征构成的, 利用 K - 均值算法将数据分为三类, 用于帮助确定将要生产的 T - 恤衫的三种尺寸, 即 S,M,L 三个型号的衣服的尺寸应该是多大.
14.3 优化目标
K-Means 优化目标函数 有两个目的:
1 可以对学习算法进行调试, 确保 K-Means 算法运行正确
2 运用'K-Means 优化目标函数'帮助 K-Means 算法找到更好的簇, 并避免局部最优解
btw, 在运行 K-Means 算法时, 我们将会对两组变量进行跟踪: c^(i) 和 u^k.
K(大写): 表示簇的数量
k(小写): 聚类中心的下标
K-Means 算法的优化目标:
『‖x^(i) - u_( c^(i) )‖^2』: 每个样本 x^(i) 到 x^(i) 所属的聚类中心的距离的平方值.
这个代价函数有时候也叫做 "失真代价函数" 或者叫做 "K-Means 算法的失真".
簇分配步骤, 实际上就是在最小化代价函数 J(c(1),c(2),...,c(m)). 我们要保持最近的聚类心中, 也就是 u1,u2,...,u^k 的位置固定不变.
所以, 第一步要做的不是改变聚类中心的位置, 而是要去选出 c(1),c(2)到 c(m), 来最小化这个代价函数.(即, 第一步的前提是 u1,u2,...,u^k 是固定不变的)
移动聚类中心步骤, 选择 u 值, 来最小化 J(u(1),u(2),...,u^(k)).
ps:wrt 是 cost 的缩写
所以, K-Means 算法做的实际就是, 它把这两个系列的变量, 把它们分成两半. 第一组是变量 c, 第二组是变量 u. 首先, 它会最小化 J 关于变量 c, 接着最小化 J 关于变量 u. 然后保持迭代
这就是 K-Means 算法所做的. 现在我们了解了 K-Means 算法. 现在来最小化代价函数 J. 我们还能用这个算法来调试我们的学习算法, 确保我们实现的 K 均指算法能够正确运行.
14.4 随机初始化
如何初始化 K-Means 算法的聚类中心, 以及讨论如何使算法避开局部最优
有几个不同的方法可以用来随机初始化聚类中心. 但事实证明, 有一种方法比其他大多数可能考虑到的方法更值得推荐.
我们通常是这样初始化聚类中心的:
在运行 K - 均值算法的之前, 我们首先要随机初始化所有的聚类中心点, 下面介绍怎样做:
我们应该选择 K <m, 即聚类中心点的个数要小于所有训练集实例的数量.
如果运行一个 K-Means 算法, 它的聚类中心数大于或等于样本数(即, K>= m), 那会很奇怪.
随机选择 K 个训练实例, 然后令 K 个聚类中心分别与这 K 个训练实例相等(即, 设定 u^1 到 u^k 等于这 K 个样本).
K - 均值的一个问题在于, 它有可能会停留在一个局部最小值处, 而这取决于初始化的情况.
如果你运行 K-Means 算法, 假设它最后得到一个比较好的局部最优. 事实上, 这应该是全局最优:
但是, 如果随机初始化得到的结果不好, 就可能得到不同的局部最优解:
为了解决这个问题, 我们通常需要多次运行 K - 均值算法, 每一次都重新进行随机初始化, 最后再比较多次运行 K - 均值的结果, 选择代价函数最小的结果. 这种方法在较小的时候 (2--10) 还是可行的(特别当 k = 2,3,4 的时候, 效果显著), 但是如果较大, 这么做也可能不会有明显地改善. 但是, 就算你的聚类数目很大. 我在这里介绍的随机初始化方法也能给 K-Means 算法一个合理的起始点, 来找到一个好的聚类结果
典型的循环次数在 50 ~ 1000 之间.
14.5 选取聚类数量
K-Means 算法中如何选择聚类数量? 即, 如何选择参数 K 的值?
说实话, 没有所谓最好的选择聚类数的方法, 通常是需要根据不同的问题, 通过观察可视化试图或者通过观察聚类算法的输出等, 人工地进行选择的. 选择的时候思考我们运用 K - 均值算法聚类的动机是什么, 然后选择能最好服务于该目的标聚类数.
选择聚类数量并不容易, 很大程度上是因为, 通常在数据集中, 有多少个聚类是不清楚的. 比如, 如下的数据集, 有的人认为是 4 个聚类. 即, K = 4
或者有的人认为是 2 个聚类. 即, K = 2
那么观察类似这样的数据集, 真实的聚类数对我来说, 相当的模棱两可. 我并不认为只有一个正确的答案, 这就是无监督学习的一部分, 数据没有标签, 因此并不总是有一个明确的答案. 也因为这个原因, 用一个自动化的算法, 来选择聚类数目是很困难的
当人们在讨论, 选择聚类数目的方法时, 有一个可能会谈及的方法叫作 "肘部法则". 关于 "肘部法则", 我们所需要做的是改变 K 值, 也就是聚类类别数目的总数. 我们用 K= 1 来运行 K 均值聚类方法. 这就意味着, 所有的数据都会分到一个聚类里, 然后计算代价目标函数或者计算畸变函数 J,K 代表聚类数目. 然后在计算 K=2 时 K-Means 算法(此时, 可能多次随机初始化 K 值), 计算得到代价函数 J, 依次...
我们可能会得到一条类似于这样的曲线. 像一个人的肘部. 这就是 "肘部法则" 所做的, 让我们来看这样一个图, 看起来就好像有一个很清楚的肘在那儿. 好像人的手臂, 如果你伸出你的胳膊, 那么这就是你的肩关节, 肘关节, 手. 这就是 "肘部法则". 你会发现这种模式, 它的畸变值会迅速下降, 从 1 到 2, 从 2 到 3 之后, 你会在 3 的时候达到一个肘点. 在此之后, 畸变值就下降的非常慢, 看起来就像使用 3 个聚类来进行聚类是正确的, 这是因为那个点是曲线的肘点, 畸变值下降得很快, K=3 之后就下降得很慢, 那么我们就选 K=3.
当你应用 "肘部法则" 的时候, 如果你得到了一个像上面这样的图, 那么这将是一种用来选择聚类个数的合理方法.
而事实证明 "肘部法则" 并不那么常用. 原因之一是, 在实际运用到聚类问题上时, 往往最后你会得到一条看上去相当模糊的曲线, 也许像这样
如果, 观察这张图, 我不知道, 也许没有一个清晰的拐点, 看上去畸变值是连续下降的. 那么, 如果在实际操作中. 如果你的图看起来像前面那张, 那么就太好了, 它会给你一个清晰的答案. 但是很多时候, 你最终你得到的图像是像这样的, 并不能准确确定拐点合适的位置. 这种情况下, 用这个方法来选择聚类数目是很困难的.
对于 "肘部法则" 快速的小结: 它是一个值得尝试的方法, 但是我觉得, 你不能期望它能够解决任何问题.
最后, 还有另外一种, 选择 K 值的思路:
通常人们使用 K-Means 值聚类是为了, 得到一些聚类用于后面的目的, 或者说是下游目的. 也许你想用 K 均值 聚类来做市场分割, 等等... 如果后续目标的能给你一个评估标准, 那么决定聚类的数量更好的方式是, 看哪个聚类数量能更好地应用于后续目的.
具体的例子: T 恤尺寸的例子
我要决定我是否需要 3 种 T 恤尺寸, 因此我选择 K=3(S,M,L); 或者我可以选择 K=5 (XS,S,M,L,XL).
具体而言, 你可以从 T 恤商业的角度去思考, 哪一种能够更好地满足客户的需求, 我们也就能卖出更多的 T 恤. 即, 通过卖出 T 恤的数量能帮助你选择使用 K=3 还是 K=5...
总结一下, 大部分时候. 聚类数量 K 仍然是通过手动, 人工输入, 或者我们的经验来决定. 一种可能的尝试是使用 "肘部原则", 但我不会期望它每次都有效果. 选择聚类数量更好的思路是去问自己, 运用 K - 均值算法聚类的动机是什么, 然后选择能最好服务于该目的标聚类数.
来源: http://www.jianshu.com/p/8c91fd177c00