Fork me on GitHub

scikit-learn聚类---机器学习算法之K-Means算法

1 K-Means

1.1算法原理

  • K是原始数据被聚集为K类,Means就是均值点,K-Means均点。K-Means的核心就是将一堆数据聚集为K个簇,每个簇中都有一个中心点称为均值点。簇中所有点到该簇的均值点的距离都较其他均值点更近。如下图:

1.2文字叙述

  • 确定K值(就是把数据聚为几个类,K值是K-Means算法中唯一的参数)

  • 从原始数据集,随机选取K个点做为初始化均值点的核心

  • 遍历所有数据集的数据,每取出一个数据就和K个均值点分别计算距离(默认计算点间欧式距离),与谁近就归哪个簇。

  • 再对各个簇之间求均值点(就是求该簇中所有点平均值)

  • 比较当前均值点和上一步均值点是否相同,如果相同,则K-Means算法结束。否则将当前均值点替换掉之前均值点,重复步骤3知道所有分配结果不发生变化。或误差小于给定误差。

    C为各个簇,K为簇个数,μ为均值

1.3 停止的条件

  • 聚类中心不再发生变化
  • 所有距离最小
  • 迭代次数达到设定值

1.4 算法优缺点

  • 优点:
    • 原理简单
    • 速度快
    • 对大多数数据集有较好伸缩性
  • 缺点:
    • 需要指定聚类数量
    • 对异常值敏感
    • 对初始值敏感,初始随机选取的K的质心会影响聚类效果

1.5 常用方法和参数设置

  • 法1:直接调用方法cluster.k_means

    import numpy as np
    import sklearn.cluster as cluster
    
  • 法2:调用构造函数cluster.KMeans(推荐)

    import numpy as np
    from sklearn.cluster import KMeans
    
    • 构造cluster.KMeans函数传入参数

      1.n_clusters:聚类数量,类型int,default=8
      2.max_iter:最大迭代次数,类型int,default:300
      3.n_init:选取不通过的种子尝试次数,和max_iter参数的区别,n_init是控制跑10轮,每一轮都初始随机选取n个中心点,max_iter是控制每一轮迭代次数。
      4.init 初始质点选取方式{'k-means++','random'/an ndarray|,defaults to 'k-means++'
      5.algorithm "auto","full" or "elkan",default="auto"
      6.precompute_distances:{'auto':True,False},预先计算距离,默认值是auto
      7.tol:聚类结果收敛的误差,当质心欧氏距离变化小于该值时,停止运算,为了控制MiniBatchKMeans尽早停止,而不是一定要运行max_iter次才停止计算。
      

1.6 关键函数

- fit(self,x,y=None):训练数据,计算K聚类
- predict(self,x): 预测X集合中每个样本归属的簇
- fit_predict(self,x,y=None):返回是self.fit(x).labels_
- transform(self,x,y=None):计算x中每个样本点到聚类中心的欧氏距离
- fit_transform(self,x,y=None):Equivalent to fit(x).transform(s)
- score(self,X,y=None):Opposite of the value of X on the K-Means objective.可能是transform的负数?
- get_params():获取聚类的参数
- set_params(**):重新设置聚类的参数

1.7示例:

  • 示例一:
from sklearn.cluster import KMeans
import numpy as np


data = np.random.rand(100,3)
k = KMeans(n_clusters=3)
k.fit(data)
#聚类中心点的坐标
print(k.cluster_centers_)
#聚类标签
print(k.labels_)
#误差平方和,每个点到聚类中心店的距离之和
print(k.inertia_)
  • 示例2:
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
import random


x = [round(random.uniform(1,100),3) for _ in range(15)]
y = [round(random.uniform(1,100),3) for _ in range(15)]
plt.plot(x,y,'b.')
plt.show()
points = [[i,j] for i,j in zip(x,y)]
y_pred = KMeans(n_clusters=2).fit_predict(points)
#分类后结果
print(y_pred)

plt.scatter(x,y,c=y_pred,marker="*")
plt.show()
  • 分类前:

  • 分类后:

  • 示例三:

    • 进行示例三需要先知道一些知识点。

      sklearn.datasets.make_blobs(n_samples=100, n_features=2, centers=None, cluster_std=1.0, center_box=(-10.0, 10.0), shuffle=True, random_state=None)
      
      #参数解释:
      1.n_samples(int/array):如果参数为int,代表总样本数;如果参数array,数组中每个数代表样本数,默认值100
      2.n_features(int):样本点的维度,默认值2
      3.centers(int):样本中心数。如果样本数为int且centers=None,生成3个样本中心。如果样本数(n_samples)为数组,则centers 要么为None,要么为数组的长度。默认值3
      4.cluster_std(float/sequence of floats):样本中,簇的标准差。默认值1.0
      5.center_box(pair of floats (min, max)):每个簇的上下限。默认值(-10.0, 10.0)
      6.shuffle(boolean):是否将样本打乱。默认值True
      7.random_state(int/RandomState instance /None):指定随机数种子,每个种子生成的序列相同,与minecraft地图种子同理。
      
      #返回类型:
      	X:样本数组[n_sample,n_features]
      	产生的样本
      	y:array of shape[n_sample]
      	每个簇的标签
      	
      #小示例:
      import numpy as np
      import matplotlib.pyplot as plt
      import matplotlib as mpl
      import sklearn.datasets as ds
      #sklearn.datasets.make_blobs(n_samples=100, 
      #                             n_features=2, 
      #                             centers=None, 
      #                             cluster_std=1.0, 
      #                             center_box=(-10.0, 10.0), 
      #                             shuffle=True, 
      #                             random_state=None)
      
      X,y = ds.make_blobs(n_samples=1000,n_features=2,centers=3,random_state=10,cluster_std=1.5)
      print(X)
      print(X.shape)
      #平均值
      print(X.mean())
      #方差
      print(X.var())
      #标准差
      print(X.std())
      y.std()
      
  • 示例3:

    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib as mpl
    import sklearn.datasets as ds
    import matplotlib.colors
    from sklearn.cluster import KMeans#引入kmeans
    
    ## 设置属性防止中文乱码
    mpl.rcParams['font.sans-serif'] = [u'SimHei']
    mpl.rcParams['axes.unicode_minus'] = False
    N = 1500 # 1500个样本
    centers = 4 # 4个聚簇中心点
    data,y = ds.make_blobs(N, n_features=2, centers=centers, random_state=28)
    data2,y2 = ds.make_blobs(N, n_features=2, centers=centers,  random_state=28)
    
    data3 = np.vstack((data[y == 0][:200], data[y == 1][:100],
         data[y == 2][:10], data[y == 3][:50]))
    
    y3 = np.array([0] * 200 + [1] * 100 + [2] * 10 + [3] * 50)
    
    
    #模型构建
    km = KMeans(n_clusters=centers,init="random",random_state=28)
    km.fit(data,y)
    
    y_hat = km.predict(data)
    print ("所有样本距离聚簇中心点的总距离和:", km.inertia_)
    print ("距离聚簇中心点的平均距离:", (km.inertia_ / N))
    cluster_centers = km.cluster_centers_
    print ("聚簇中心点:", cluster_centers)
    
    
    y_hat2 = km.fit_predict(data2)
    y_hat3 = km.fit_predict(data3)
    
    #画图:
    def expandBorder(a, b):
        d = (b - a) * 0.1
        return a-d, b+d
    cm = mpl.colors.ListedColormap(list('rgbmyc'))
    plt.figure(figsize=(15, 9), facecolor='w',dpi=80)
    
    plt.subplot(241)
    plt.scatter(data[:, 0], data[:, 1], c=y, s=30, cmap=cm, edgecolors='none')
    
    x1_min, x2_min = np.min(data, axis=0)
    x1_max, x2_max = np.max(data, axis=0)
    x1_min, x1_max = expandBorder(x1_min, x1_max)
    x2_min, x2_max = expandBorder(x2_min, x2_max)
    plt.xlim((x1_min, x1_max))
    plt.ylim((x2_min, x2_max))
    plt.title(u'原始数据')
    plt.grid(True)
    
    #K-Means算法聚类结果
    plt.subplot(242)
    plt.scatter(data[:, 0], data[:, 1], c=y_hat, s=30, cmap=cm, edgecolors='none')
    plt.xlim((x1_min, x1_max))
    plt.ylim((x2_min, x2_max))
    plt.title(u'K-Means算法聚类结果')
    plt.grid(True)
    
    m = np.array(((1, 1), (0.5, 5)))
    print(m)
    data_r = data.dot(m)
    print(data_r)
    y_r_hat = km.fit_predict(data_r)
    

2 Mini Batch K-Means聚类

  • Mini Batch K-Means算法:是K-Means算法采用小批量的数据子集减少计算时间,同时仍视图优化目标函数,通过随机抽取小批量的数据子集,将随机产生子集进行训练算法,可有效减少计算时间。

  • 该算法通过集中随机抽取一些数据形成小批量,把它们分配给最近的质心,然后更新质心。

  • 与K均值算法相比,数据的更新是在每一个小的样本集上,对于每个小批量,通过计算平均值得到更新质心。并把小批量里的数据分配给质心。随着迭代次数的增加,这些质心变化逐渐减小,知道质心稳定或者达到指定的迭代次数,停止计算。

  • Mini Batch K-Means比K-Means有更快的收敛速度,但同时也降低聚类效果,如下图:

  • 方法参数:

class sklearn.cluster.MiniBatchKMeans(n_clusters=8, 
init=’kmeans++’, 
max_iter=100, 
batch_size=100, verbose=0, 
compute_labels=True, 
random_state=None, 
tol=0.0, 
max_no_improvement=10, 
init_size=None, 
n_init=3, 
reassignment_ratio=0.01)


| 参数                                                         |
| :----------------------------------------------------------- |
| n_clusters : int,optional,默认值:8<br/><br/>要形成的簇数以及要生成的质心数。<br/><br/>init : {'k-means ++','random'或ndarray},默认:'k-means ++'<br/><br/>初始化方法,默认为'k-means ++':<br/><br/>'k-means ++':以智能方式选择初始聚类中心进行k均值聚类,以加速收敛。有关更多详细信息,请参阅k_init中的注释部分。<br/><br/>'random':从初始质心的数据中随机选择k个观测值(行)。<br/><br/>如果传递了ndarray,它应该是形状(n_clusters,n_features)并给出初始中心。<br/><br/>max_iter : int,可选<br/><br/>独立于任何早期停止标准启发式停止之前,完整数据集上的最大迭代次数。<br/><br/>batch_size : int,optional,默认值:100<br/><br/>迷你批次的大小。<br/><br/>verbose : 布尔值,可选<br/><br/>详细模式。<br/><br/>compute_labels : boolean,default = True<br/><br/>一旦小批量优化收敛到适合,计算完整数据集的标签分配和惯性。<br/><br/>random_state : int,RandomState实例或None(默认)<br/><br/>确定质心初始化和随机重新分配的随机数生成。使用int可以使随机性具有确定性。见术语表。<br/><br/>tol : float,默认值:0.0<br/><br/>基于通过平均中心平方位置变化的平滑,方差归一化测量的相对中心变化来控制早期停止。这种早期停止启发式算法更接近于用于算法的批量变体的启发式算法,但在惯性启发式上引入了轻微的计算和内存开销。<br/><br/>要根据标准化的中心变化禁用收敛检测,请将tol设置为0.0(默认值)。<br/><br/>max_no_improvement : int,默认值:10<br/><br/>基于连续数量的微型批次控制早期停止,这些微型批次不会对平滑的惯性产生改善。<br/><br/>要禁用基于惯量的收敛检测,请将max_no_improvement设置为None。<br/><br/>init_size : int,optional,默认值:3 * batch_size<br/><br/>为加速初始化而随机采样的样本数(有时以牺牲精度为代价):通过在数据的随机子集上运行批处理KMeans来初始化唯一的算法。这需要大于n_clusters。<br/><br/>n_init : int,default = 3<br/><br/>尝试的随机初始化数。与KMeans相比,该算法仅运行一次,使用n_init惯性测量的最佳初始化。<br/><br/>reassignment_ratio : float,默认值:0.01<br/><br/>控制要重新分配的中心的最大计数数的分数。较高的值意味着较低的计数中心更容易重新分配,这意味着模型将需要更长的时间来收敛,但应该聚合在更好的聚类中。<br/> |

- 参数说明:

```python
1) n_clusters: 即我们的k值,和KMeans类的n_clusters意义一样。

2)max_iter:最大的迭代次数, 和KMeans类的max_iter意义一样。

3)n_init:用不同的初始化质心运行算法的次数。这里和KMeans类意义稍有不同,
KMeans类里的n_init是用同样的训练集数据来跑不同的初始化质心从而运行算法。
而MiniBatchKMeans类的n_init则是每次用不一样的采样数据集来跑不同的初始化质心运行算法。

4)batch_size:即用来跑Mini Batch KMeans算法的采样集的大小,默认是100.如果发现数据集的类别较多或者噪音点较多,需要增加这个值以达到较好的聚类效果。

5)init: 即初始值选择的方式,和KMeans类的init意义一样。

6)init_size: 用来做质心初始值候选的样本个数,默认是batch_size的3倍,一般用默认值就可以了。

7)reassignment_ratio: 某个类别质心被重新赋值的最大次数比例,
  这个和max_iter一样是为了控制算法运行时间的。这个比例是占样本总数的比例,
  乘以样本总数就得到了每个类别质心可以重新赋值的次数。
  如果取值较高的话算法收敛时间可能会增加,
  尤其是那些暂时拥有样本数较少的质心。默认是0.01。
  如果数据量不是超大的话,比如1w以下,建议使用默认值。如果数据量超过1w,
  类别又比较多,可能需要适当减少这个比例值。具体要根据训练集来决定。

8)max_no_improvement:即连续多少个Mini Batch没有改善聚类效果的话,就停止算法, 和reassignment_ratio, max_iter一样是为了控制算法运行时间的。默认是10.一般用默认值就足够了。
  • 与K-Means对比

     与K-Means算法相比,Mini Batch K-Means中多了一个方法,partial_fit,即可以只用一个batch_size进行训练。其他与K-Means相同。
    
posted @ 2019-12-29 14:52  是阿凯啊  阅读(1114)  评论(0编辑  收藏  举报