K-means算法笔记python3.0

聚类的基本思想

俗话说“物以类聚,人以群分”

聚类--Clustering--是一种无监督学习,简单地说就是把相似的对象归到同一簇中。簇内的对象越相似,聚类的效果越好。

定义:给定一个有个对象的数据集,聚类将数据划分为个簇,而且这个划分满足两个条件:(1)每个簇至少包含一个对象;(2)每个对象属于且仅属于一个簇。

基本思想:对给定的,算法首先给出一个初始的划分方法,以后通过反复迭代的方法改变划分,使得每一次改进之后的划分方案都较前一次更好

K-Means算法

K-Means算法是最为经典的基于划分的聚簇方法,是十大经典数据挖掘算法之一。简单的说K-Means就是在没有任何监督信号的情况下将数据分为K份的一种方法。

聚类算法就是无监督学习中最常见的一种,给定一组数据,需要聚类算法去挖掘数据中的隐含信息。聚类算法的应用很广:顾客行为聚类,google新闻聚类等。

K值是聚类结果中类别的数量。简单的说就是我们希望将数据划分的类别数

算法实现

具体的算法步骤如下:

  1. 随机选择K个中心点
  2. 把每个数据点分配到离它最近的中心点
  3. 重新计算每类中的点到该类中心点距离的平均值
  4. 分配每个数据到它最近的中心点
  5. 重复步骤3和4,直到所有的观测值不再被分配或是达到最大的迭代次数R把10次作为默认迭代次数
  6. 以下代码数据集随机生成
  7.  1 import numpy as np
     2 import matplotlib.pyplot as plt
     3 
     4 # 两点距离
     5 def distance(e1, e2):
     6     return np.sqrt((e1[0]-e2[0])**2+(e1[1]-e2[1])**2)
     7 
     8 # 集合中心
     9 def means(arr):
    10     return np.array([np.mean([e[0] for e in arr]), np.mean([e[1] for e in arr])])
    11 
    12 # arr中距离a最远的元素,用于初始化聚类中心
    13 def farthest(k_arr, arr):
    14     f = [0, 0]
    15     max_d = 0
    16     for e in arr:
    17         d = 0
    18         for i in range(k_arr.__len__()):
    19             d = d + np.sqrt(distance(k_arr[i], e))
    20         if d > max_d:
    21             max_d = d
    22             f = e
    23     return f
    24 
    25 # arr中距离a最近的元素,用于聚类
    26 def closest(a, arr):
    27     c = arr[1]
    28     min_d = distance(a, arr[1])
    29     arr = arr[1:]
    30     for e in arr:
    31         d = distance(a, e)
    32         if d < min_d:
    33             min_d = d
    34             c = e
    35     return c
    36 
    37 
    38 if __name__=="__main__":
    39     ## 生成二维随机坐标(如果有数据集就更好)
    40     arr = np.random.randint(100, size=(100, 1, 2))[:, 0, :]
    41 
    42     ## 初始化聚类中心和聚类容器
    43     m = 5
    44     r = np.random.randint(arr.__len__() - 1)
    45     k_arr = np.array([arr[r]])
    46     cla_arr = [[]]
    47     for i in range(m-1):
    48         k = farthest(k_arr, arr)
    49         k_arr = np.concatenate([k_arr, np.array([k])])
    50         cla_arr.append([])
    51 
    52     ## 迭代聚类
    53     n = 20
    54     cla_temp = cla_arr
    55     for i in range(n):    # 迭代n次
    56         for e in arr:    # 把集合里每一个元素聚到最近的类
    57             ki = 0        # 假定距离第一个中心最近
    58             min_d = distance(e, k_arr[ki])
    59             for j in range(1, k_arr.__len__()):
    60                 if distance(e, k_arr[j]) < min_d:    # 找到更近的聚类中心
    61                     min_d = distance(e, k_arr[j])
    62                     ki = j
    63             cla_temp[ki].append(e)
    64         # 迭代更新聚类中心
    65         for k in range(k_arr.__len__()):
    66             if n - 1 == i:
    67                 break
    68             k_arr[k] = means(cla_temp[k])
    69             cla_temp[k] = []
    70 
    71     ## 可视化展示
    72     col = ['HotPink', 'Aqua', 'Chartreuse', 'yellow', 'LightSalmon']
    73     for i in range(m):
    74         plt.scatter(k_arr[i][0], k_arr[i][1], linewidth=10, color=col[i])
    75         plt.scatter([e[0] for e in cla_temp[i]], [e[1] for e in cla_temp[i]], color=col[i])
    76     plt.show()
     
  8. 训练结果:
  9. K-Means的细节问题
          1. K值怎么定?我怎么知道应该几类?
            答:这个真的没有确定的做法,分几类主要取决于个人的经验与感觉,通常的做法是多尝试几个K值,看分成几类的结果更好解释,更符合分析目的等。或者可以把各种K值算出的SSE做比较,取最小的SSE的K值。

          2. 初始的K个质心怎么选?
            答:最常用的方法是随机选,初始质心的选取对最终聚类结果有影响,因此算法一定要多执行几次,哪个结果更reasonable,就用哪个结果。 当然也有一些优化的方法,第一种是选择彼此距离最远的点,具体来说就是先选第一个点,然后选离第一个点最远的当第二个点,然后选第三个点,第三个点到第一、第二两点的距离之和最小,以此类推。第二种是先根据其他聚类算法(如层次聚类)得到聚类结果,从结果中每个分类选一个点。

          3. K-Means会不会陷入一直选质心的过程,永远停不下来?
            答:不会,有数学证明K-Means一定会收敛,大致思路是利用SSE的概念(也就是误差平方和),即每个点到自身所归属质心的距离的平方和,这个平方和是一个函数,然后能够证明这个函数是可以最终收敛的函数

参考:

https://www.cnblogs.com/nxld/p/6376496.html

https://blog.csdn.net/qq_37509235/article/details/82925781

 

 

 

posted @ 2020-03-23 22:51  daisy99lijing  阅读(278)  评论(1编辑  收藏  举报