最近,在完成 ‘多核程序设计与实践’ 这门课程的大作业时,需要接触不同的聚类算法,对其进行 CUDA 并行化的改进。
所以,顺便以这篇博客作为聚类算法相关知识的笔记。
此外,聚类算法往往涉及到数据点之间的距离 / 相似度的计算,关于这方面的知识,欢迎看我的另一篇笔记:Meatric Learning(暂无)。
伪代码:
Step 1 : 随机选择 K 个聚类质心点 (Cluster Centroids)
Step 2 : 对每个点计算到各个聚类质心点的距离,将其类别划分为距其最近的聚类质心点
Step 3 : 计算每个簇 (Cluster)的质心,以此更新每个簇的质心点
Step 4 : 若聚类质心点不再发生变化或者已达最大迭代次数,算法结束;否则,转到Step 2。
优点:
缺点:
有文章认为 K-Means 是 Hard EM,GMM 是 Soft EM。
伪代码:
Step 1 :
(1)方案一:协方差矩阵 Σ k \Sigma_k Σk设为单位矩阵,每个模型比例的先验概率 π k = 1 / N π_k=1/N πk=1/N,均值 u k u_k uk设为随机数。
(2)方案二:利用 K-Means 对样本进行聚类,设各类的均值作为 u k u_k uk,并计算 Σ k \Sigma_k Σk, π k π_k πk取各类样本占样本总数的比例。
Step 2 : 计算数据点 x i x_i xi为 C o m p o n e n t k Component_k Componentk生成的概率。(E-step,Expectation-Step)
γ ( x i , C o m p o n e n t k ) = π k ∗ N ( x i ∣ u k , Σ k ) ∑ k = 1 K π k ∗ N ( x i ∣ u k , Σ k ) \gamma(x_i,Component_k) = \frac{\pi_k * N(x_i|u_k,\Sigma_k)}{\sum_{k=1}^{K}\pi_k * N(x_i|u_k,\Sigma_k)} γ(xi,Componentk)=∑k=1Kπk∗N(xi∣uk,Σk)πk∗N(xi∣uk,Σk)
Step 3 : 计算每个 C o m p o n e n t k Component_k Componentk的参数。(M-step,Maximization-Step)
各个类别的个数: N k = ∑ k = 1 K γ ( x i , C o m p o n e n t k ) N_k=\sum_{k=1}^{K}\gamma(x_i,Component_k) Nk=∑k=1Kγ(xi,Componentk)
各个类别的均值: u k = ∑ k = 1 K x i γ ( x i , C o m p o n e n t k ) / N k u_k =\sum_{k=1}^{K} x_i \gamma(x_i,Component_k)/N_k uk=∑k=1Kxiγ(xi,Componentk)/Nk
各个类别的协方差矩阵: Σ k = ∑ k = 1 K γ ( x i , C o m p o n e n t k ) ( x i − u k ) ( x i − u k ) T \Sigma_k =\sum_{k=1}^{K} \gamma(x_i,Component_k)(x_i-u_k)(x_i-u_k)^T Σk=∑k=1Kγ(xi,Componentk)(xi−uk)(xi−uk)T
各个Component的先验概率(混合系数): π k = N k N \pi_k=\frac{N_k}{N} πk=NNk
Step 4 : 若模型不再发生变化(变化幅度小于阈值)或者已达最大迭代次数,算法结束;否则,转到Step 2。
优点:
缺点:
伪代码:
Step 1 : 将所有数据点 x i x_i xi 设置为未标注。
Step 2 : 在未标注的数据点 x i x_i xi 中随机选择一个作为center。
Step 3 :
将离 c e n t e r center center 的距离小于等于 b a n d w i d t h bandwidth bandwidth 的所有点,记为集合 M M M,并其类别为 C C C。
同时,将集合 M M M 内所有点关于类别 C C C 的次数加一。
Step 4 : 以 c e n t e r center center 为中心点,计算集合 M M M 中每个元素的向量,并将这些向量相加,得到向量 s h i f t shift shift。
Step 5 : 更新 c e n t e r = c e n t e r + s h i f t center = center+shift center=center+shift,即沿着 s h i f t shift shift 方向移动 c e n t e r center center,移动距离为 ∣ ∣ s h i f t ∣ ∣ ||shift|| ∣∣shift∣∣。
Step 6 : 若 ∣ ∣ s h i f t ∣ ∣ ||shift|| ∣∣shift∣∣小于阈值或迭代次数达到最大迭代次数,则转到Step 7;否则,转到 Step 3。
Step 7 : 若收敛时 c e n t e r center center 与其他类别的 c e n t e r center center的距离小于阈值,则合并两个类别;否则,记录类别 C C C,记为新增类别。
Step 8 : 若所有数据点 x i x_i xi 都被标注,则转到 Step 9;否则,转到 Step 2。
Step 9 : 遍历各个集合,对集合中所有数据点 x i x_i xi,根据其关于类别访问次数,取集合中其访问次数最大的类别作为集合的归属类别。
优点:
缺点:
Hierarchical Clustering(即层次聚类算法),也被称为系统聚类算法,与其他聚类算法不同,该算法对类别进行聚类,即将相似的类别聚为一个更大的类别或将一个类别二拆为两个小类别。其中,前者为自底向上算法(Bottom-up algorithms),后者称为自顶向下算法(Top-down algorithms)。
在层次聚类算法中,除了数据点之间的距离计算公式(metric)需要确定外,也需要确定类别之间的距离计算公式(linkage)。其中,常见的类间距离如下所示:
PS:在我之前学过的《数据分析方法》(梅长林 范金城 编)第189页中,介绍的谱系聚类法应该就是对应这个Hierarchical Clustering了,虽然感觉根据名字来看应该对应 Spectral Clustering
伪代码: (此处仅介绍常见的自底向上的算法流程)
Step 1 : 设置所有数据点 x i x_i xi 各自属于类别 i i i。
Step 2 : 计算每个类别的类间距离,并选择类间距离最小的两个类别进行合并,并将合并过程通过 Dendrogram (一种树结构,动图中有进行展示)进行记录。
Step 3 : 若所有数据点 x i x_i xi 都属于同一类别,则转到 Step 4;否则,转到 Step 2。
Step 4 : 根据 Dendrogram 以及问题需求,确定簇的个数,并对聚类结果进行划分。
优点:
缺点:
定义:
ϵ \epsilon ϵ-邻域:对于 x j ∈ D x_j \in D xj∈D,其 ϵ \epsilon ϵ-邻域为样本集D中与 x j x_j xj的距离不大于 ϵ \epsilon ϵ的子样本集,即 N x j = { x i ∈ D ∣ d i s t a n c e ( x i , x j ) ≤ ϵ } N_{x_j}=\{x_i \in D | distance(x_i,x_j) \leq \epsilon \} Nxj={xi∈D∣distance(xi,xj)≤ϵ}, 子样本集的个数记为 ∣ N x j ∣ |N_{x_j}| ∣Nxj∣。
核心对象:对于任一样本 x j ∈ D x_j \in D xj∈D,如果其 ϵ \epsilon ϵ-邻域对应的 N x j N_{x_j} Nxj至少包含 M i n P t s MinPts MinPts 个样本,即如果 ∣ N x j ∣ ≥ M i n P t s |N_{x_j}| \geq MinPts ∣Nxj∣≥MinPts,则 x j x_j xj是核心对象。
密度直达:如果 x i x_i xi位于 x j x_j xj的 ϵ \epsilon ϵ-邻域中,且 x j x_j xj是核心对象,则称 x i x_i xi由 x j x_j xj密度直达,反之不一定成立。
密度可达:对于 x i x_i xi和 x j x_j xj,如果存在样本样本序列 p 1 , p 2 , . . . , p T p_1,p_2,...,p_T p1,p2,...,pT,满足 p 1 = x i p_1=x_i p1=xi, p T = x j p_T=x_j pT=xj, 且 p t + 1 p_{t+1} pt+1由 p t p_t pt密度直达,则称 x j x_j xj由 x i x_i xi密度可达。也就是说,密度可达满足传递性。此时序列中的传递样本 p 1 , p 2 , . . . , p T − 1 p_1,p_2,...,p_{T−1} p1,p2,...,pT−1均为核心对象,因为只有核心对象才能使其他样本密度直达,密度可达也不满足对称性,这个可以由密度直达的不对称性得出。
密度相连:对于 x i x_i xi和 x j x_j xj,如果存在核心对象样本 x k x_k xk,使 x i x_i xi和 x j x_j xj均由 x k x_k xk密度可达,则称 x i x_i xi和 x j x_j xj密度相连,密度相连关系是满足对称性的。
伪代码:
Step 1 : 将所有数据点 x i x_i xi 设置为未标注。
Step 2 : 在未标注的数据点 x i x_i xi 中随机选择一个数据点 x j x_j xj,并计算其 ϵ \epsilon ϵ-领域子样本集 N x j N_{x_j} Nxj。若 ∣ N x j ∣ ≥ M i n P t s |N_{x_j}| \geq MinPts ∣Nxj∣≥MinPts,则将 x j x_j xj添加到核心对象样本集合中。
Step 3 :
将离 c e n t e r center center 的距离小于等于 b a n d w i d t h bandwidth bandwidth 的所有点,记为集合 M M M,并其类别为 C C C。
同时,将集合 M M M 内所有点关于类别 C C C 的次数加一。
Step 4 : 以 c e n t e r center center 为中心点,计算集合 M M M 中每个元素的向量,并将这些向量相加,得到向量 s h i f t shift shift。
Step 5 : 更新 c e n t e r = c e n t e r + s h i f t center = center+shift center=center+shift,即沿着 s h i f t shift shift 方向移动 c e n t e r center center,移动距离为 ∣ ∣ s h i f t ∣ ∣ ||shift|| ∣∣shift∣∣。
Step 6 : 若 ∣ ∣ s h i f t ∣ ∣ ||shift|| ∣∣shift∣∣小于阈值或迭代次数达到最大迭代次数,则转到Step 7;否则,转到 Step 3。
Step 7 : 若收敛时 c e n t e r center center 与其他类别的 c e n t e r center center的距离小于阈值,则合并两个类别;否则,记录类别 C C C,记为新增类别。
Step 8 : 若所有数据点 x i x_i xi 都被标注,则转到 Step 9;否则,转到 Step 2。
Step 9 : 遍历各个集合,对集合中所有数据点 x i x_i xi,根据其关于类别访问次数,取集合中其访问次数最大的类别作为集合的归属类别。
优点:
缺点:
Spectral Clustering 比较复杂,需要对凸轮、线性代数、矩阵分析都有一定的了解,所以在这篇博文中我仅粗略的讲解。
伪代码:
Step 1 : 确定降维后的维度 K 1 K_1 K1以及簇的个数 K 2 K_2 K2。
Step 2 : 构建样本的相似矩阵 S S S,并以此构建邻接矩阵 W W W 和度矩阵 D D D。
Step 3 : 计算拉普拉斯矩阵 L L L,并对其进行标准化,即 D − 1 / 2 L D − 1 / 2 D^{-1/2}LD^{-1/2} D−1/2LD−1/2。
Step 4 : 计算 D − 1 / 2 L D − 1 / 2 D^{-1/2}LD^{-1/2} D−1/2LD−1/2 最小的 K 1 K_1 K1 个特征值所各自对应的特征向量 f f f,并将其组成矩阵,进行行标准化后得到特征矩阵 F F F,其维度为 n ∗ K 1 n * K_1 n∗K1(其中, n n n 为数据点的个数)。
Step 5 : 将该矩阵作为新的数据点,利用其他聚类方式对其进行聚类,并设定簇的个数为 K 2 K_2 K2。
优点:
缺点:
伪代码:
Step 1 : 计算初始的相似度矩阵,并将各个数据点 x i x_i xi 之间的吸引度 r ( i , k ) r(i,k) r(i,k) 和归属度 a ( i , k ) a(i,k) a(i,k) 置为 0。
Step 2 : 更新各个数据点 x i x_i xi 之间的吸引度 r ( i , k ) r(i,k) r(i,k),再更新各个数据点 x i x_i xi 之间的归属度 a ( i , k ) a(i,k) a(i,k),公式如下:
r ( i , k ) = s ( i , k ) − m a x ( a ( i , k ′ ) + s ( i , k ′ ) , ∀ k ′ ≠ k ) r(i,k) = s(i,k)-max(a(i,k^{'})+s(i,k^{'}), \forall k^{'} \neq k) r(i,k)=s(i,k)−max(a(i,k′)+s(i,k′),∀k′̸=k)
a ( i , k ) = m i n ( 0 , r ( k , k ) + ∑ i ′ ∉ { i , k } r ( i ′ , k ) ) a(i,k) = min(0,r(k,k)+\sum_{i^{'}\notin \{i,k\}}r(i^{'},k)) a(i,k)=min(0,r(k,k)+i′∈/{i,k}∑r(i′,k))
r t + 1 ( i , k ) = λ ∗ r t ( i , k ) + ( 1 − λ ) ∗ r t + 1 ( i , k ) r_{t+1}(i,k) = \lambda * r_t(i,k) + (1-\lambda) * r_{t+1}(i,k) rt+1(i,k)=λ∗rt(i,k)+(1−λ)∗rt+1(i,k)
α t + 1 ( i , k ) = λ ∗ α t ( i , k ) + ( 1 − λ ) ∗ α t + 1 ( i , k ) \alpha_{t+1}(i,k) = \lambda * \alpha_t(i,k) + (1-\lambda) * \alpha_{t+1}(i,k) αt+1(i,k)=λ∗αt(i,k)+(1−λ)∗αt+1(i,k)
Step 3 : 通过 m a x ( a ( i , k ) + r ( i , k ) ) max(a(i,k)+r(i,k)) max(a(i,k)+r(i,k)),确定数据点 x i x_i xi 的代表样本点(所属类别) k k k。
Step 4 : 若模型不再发生变化(变化幅度小于阈值)或者已达最大迭代次数,算法结束;否则,转到Step 2。
优点:
缺点:
参考资料:
如果你看到了这篇文章的最后,并且觉得有帮助的话,麻烦你花几秒钟时间点个赞,或者受累在评论中指出我的错误。谢谢!
作者信息:
知乎:没头脑
LeetCode:Tao Pu
CSDN:Code_Mart
Github:Bojack-want-drink