聚类就是把数据对象集合按照相似性划分成多个子集的过程(如下图)。其中,每个子集称为一个簇。聚类不仅要使簇中的对象彼此相似,而且要与其他簇中的对象相似。聚类是无监督学习,数据不需要类标号(标注)信息。

聚类分析以相似度为基础,在一个聚类中的模式比不在这个聚类中的模式有更多的相似度。
分类是有监督学习,即每个训练样本的数据对象已经有类标签,通过有标签样本学习分类器。
聚类是无监督学习,即不使用训练数据进行学习,通过观察学习将数据集分割成多个簇。
划分方法是指讲有n个对象的数据集D划分成k(k<=n)个簇,需满足两个条件:
其基本思想是首先创建一个初始k划分(k为要构造的划分数),然后不断迭代计算各个簇的聚类中心,并依据新的聚类中心调整聚类情况,直至收敛。
划分方法的目标有两个:
启发式方法有两种:
这些启发式算法适合发现中小规模数据库中的球状聚类;对于大规模数据库和处理任意形状的聚类,这些算法还需要进一步扩展。
K-Means算法是启发式算法,遵循寻优原则(如下图),即每次聚类保证局部最优,随后调整聚类,利用局部最优聚类的上限来不断逼近全局最优。

具体算法步骤如下:

例1:给定如下要进行聚类的对象:{2,4,10,12,3,20,30,11,25},K= 2,请使用K均值划分聚类。具体计算步骤如下:
| m 1 m_1 m1 | m 2 m_2 m2 | K 1 K_1 K1 | K 2 K_2 K2 |
|---|---|---|---|
| 2 | 4 | {2,3} | {4,10,12,20,30,11,25} |
| 2.5 | 16 | {2,3,4} | {10,12,20,30,11,25} |
| 3 | 18 | {2,3,4,10} | {10,12,20,30,11,25} |
| 4.75 | 19.6 | {2,3,4,10,11,12} | {20,30,25} |
| 7 | 25 | {2,3,4,10,11,12} | {20,30,25} |
例2:假定我们对A、B、C、D四个样品分别测量两个变量和得到结果见表。试将表中得样品聚成两类。

第一步:按要求取K=2,为了实施均值法聚类,我们将这些样品随意分成两类,比如(A、B)和(C、D),然后计算这两个聚类的中心坐标,见下表所示。
中心坐标是通过原始数据计算得来的。

第二步:计算某个样品到各类中心的欧氏平方距离,然后将该样品分配给最近的一类。对于样品有变动的类,重新计算它们的中心坐标,为下一步聚类做准备。先计算A到两个类的平方距离:
d
2
(
A
,
(
A
B
)
)
=
(
5
−
2
)
2
+
(
3
−
2
)
2
=
10
d
2
(
A
,
(
C
D
)
)
=
(
5
+
1
)
2
+
(
3
+
2
)
2
=
61
d^2(A,(AB))=(5-2)^2+(3-2)^2=10\\ d^2(A,(CD))=(5+1)^2+(3+2)^2=61
d2(A,(AB))=(5−2)2+(3−2)2=10d2(A,(CD))=(5+1)2+(3+2)2=61
由于A到(A、B)的距离小于到(C、D)的距离,因此A不用重新分配。计算B到两类的平方距离:
d
2
(
B
,
(
A
B
)
)
=
(
−
1
−
2
)
2
+
(
1
−
2
)
2
=
10
d
2
(
B
,
(
C
D
)
)
=
(
−
1
+
1
)
2
+
(
1
+
2
)
2
=
9
d^2(B,(AB))=(-1-2)^2+(1-2)^2=10\\ d^2(B,(CD))=(-1+1)^2+(1+2)^2=9
d2(B,(AB))=(−1−2)2+(1−2)2=10d2(B,(CD))=(−1+1)2+(1+2)2=9
由于B到(A、B)的距离大于到(C、D)的距离,因此B要分配给(C、D)类,得到新的聚类是(A)和(B、C、D)。 更新中心坐标如下表所示。

第三步:再次检查每个样品,以决定是否需要重新分类。计算各样品到各中心的距离平方,结果见下表。

到现在为止,每个样品都已经分配给距离中心最近的类,因此聚类过程到此结束。最终得到K=2的聚类结果是A独自成 一类,B、C、D聚成一类。
(1)K-Mode算法
(2)K-means++算法
通过尽可能选择距离远得点作为初始种子节点,从而解决K-means初始点选择问题。具体得算法流程如下:
(3)K中心点(K-Mediods)算法
K中心点主要通过选用簇中位置最中心的实际对象即中心点作为参照点并基于最小化所有对象与其参照点之间的相异度之和 E = ∑ i = 1 k ∑ p ∈ C i ∣ p − o i ∣ E=\sum_{i=1}^{k}\sum_{p\in C_i}^{} \left |p-o_i \right | E=∑i=1k∑p∈Ci∣p−oi∣划分(使用绝对误差标准),解决离群点敏感问题。

层次方法满足三个条件:
有两种层次方法:

基于密度聚类是指根据密度条件对邻近对象分组形成簇,簇的增长或者根据邻域密度,或者根据特定的密度函数(只要临近区域的密度超过某个阈值,就继续聚类)
主要特点:
ε-邻域:给定对象半径ε内的邻域称为该对象的ε-邻域。

核心对象:如果对象的ε-邻域至少包含最小数目MinPts个对象,则称该对象为核心对象
直接密度可达:给定对象集合D,如果p 是在q 的ε-邻域内,而q 是核心对象,则称对象p 是从对象q 关于ε和MinPts直接密度可达的。

密度可达:如果存在一个对象链 p 1 , . . . , p n , p 1 = q , p n = p p_1,...,p_n,p_1=q,p_n=p p1,...,pn,p1=q,pn=p,使得 p i + 1 p_{i+1} pi+1是从 p i p_i pi直接密度可达的,则称对象p是从对象q关于ε和MinPts(间接)密度可达的.
密度相连:如果存在对象o 使得,p 和q 都是从o关于ε和MinPts密度可达的,则称对象p与q关于ε和MinPts是密度相连的

聚类评估旨在估计在数据集上进行聚类的可行性和被聚类方法产生的结果的质量。主要包括:估计聚类趋势、确定数据集中的簇数、测定聚类质量。
对于给定的数据集,聚类趋势估计确定给定的数据集是否具有可以得到有意义的聚类的非随机结构。如果数据服从均匀分布,显然对其进行的聚类操作都是没有意义的。
霍普金斯统计量是一种空间统计量,可以检验空间分布的变量的空间随机性。
K均值这样的算法需要数据集的簇数作为参数,簇数也可以看作数据集的一个重要的概括度量,因此,在使用聚类算法导出详细的簇之前,估计簇数是可取的。
一般而言,根据是否有基准(由专家构建的理想的聚类),将聚类质量的测定分为外在方法和内在方法。外在方法通过比较聚类结果和基准进行聚类质量测定。内在方法没有可用的基准,它通过簇的分离情况评估聚类的好坏。
有许多度量(如熵、纯度、精度、召回率和F度量)用来评估分类模型的性能。对于分类,度量预测的类标号与实际类标号的对应程度。但是这些度量通过使用簇标号而不是预测的类标号,不需要做较大的改变。
这里我们主要讨论兰德系数和调整兰德系数。
兰德系数(Rand Index,RI)定义为:
R
I
=
a
+
b
C
2
n
s
a
m
p
l
e
s
RI=\frac{a+b}{C_2^n samples}
RI=C2nsamplesa+b
a表示在实际类别信息与聚类结果中都是同类别的元素对数,
b表示在实际类别信息与聚类结果中都是不同类别的元素对数,
分母表示数据集中可以组成的总元素对数。
兰德系数的值在[0,1]之间,当聚类结果完美匹配时,兰德系数为1。对于随机结果,RI并不能保证分数接近零。
为了实现“在聚类结果随机产生的情况下,指标应该接近零”,调整兰德系数(Adjusted rand index)被提出,它具有更高的区分度。

ARI取值范围为[-1,1],负数代表结果不好,值越大意味着聚类结果与真实情况越吻合。ARI可用于聚类算法之间的比较。

内在方法用于没有基准可用时的聚类质量评估,通过考察簇的分离情况和簇的紧凑度进行聚类评估。
轮廓系数(Silhouette Coefficient)是一种内在评估方法。对于n个对象的数据集D,假设D别划分为k个簇。对于每个对象
o
∈
D
o\in D
o∈D,计算o到所有它所属簇中其他点的距离a(o)和o到它相邻最近的一簇内的所有点的平均距离b(o),则o的轮廓系数定义为:
s
(
o
)
=
b
(
o
)
−
a
(
o
)
m
a
x
{
b
(
o
)
,
a
(
o
)
}
s(o)=\frac{b(o)-a(o)}{max\{b(o),a(o)\}}
s(o)=max{b(o),a(o)}b(o)−a(o)
轮廓系数的值为-1~1,a(o)反映对象o所属的簇的紧凑性,值越小,簇越紧凑;b(o)反映对象o与其他簇的分离程度,值越大,说明o与其他簇越分离。当o的轮廓系数接近1时,包含o的簇是紧凑的,并且o远离其他簇。当轮廓系数为负值时,说明o距离其他簇的对象比距离与子集同在簇的对象更近。在很多情况,这是需要避免的。
sklearn中通过sklearn.metrics.silhouette_score()方法计算聚类的轮廓系数。
聚类质量包括四个维度:
from sklearn.cluster import KMeans
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn import metrics
iris=load_iris()
X=iris['data']
# 构造聚类器
estimator=KMeans(n_clusters=3,random_state=42)
kmeans_pred=estimator.fit_predict(X)
print(kmeans_pred)
# 可视化
x1 = X[kmeans_pred==0]
x2 = X[kmeans_pred==1]
x3 = X[kmeans_pred==2]
plt.scatter(x1[:,0],x1[:,1],s=100,c='red',label='Cluter 1') #选择鸢尾花数据集中前两个特征变量作为横纵坐标
plt.scatter(x2[:,0],x2[:,1],s=100,c='blue',label='Cluter 2')
plt.scatter(x3[:,0],x3[:,1],s=100,c='green',label='Cluter 3')
plt.scatter(estimator.cluster_centers_[:,0],estimator.cluster_centers_[:,1],s=100,c='black',label='Controids')
plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.legend()
plt.show()
# 模型评估
# 调整兰德系数
print('调整兰德系数:',metrics.adjusted_rand_score(iris.target, kmeans_pred))
# metric str 或可调用,默认='euclidean'
# 计算特征数组中实例之间的距离时使用的度量。
print('所有样本的平均轮廓系数:',metrics.silhouette_score(X,kmeans_pred,metric='euclidean'))


from sklearn.cluster import AgglomerativeClustering
import pandas as pd
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
from sklearn import metrics
iris=load_iris()
X=iris['data']
clustering=AgglomerativeClustering(linkage='average',n_clusters=3)
kmeans_pred=clustering.fit_predict(X)
print(kmeans_pred)
# 可视化
x1 = X[kmeans_pred==0]
x2 = X[kmeans_pred==1]
x3 = X[kmeans_pred==2]
print(x1)
plt.scatter(x1[:,0],x1[:,1],s=100,c='red',label='Cluter 1') #选择鸢尾花数据集中前两个特征变量作为横纵坐标
plt.scatter(x2[:,0],x2[:,1],s=100,c='blue',label='Cluter 2')
plt.scatter(x3[:,0],x3[:,1],s=100,c='green',label='Cluter 3')
# plt.scatter(clustering.cluster_centers_[:,0],clustering.cluster_centers_[:,1],s=100,c='black',label='Controids')
plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.legend()
plt.show()
# 调整兰德系数
print('调整兰德系数:',metrics.adjusted_rand_score(iris.target, kmeans_pred))
# metric str 或可调用,默认='euclidean'
# 计算特征数组中实例之间的距离时使用的度量。
print('所有样本的平均轮廓系数:',metrics.silhouette_score(X,kmeans_pred,metric='euclidean'))

