聚类
在前面我们所使用的KNN、SVM、DT等算法中,我们就是根据给定数据集的数据和标签来不断的学习模型参数,最终形成一个合适的模型,然后可以通过该模型去对其他的数据进行预测。但现在如果我们的数据中缺失了标签怎么办?从一个带有标签的监督学习转变为一个无标签的无监督学习。那么我们上述的算法就没法发挥作用了,聚类算法变应运而生,专门来应对此类没有标签的无监督学习任务,通过对无标签数据的学习来揭示数据的内在性质与规律。 聚类算法一般主要有量大用途: 1:作为一些监督学习任务的预处理,针对一些无标签数据进行簇聚类,形成标记数据在进行后续的分类等学习 2:单独使用来揭示数据之间存在的分布结构信息
聚类算法
KMEANS(基于原型聚类)
目标函数:
E
=
∑
i
=
1
K
∑
x
∈
C
i
∣
∣
x
?
u
i
∣
∣
2
E=\sum_{i=1}^K\sum_{x∈C_i}||x-u_i||^2
E=∑i=1K?∑x∈Ci??∣∣x?ui?∣∣2,其中
u
i
=
1
∣
C
i
∣
∑
x
∈
C
i
x
u_i=\frac{1}{|C_i|}\sum_{x∈C_i}x
ui?=∣Ci?∣1?∑x∈Ci??x,相当于簇的均值向量。也就是每一簇的均值,是每一个簇的质心。样本集:
D
=
{
x
1
,
x
2
,
.
.
.
,
X
m
}
D=\{x_1,x_2,...,X_m\}
D={x1?,x2?,...,Xm?},簇:
C
=
{
C
1
,
C
2
,
.
.
.
,
C
k
}
C=\{C_1,C_2,...,C_k\}
C={C1?,C2?,...,Ck?}
kmean算法流程
1:确定超参数k,聚类簇数
2:在样本中随机选取k个样本作为初始化均值向量
3:循环遍历所有样本,分别计算样本与均值向量之间的距离(距离度量算法多种,欧式、曼哈顿、闵可夫斯基等),并根据距离的远近将样本划分到不同的簇中
4:在上一次遍历完生成的簇中再次计算初始化均值,再重复上述1-3过程,当初始化均值不再发生改变,kmeans算法会自动停止,输出最后一次的分簇结果
下图,kmeans算法伪代码+
栗子:假设有
D
=
{
x
1
,
.
.
.
,
x
10
}
D=\{x_1,...,x_{10}\}
D={x1?,...,x10?}十个数据,设置k=3,初始化中随机选取
x
1
,
x
5
,
x
7
x_1,x_5,x_7
x1?,x5?,x7?作为均值向量(代表三个簇),分别计算每个样本与三个均值向量的距离,然后距离哪个均值向量近就分为哪个簇。假设一轮后
C
1
=
{
x
1
,
x
3
,
x
4
,
x
6
}
,
C
2
=
{
x
2
,
x
5
}
,
C
3
=
{
x
7
,
x
8
,
x
9
,
x
10
}
C_1=\{x_1,x_3,x_4,x_6\},C_2=\{x_2,x_5\},C_3=\{x_7,x_8,x_9,x_{10}\}
C1?={x1?,x3?,x4?,x6?},C2?={x2?,x5?},C3?={x7?,x8?,x9?,x10?},再分别计算三个簇的均值向量,然后载进行上述过程,直到满足算法终止条件,最终输出聚类结果。
kmeans:
优点:简单直观,原理清晰
缺点:kmeans的聚类效果与初始化的均值向量有较大的联系,不稳定。一般需要我们运行多次观察较好结果,计算量随着样本数增大线性增大
参数影响:存在超参k,k值的选择很重要,对后续的聚类效果有较大的影响
LVQ(基于原型向量)
目标函数:学习一组n维的原型向量
{
p
1
,
p
2
,
.
.
.
,
p
m
}
\{p_1,p_2,...,p_m\}
{p1?,p2?,...,pm?},其中每一个原型向量表示一个聚类簇,使得
d
i
s
=
{
x
∈
X
∣
∣
∣
x
?
p
i
∣
∣
2
≤
∣
∣
x
?
p
j
∣
∣
2
,
i
≠
j
}
dis=\{x∈X| ||x-p_i||^2≤||x-p_j||^2,i≠j\}
dis={x∈X∣∣∣x?pi?∣∣2≤∣∣x?pj?∣∣2,i?=j}成立,换句话就是将距离最近的点划给
p
i
p_i
pi?代表的
C
?
i
C-i
C?i簇。(划分思想同kmeans基本一致) 在学习原型向量中,我们可以使用带有标记的数据,这点和其他聚类算法不同 其数据集形式:
D
=
{
(
x
1
,
y
1
)
,
(
x
2
,
y
2
)
,
.
.
.
,
(
x
m
,
y
m
)
}
D=\{(x_1,y_1),(x_2,y_2),...,(x_m,y_m)\}
D={(x1?,y1?),(x2?,y2?),...,(xm?,ym?)}
LVQ算法流程
1:初始化一组原型向量(一般就是选取k个点作为初始化原型向量,k为簇数),并且分别给与每个原型向量一个标签,并设定一个学习率
2:随机在数据集中抽取样本,分别计算样本与每个原型向量之间的距离。
3:选取原型向量中与该样本距离最近的那个原型向量,将该原型向量的标签与样本的标签对照
4:如果二者标签一致,表明该样本应该属于该原型向量代表的簇中,就通过设定的学习率来缩小二者之间的距离,反之若是不符合就拉大二者间距离
5:不断的重复2-4的过程,直到原型向量基本不再变化或者变化很小就结束算法,输出学习的一组n维原型向量
6:分别计算每个样本与原型向量之间的距离,就近原则进行分簇
栗子:假设有
D
=
{
(
x
1
,
y
1
)
,
(
x
2
,
y
2
)
,
.
.
.
,
(
x
10
,
y
10
)
}
D=\{(x_1,y_1),(x_2,y_2),...,(x_{10},y_{10})\}
D={(x1?,y1?),(x2?,y2?),...,(x10?,y10?)}十个数据,设置q=k=4,初始化中随机选取
x
1
,
x
5
,
x
7
,
x
9
x_1,x_5,x_7,x_9
x1?,x5?,x7?,x9?作为原型向量(代表四个簇)。其中
y
1
?
y
4
y_1-y_4
y1??y4?为A类,
y
5
,
y
6
y_5,y_6
y5?,y6?为B类,
y
7
,
y
9
y_7,y_9
y7?,y9?记为C类,
y
10
y_{10}
y10?记为D类。同时原型向量q的标记t分别记作{A,B,C,C},从样本中随机抽取一个样本假设为
x
4
x_4
x4?,分别计算四个原型向量与该样本之间的距离,选取距离最小的原型向量(这里假设为
q
2
q_2
q2?),判断
q
2
q_2
q2?与
x
2
x_2
x2?之间的类别标记是否一样,一样就缩小距离,否则就扩大距离。重复这样的一个过程,知道q整体不再有大的变化结束算法。 算法中扩大、缩小距离,不太明白的将
p
‘
p^`
p‘代入计算与
x
j
x_j
xj?的欧氏距离即可明白,
d
i
s
=
∣
∣
p
‘
?
x
j
∣
∣
2
=
∣
∣
p
i
+
n
(
x
j
?
p
i
)
?
x
j
∣
∣
2
=
(
1
?
n
)
∣
∣
p
i
?
x
j
∣
∣
2
dis = ||p^`-x_j||_2=||p_i+n(x_j-p_i)-x_j||_2=(1-n)||p_i-x_j||_2
dis=∣∣p‘?xj?∣∣2?=∣∣pi?+n(xj??pi?)?xj?∣∣2?=(1?n)∣∣pi??xj?∣∣2?
LDQ:
优点:可以使用我们日常数据中的标签信息,计算量对于kmeans小
缺点,超参较多,一个q(原型向量数),一个学习率,都需要进行调整
用途:因为可以使用原有数据的标签,因此多用于处理带有标签的数据聚类情况
MOG(高斯混合聚类)
假设前提:簇中数据大致服从一个多元高斯分布 目标函数:
P
M
(
x
)
=
∑
i
=
1
k
α
i
p
(
x
∣
u
i
,
δ
i
)
P_M(x)=\sum_{i=1}^kα_ip(x|u_i,\delta_i)
PM?(x)=∑i=1k?αi?p(x∣ui?,δi?),我们假设每一个簇内数据都服从一个高斯分布,而整个数据集就是由这些高斯分布共同作用抽样得到的。其中
α
i
α_i
αi?表示每个高斯模型的权重,代表着混合系数,总和为1 。现在我们就是假设在已知数据的分布情况下,来计算每个样本由,每个高斯模型产生的可能性。因此我们的目标是最终计算一个已知样本下的后验概率。
P
M
(
z
j
∣
x
j
)
=
P
(
z
j
=
x
)
P
M
(
x
j
∣
z
j
=
i
)
P
M
(
x
j
)
(
贝
叶
斯
公
式
)
=
α
i
.
P
(
x
j
∣
u
i
,
δ
i
)
∑
l
=
1
k
α
l
.
P
(
x
j
∣
u
l
,
δ
l
)
P_M(z_j|x_j)=\frac{P(z_j=x)P_M(x_j|z_j=i)}{P_M(x_j)}(贝叶斯公式)=\frac{α_i.P(x_j|u_i,\delta_i)}{\sum_{l=1}^kα_l.P(x_j|u_l,\delta_l)}
PM?(zj?∣xj?)=PM?(xj?)P(zj?=x)PM?(xj?∣zj?=i)?(贝叶斯公式)=∑l=1k?αl?.P(xj?∣ul?,δl?)αi?.P(xj?∣ui?,δi?)?,其中
z
j
∈
{
1
,
2
,
.
.
.
,
k
}
z_j∈\{1,2,...,k\}
zj?∈{1,2,...,k}表示第i个簇代表的高斯模型。这样问题就转化为如何求解这些我们假设的高斯模型了,换句话说就是求解模型的参数
α
i
,
u
i
,
δ
i
α_i,u_i,\delta_i
αi?,ui?,δi?,对于这种优化估计参数问题不用考虑太多老朋友对数似然估计法直接出战。
L
L
(
D
)
=
l
n
(
∏
j
=
1
m
P
M
(
x
j
)
)
LL(D)=ln(\prod_{j=1}^mP_M(x_j))
LL(D)=ln(∏j=1m?PM?(xj?)),分别对
u
i
,
δ
i
u_i,\delta_i
ui?,δi?求导=0,即可算出均值
u
i
u_i
ui?,方差
δ
i
\delta_i
δi?,而对于
α
i
α_i
αi?有一个的约束条件,
α
i
≥
0
,
∑
i
=
1
m
α
i
=
1
α_i≥0,\sum_{i=1}^mα_i=1
αi?≥0,∑i=1m?αi?=1,在SVM中刚见过这种约束性的优化问题,拉格朗日乘子法直接上,对
α
i
α_i
αi? 求导。即可得出所有的参数。知道所有的参数再去计算后验概率就完事了。
MOG算法流程
1:初始化k(簇数)个高斯模型参数,一般这个均值直接选取样本点作为初始化。
2:遍历样本,根据上述的后验概率公式计算每个样本由每个高斯模型生成的概率
3:将2步得到的均值、方差、权重系数求均值作为新的参数对上一轮每个高斯模型参数进行更新
4:重复2-3,直到参数不再发生大的变化
5:根据最终的模型参数,计算每个样本的后验概率,划分确定的簇
栗子:假设有
D
=
{
x
1
,
,
x
2
,
.
.
.
,
x
10
}
D=\{x_1,,x_2,...,x_{10}\}
D={x1?,,x2?,...,x10?}十个数据,设置k=3,初始化中随机选取
x
1
,
x
5
,
x
9
x_1,x_5,x_9
x1?,x5?,x9?作为均值
u
i
u_i
ui?(代表三个簇)。
α
1
=
α
2
=
α
3
=
1
3
α_1=α_2=α_3=\frac{1}{3}
α1?=α2?=α3?=31?,在初始化一个方差,遍历10个样本,计算后验概率,再求均值方差与权重的均值再遍历。。等到三个参数不咋变了,OK再遍历求后验概率,根据概率大划分原则分簇。
MOG:
一种基于假设分布的高斯性质的概率聚类方法,一般数据偏向于高斯分布效果较好
超参数:k值的选择也是调参中的核心问题
DBSCAN(基于密度聚类)
我愿称之为传销法,其主题思想有点传销不断发展下线的味道。该算法也没有什么目标函数就是找取一些核心对象,一直画圈,只要满足一定的条件就一直画下去。就是一条链式圈,这条链式圈上所有样本就分为一个簇。当然这个核心对象是有一定的要求的,需要设定在一定半径内邻域参数
?
,
n
\epsilon,n
?,n,也就是在一定半径内要至少有
n
n
n个点。(下图链式画圈)
DBSCAN算法流程
1:设定邻域参数,确定半径与n
2:遍历数据集,寻找符号条件的核心对象集
3:随机从2中选取一个核心对象,根据设定的半径画圈,圈内的其他核心对象也依次画圈,将圈内的样本划分为一个簇
4:在数据集中去除3中的样本并去除核心对象集中已被访问过的核心对象
5:再剩余的核心对象集中随机选取一个核心对象重复3-4操作,直到核心对象集为空
6:输出聚类好的簇数
栗子:假设有
D
=
{
x
1
,
,
x
2
,
.
.
.
,
x
10
,
.
.
.
x
30
}
D=\{x_1,,x_2,...,x_{10},...x_{30}\}
D={x1?,,x2?,...,x10?,...x30?} 30个数据,设置半径
?
=
0.1
,
n
=
M
I
n
P
t
s
=
5
\epsilon=0.1,n=MInPts=5
?=0.1,n=MInPts=5,先遍历一遍找出来核心对象集为
{
x
1
,
x
3
,
x
7
,
x
9
,
x
1
1
,
x
15
,
x
19
,
x
25
,
x
29
}
\{x_1,x_3,x_7,x_9,x_11,x_{15},x_{19},x_{25},x_{29}\}
{x1?,x3?,x7?,x9?,x1?1,x15?,x19?,x25?,x29?}。随机选取一个核心对象
x
1
x_1
x1?,按照半径和上述要求,不断的链式画圈,最终生成第一个聚类簇
C
1
=
{
x
1
,
x
2
,
x
3
,
x
4
,
x
5
,
x
7
,
x
11
,
x
19
,
x
22
}
C_1=\{x_1,x_2,x_3,x_4,x_5,x_7,x_{11},x_{19},x_{22}\}
C1?={x1?,x2?,x3?,x4?,x5?,x7?,x11?,x19?,x22?},在数据集中去除这些点,在核心对象集中去除上述已经遍历过的点,此时核心对象集为
{
x
9
,
x
15
,
x
25
,
x
29
}
\{x_9,x_{15},x_{25},x_{29}\}
{x9?,x15?,x25?,x29?},然后再随机选取一个核心对象重复上述操作,最终生成k个簇。
DBSCAN
优点:不需要在设定k值,由算法自动去计算,计算量减少很多
超参:但是同样引入了半径与n,需要寻找合适的参数优化模型
AGNES(基于层次)
算法思想:首先要给定目标簇数k,首先将数据集中每一个样本视为一个初始的聚类,然后就是计算簇与簇之间的距离,距离最近的两个合并,一直循环该步骤,知道满足目标簇数k。因此如何度量簇与簇之间的距离成为了该算法的关键。一般我们采取簇的最大、最小、平均距离来度量簇与簇之间的距离
AGNES算法流程
1:确定簇数k,以及距离度量算法d
2:i∈(1,2,..,m),j=i+1,循环计算两个簇之间的距离,可以形成一个M*M的实对称距离矩阵
3:根据距离矩阵找出距离最近的两个簇,进行合并。并删除第二个被合并簇的数据
4:簇再重新进行编号不断重复上述2-3,知道聚合到设定的k个类
5:输出划分后的簇
上述的几个算法伪代码图均来自西瓜书,也是目前聚类算法较为常用,各个类别方法中的代表作。聚类算法发展很快,还有很多改进型算法如Canopy、Kmeans++、二分kmeans等等,大家只需要用到时候在去学习即可。下面用一个实例来展示聚类API使用。
from sklearn.datasets import load_iris,make_circles
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
from sklearn.metrics import calinski_harabasz_score,silhouette_score
import matplotlib.pyplot as plt
import pandas as pd
dataset = load_iris()
pca = PCA(n_components=2,svd_solver="full")
data = pca.fit_transform(dataset.data)
score_list = list()
lunkuo = list()
dis =list()
y_prediction = list()
for i in range(2,11):
estimator = KMeans(n_clusters=i,algorithm="auto")
y_pred = estimator.fit_predict(data)
y_prediction.append(y_pred)
dis.append(estimator.inertia_)
score = calinski_harabasz_score(data,y_pred)
sil = silhouette_score(data,y_pred)
score_list.append(score)
lunkuo.append(sil)
fig,ax = plt.subplots(nrows=3,ncols=3,figsize=(12,12))
n = 2
for i in range(3):
for j in range(3):
ax[i,j].scatter(data[:,0],data[:,1],c=y_prediction[n-2])
ax[i,j].set_title('k=%s' %(n))
n+=1
聚类性能度量
由上图可见,单从图的可视化我们还无法很清晰的区分出聚类的好坏,下面就介绍几种衡量聚类好坏的方法以及如何确定合适的k值。 1:’‘肘’‘方法,elbow method
下降率突然变缓认为是最为合适的k值,纵轴为损失函数,一般选取距离平方和。上面那个案例中,我们采取kemans中inertia_属性求取距离平方和。
plt.plot([i for i,_ in enumerate(score_list,2)],dis)
plt.show()
由上图看来,k=4比较合适,也符合鸢尾花四类别的实际情况
2:SSE(误差平方和)
S
S
E
=
∑
i
=
1
k
∑
p
∈
C
i
∣
p
?
u
i
∣
2
SSE=\sum_{i=1}^k\sum_{p∈C_i}|p-u_i|^2
SSE=∑i=1k?∑p∈Ci??∣p?ui?∣2 SSE 越小代表聚类性能越好,簇内方差越小
3:轮廓距离(Silhouette Coefficient) 聚类的凝聚度(Cohesion)和分离度(Separation)
S
=
b
?
a
m
a
x
(
a
,
b
)
,
S
∈
[
?
1
,
1
]
S=\frac{b-a}{max(a,b)},S∈[-1,1]
S=max(a,b)b?a?,S∈[?1,1] 其中a表示簇内样本间不相似程度的平均值,b表示样本到其他簇平均不相似程度中的最小值。为1时,说明这个点与周围簇距离较远,聚类结果?常好,为0,这个点可能处在两个簇的边界上,当值为负时,暗含该点可能被误分了系数越大,效果越好。表示簇内越近,簇见距离越远。
plt.plot([i for i,_ in enumerate(score_list,2)],lunkuo)
plt.show()
西瓜书中还为我们提供几种其他形式的衡量方法,讲的比较透彻,这里就直接放出来供参考 4:外部指标法 对于数据集
D
=
{
x
1
,
x
2
,
.
.
.
,
x
m
}
D=\{x_1,x_2,...,x_m\}
D={x1?,x2?,...,xm?},通过聚类算法给出来的簇划分为
C
=
{
C
1
,
C
2
,
.
.
.
,
C
k
}
C=\{C_1,C_2,...,C_k\}
C={C1?,C2?,...,Ck?},而外部现在给了我们一个标准的簇划分
C
?
=
{
C
1
?
,
C
2
?
,
.
.
.
,
C
s
?
}
C^*=\{C^*_1,C_2^*,...,C_s^*\}
C?={C1??,C2??,...,Cs??},
λ
,
λ
?
λ,λ^*
λ,λ?分别为
C
,
C
?
C,C^*
C,C?簇的标记。上述可知,每个样本对之间只能存在一个集合中,因此样本对综述为
m
(
m
?
1
)
2
=
a
+
b
+
c
+
d
\frac{m(m-1)}{2}=a+b+c+d
2m(m?1)?=a+b+c+d 其中a就代表着与标准聚类一样,就是完美聚类的样本,主题思想就是a越大越好,b,c越小越好。 上述指数都是在[0,1]之间,越大代表聚类效果越好。
5:内部指标(下面这部分使用的较少,了解即可。直接上书了,书上这点讲的很清楚,没啥可再解释的了)
回到顶部
|