一、什么是聚类

所谓聚类,就是将相似的事物聚集在一起,而将不相似的事物划分到不同的类别的过程,例如男人和女人可以进行聚类,分为男类和女类。

在人工智能中,聚类是一种非常重要的方法,那么聚类到底是什么意思呢? 这个概念很简单,我有一个3岁的宝宝(典型的晚婚晚育)。大约在我家宝宝2岁左右,他就能够对生活中的很多相似事物进行聚类了。例如,他能够轻松地将垃圾放到垃圾桶,将乐高归为玩具一类。

我的小宝贝,能够很容易的分出这些事务来,一部分原因,是家长在不断的教他,另外是他已经会学习和总结了,尽管他还不知道这个过程。人工智能也是一个学习和总结的过程哦。

二、聚类的应用

我们以生活中的一些例子来类比,下面一些问题是可以用聚类分析来解决的。

1、信用卡额度聚类分析,可以将信用卡客户用额度来划分,将他们划分为2000,5000,10000,20000,50000,100000等。这样对银行进行风控非常有好处。实际上,金融是使用人工智能最多的地方,李开复老师也经常说人工智能可能最先在金融领域开花结果。

2、城市级别聚类分析,自动聚类哪些是一类城市、二类城市。 虽然我们知道北上广是一线城市,南京 武汉 沈阳 西安 成都等是二线城市,但是这毕竟是从别人嘴里听说的,如果能够通过数据说话,那么肯定更容易使人信服。

三、K均值聚类初始应该有几个类

为了研究方便,我们在二维空间中,研究聚类。如下图 :

这幅图,我们肉眼很容易看出它最适合分为4类,但是计算机却没这么聪明,一眼就看出它有几类。计算机需要使用一些算法,将其分为4类。

下面,我们来分析一下K均值聚类算法:

3.1、确定几个分类

首先第一个问题怎么确定有几个分类,计算机能自动计算出来吗?例如上图,程序怎么知道是分为2类、3类、还是4类、甚至5类呢?我们用人眼很容易看出,但是计算机想分辨是几类却并不容易。

3.2、随机的确定K个类

首先我们根据感觉认为可以有K个分类,这里说的感觉就是计算机随机产生一个数字。这里K可以取大于0的一个整数,当然这个整数不能太大。为什么不能太大呢? 原因是很简单,例如一共只有100个样本,你要让K=101,这显然是错的,怎么能够将100个样本分出101个类呢。 取100,也是不好的,这样会将100个样本分成100个类,那么1个样本1个类,似乎在实际中并没有卵用。

四、K均值伪代码

4.1、为K个类随机的确定中心

1、这K个分类都应该有自己的中心,我们随机的给出K个中心,这K个中心完全是随机的,可以在样本点中随机的取,也可以和样本点一点关系都没有。显然这些随机的中心点都是不正确的,它不是最终各个分类的中心。

下图中的蓝色、红色点,可以表示我们随机取的中心:

4.2、计算每一个样本点到各个中心的距离

2、现在计算每一个样本点,分别离某一个中心的距离,这样每个点可以计算出K个距离,分别表示离K个中心点的距离,这个距离谁小,那么这个样本点就离谁最近,那么就暂时将这个点划分到这个中心点所表示的类。

4.3、确定样本点属于哪一个类

3、所有点经过这样计算后,都能够把它划分到一个类中。

4.4、重新计算分类的中心点。

4、我们第一次得到的中心点是随机生成的。然后重新计算每一个分类的中心点的位置。怎么计算每一个分类的中心点呢? 大多数情况是求样本的各个分量的平均值,我们后面再介绍具体的算法,到时候你会知道,这非常简单。

4.5、迭代计算中心点

5、重新第2步。经过多次迭代,也就是重复执行第2到4步,直到最后几次计算的中心点基本一样,准确的说,就是中心点基本固定在某一个范围类。这在数学上叫做收敛,那么,算法就结束了。

上面的算法重点是,每次迭代都应该计算新的中心,怎么计算新的中心呢?这里使用的方法很简单,就是计算该类的所有样本的平均值。所以,这又叫做K均值聚类

五、K均值聚类(K-Mean)算法

K-means聚类方法算法描述如下:

1
2
3
4
5
6
7
输入:k, data[n];1) 选择k个初始中心点,例如c[0]=data[0],…c[k-1]=data[k-1];2) 对于样本数据data[0]….data[n],分别求与c[0]…c[k-1]之间的距离,
     如果data[0]这个点与c[i]的距离最小,就将该样本的标记为i。
(3) 对于所有标记为i点,重新计算中心点的位置,公式为:
     c[i]={ 所有标记为i的data[j]之和}/标记为i的个数; 
(4) 重复(2)(3),直到所有c[i]值的变化小于给定阈值。
  1. 输入参数k指的是需要分为几个类。data是样本数据,其是一个包含样本数据的数组,当然,也可以是其他数据类型。
  2. 第1步,似乎没有什么可以解释的,就是找到k个中心点,因为中心点可以随机选择,而这里随机选择的前k个点作为中心点。c[i]表示第i类的中心。
  3. 第2步,计算每个点根据与每个分类中心的距离,那个距离最小,那么这个点就先归为哪一类。
  4. 第3步,重新求每个新分类的中心
  5. 第4步,重复求中心,知道最后几次求出的中心基本一致,算法停止,得出的就是最终的分类结果。

该算法的最大优势在于简洁和快速。算法的关键在于初始中心的选择和距离公式。

六、K均值中计算两个点之间的距离

上面的解释,我们还剩下一个怎么求2个样本之间的距离,这个问题了。这里的距离,可以使用欧氏距离来计算。欧式距离就是在欧式空间计算距离,通俗一点说,就是我们小学时候学的使用加减法来求得的点与点之间的距离,如下图:

欧式距离的计算公式如下:

(1)二维平面上两点a(x1,y1)与b(x2,y2)间的欧氏距离:

(2)三维空间两点a(x1,y1,z1)与b(x2,y2,z2)间的欧氏距离:

 

(3)两个n维向量a(x11,x12,…,x1n)与 b(x21,x22,…,x2n)间的欧氏距离:

也可以用表示成向量运算的形式:

至少在一维、二维、三维空间中,欧式距离是很容易理解的,一旦到多维空间中,欧式距离就很难理解了,不过,没关系,我们并不需要了解欧式距离在多维空间中的意义。

七、怎么生成测试聚类方法用的数据

为了让大家理解聚类,我们先在二维空间中做实验。首先,我们生成一些测试数据。可以通过scikit learn中的make_blobs函数来实现。blob有一团一堆的意思,所以make_blobs有生成一大推数据的意思。make_blobs主要用来生成聚类算法的测试数据。

7.1 make_blobs详解

这个函数原型如下:

1
2
def make_blobs(n_samples=100, n_features=2, centers=3, cluster_std=1.0,
               center_box=(-10.0, 10.0), shuffle=True, random_state=None):

下面对几个参数简要解释一下:

n_samples:是待生成的样本的总数。

n_features:是每个样本的特征数,默认是2个特征。

centers:表示有几个中心,也就是希望数据分为几类。

cluster_std:表示每个类别的方差,例如我们希望生成2类数据,其中一类比另一类具有更大的方差,可以将cluster_std设置为[1.0,3.0]。方差越大,表示该类的数据越分散。

center_box:

shuffle:

random_state:

make_blobs返回2个值X,Y,第一个X是一组特征点。 Y是一个数组,表示每个样本属于哪一个分类。

7.2 make_blobs的使用

本节我们使用make_blobs生产了很多样本点,如下图所示:

这些样本点看上去并不随机,肉眼观察是4个聚类,所以,这样的数据还是很适合用来做聚类分析的。生成这些样本点的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# -*- coding: utf8 -*-
 
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets.samples_generator import make_blobs
 
# X为样本特征,Y为样本簇类别,
# 共1000个样本,每个样本4个特征,共4个簇,簇中心在[-1,-1], [0,0],[1,1], [2,2],
#  簇方差分别为[0.4, 0.2, 0.2]
X, y = make_blobs(n_samples=1000,
                  n_features=2,
                  centers=[[-1,-1], [0,0], [1,1], [2,2]],
                  cluster_std=[0.4, 0.2, 0.2, 0.2],
                  random_state =9)
print X
print y
plt.scatter(X[:, 0], X[:, 1], marker='o')
plt.show()

下面我们来仔细分析一下代码:

第3行:引入了numpy数学库,主要用来处理矩阵和数组。

第4行:引入了pyplot绘图库,主要用来绘制一些图表。

第5行:从sklearn中引入了make_blobs函数,用于生产样本点。

第10行到14行:用于生成1000个样本点,指定了4个中心,这样就可以生成4个聚类。make_blobs返回的X是一个类似坐标的数组,通过print X打印出来如下:

可以看出来,每一行数据,它就是平面坐标。

返回的Y值,如下:

它表示对应的样本属于哪一个类,我们这里产生了4个类,所以,取值为0,1,2,3.

第17,18行,就是将散点图显示出来了。

八、使用sklean库提供的K-Mean算法对1000个样本进行聚类

为了让大家有整体的概念,我们首先来看一下本节要实现的效果,如下图所示:

这个案例在二维空间中产生了1000个样本点,之所以选择在二维空间中,是因为我们能够比较容易的用图形绘制出来。然后通过聚类算法,我们将1000个点分成了4类并用不同的颜色标记出来,这就是本节的全部内容了。

侯捷说:”代码面前,了无秘密”,我们先看看代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# -*- coding: utf8 -*-
 
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets.samples_generator import make_blobs
from sklearn.cluster import KMeans
 
# X为样本特征,Y为样本簇类别,
# 共1000个样本,每个样本4个特征,共4个簇,簇中心在[-1,-1], [0,0],[1,1], [2,2],
#  簇方差分别为[0.4, 0.2, 0.2]
X, y = make_blobs(n_samples=1000,
                  n_features=2,
                  centers=[[-1,-1], [0,0], [1,1], [2,2]],
                  cluster_std=[0.4, 0.2, 0.2, 0.2],
                  random_state =9)
print X
print y
 
y_pred = KMeans(n_clusters=3, random_state=9).fit_predict(X)
plt.scatter(X[:, 0], X[:, 1], c=y_pred)
plt.show()

部分代码,我们已经在前面说明了,对未说明的代码,我们重点解释一下:

8.1、KMeans函数的使用

第6行,导入了sklearn模块的KMeans算法。KMeans就是处理k均值算法的类。KMeans算法的函数构造如下:

1
2
3
4
def __init__(self, n_clusters=8, init='k-means++', n_init=10,
             max_iter=300, tol=1e-4, precompute_distances='auto',
             verbose=0, random_state=None, copy_x=True,
             n_jobs=1, algorithm='auto'):

下面解释一下构造函数的几个参数:

n_clusters:表示把样本分为几类,不传这个参数,默认是8类。

init:可以取3个值{‘k-means++’, ‘random’ or an ndarray},他们的意思分别是:

‘k-means++’ : 通过k-mean内置的初始化中心方法。其实具体采用哪种方法是无所谓的,因为第一次选择的中心点,对最终结果其实没有多大的影响。

‘random’: 随机选择样本的几个点作为中心点。

‘ndarray’:表示自己传一个数组进来,这个数组中包含了中心点。这种方式,有时候就相当于作弊了,因为,自己都差不多知道中心点了,还要聚类干嘛。

max_iter: 算法最多迭代计算的次数,这里默认是300次。也就是说即使300次,还未求到收敛的各个分类的中心,也不在计算了,以最后一次的分类中心为准。 algorithm : “auto”, “full” or “elkan”, default=”auto”

random_state:这是一个中心点选择的随机数种子,可以任意的填写。

其他的参数一般没用,先不用管,保持默认就好。

8.2、预测函数 fit_predict

KMeans函数初始化了一个k均值聚类的模型,fit_predict函数对参数进行聚类处理,并返回每个样本所属的类别。代码如下:

1
y_pred = KMeans(n_clusters=3, random_state=9).fit_predict(X)

这里的y_pred就是分类后的结果。

最后将分类结果绘制出来,

1
2
plt.scatter(X[:, 0], X[:, 1], c=y_pred) plt.show()
plt.show()

上面的代码通过scatter绘制散点图,c参数表示使用不同的颜色,取值可以使整数,scatter内部会根据c的不同值,随机的绘制不同的颜色。

好了,这节课,我们就讲到这里,大家快动手码代码吧。