机器学习——聚类之K-means(未完)

这是我看下来,最简单的内容,哭了,K-means,so nice

K-means,由于太过简单,不需要数学推导时,一时间甚至无从下指

首先,K-means需要提前锚定几个点,然后让所有数据样本根据与这几个点的距离,将分别选择最短距离凑成一簇

有那么点近水楼台先得月,兔子硬吃窝边草的意思

然后所有样本分别站队分组后,每个组再重新选出新的锚定点:计算出所有特征各自的均值,作为新锚定点

重复分组与计算新锚点,直到最终所有组的锚点不再改变,或是超过最大迭代次数。

  1. 确定初始锚点
  2. 数据样本分组
  3. 计算各组新锚点
  4. 重复2和3步,直到达标

但非常关键的是,如何确定初始锚点?以及,需要几个初始锚点?

需要几个初始锚点: 这个其实不好说,在scikit-learn里,默认是8个,但要想获得更好的聚类效果,一般可以调试选择最终表现较好的锚点数 N p o i n t N_{point} Npoint

如何确定初始锚点: 可以随机,但是有一个优化选择初始锚点的方式,一般被称为K-means++

K-means++:也是先确定了锚点数 N p o i n t N_{point} Npoint,然后,

  1. 首先随机选取一个锚点,此时,所有样本都归于当前锚点
  2. 计算出所有样本到锚点的距离,选择距锚点最远的样本点,作为新的锚点,
  3. 计算出所有样本到新锚点的距离,如果到新锚点距离更短,则分到新锚点组
  4. 然后再次分别计算所有样本到各自锚点的距离,选择各组中距离锚点最远的点,作为新锚点,(注意:如果已经有多个锚点,也是依次遍历多个锚点,生成新锚点)
  5. 依次循环234步,直到得到 N p o i n t N_{point} Npoint个锚点

K-means++,仅仅是获取 N p o i n t N_{point} Npoint个新锚点,还要重新开始进行聚类,即

1. 确定初始锚点
①. 首先随机选取一个锚点,此时,所有样本都归于当前锚点
②. 计算出所有样本到锚点的距离,选择距锚点最远的样本点,作为新的锚点,
③. 计算出所有样本到新锚点的距离,如果到新锚点距离更短,则分到新锚点组
④. 然后再次分别计算所有样本到各自锚点的距离,选择各组中距离锚点最远的点,作为新锚点,(注意:如果已经有多个锚点,也是依次遍历多个锚点,生成新锚点)
⑤. 依次循环234步,直到得到 N p o i n t N_{point} Npoint个锚点

2. 数据样本分组
3. 计算各组新锚点
4. 重复2和3步,直到达标

步骤很清晰,思路很明确,下笔如有神!开敲键盘~

程序设计

数据结构

考虑到每个簇,有各自的锚点,还有分组的点,并且都有一样的计算距离的方式
用字典或是创建一个类的对象来存储各个簇(组)的数据,也是可以的

但考虑到,样本要同时与每个锚点计算并比较距离,如果是用对象的话呢,不太好在类之外进行比较

因此,不如直接用字典存储,然后在外边定义一个计算距离的方法,直接在外边进行比较,会更方便吧

那就是,一个字典,包含了多个组别,每个组别都有各自的锚点、分组数据、组均方误差

字典 = {
		"组1":[xxxx],
		"组2":[xxxx]
		# .......[xxxx]表示对应的锚点..........
}

但在对每个样本进行分类时,遇到点小麻烦,有两个思路:
思路一:

  • 维护一张所有样本与所有组锚点距离的dataframe表,每次都计算出所有样本与新锚点的距离
  • 再给每个样本获取距离最小的对应锚点,并添加一个新列class,这个新列存的是每个样本的组别名
  • 再对组别名新列,进行分组聚合,也就是每个组都割裂开各自的数据(这里要注意,新列里的组别名要跟字典的组名保持一致)
  • 将割裂开的数据,依次计算各特征的均值作为新锚点,并对比旧锚点是否有改变
  • 判断是否需要再迭代:是否超迭代次数或锚点是否无改变?
  • 如果需要再迭代,那就继续循环,否则停止迭代,输出最终的分组锚点及数据

思路二:

  • 所有锚点都存在一个列表里
  • 对一条数据,计算各样本与新锚点的距离,并存入一个新列表里。
  • 获取列表中距离最小的下标值,并获取到对应的锚点
  • 用pandas里的apply函数,对所有样本数据,进行相同的操作,最终得到每个样本的锚点
    如果是每个样本都单独去计算距离,再进行比较
    。。。。啊算了,思路一就挺好的,思路二还有些小问题。。。。

啊,明天再说,今晚没心思敲键盘了。。。

你可能感兴趣的:(机器学习基础,统计学习,算法,机器学习,聚类,kmeans)