无监督学习--聚类算法

划分聚类

典型的划分聚类 KMeans

密度聚类

DBSCAN

经典的密度聚类DBSCAN

基本概念

  1. ε \varepsilon ε邻域(eps邻域)
    ε \varepsilon ε是一个距离阈值,对于样本集S中的任意 x i x_i xi样本,与其距离小于等于 ε \varepsilon ε阈值的其他样本的集合,叫做样本 x i x_i xi ε \varepsilon ε邻域
    记为:
    N ε ( x i ) N_\varepsilon(x_i) Nε(xi)= { x j ∣ d i s t ( x i , x j ) ≤ ε { x_j|dist(x_i,x_j)\le \varepsilon } xjdist(xi,xj)ε}

  2. 核心对象(点)
    N ε ( x i ) N_\varepsilon(x_i) Nε(xi)内样本点数大于等于 M i n P t s MinPts MinPts阈值,即
    | N ε ( x i ) N_\varepsilon(x_i) Nε(xi)| ≥ M i n P t s \ge MinPts MinPts
    x i x_i xi称为核心点,否则称为边界点

  3. 密度直达
    x j x_j xj N ε ( x i ) N_\varepsilon(x_i) Nε(xi),且 x i x_i xi为核心点,则 x j x_j xj可由 x i x_i xi密度直达,反之不一定成立( x j x_j xj不一定是核心点)
    只有核心点之间满足对称性

  4. 密度可达
    若有一个样本点序列 p 1 , p 2 , p 3 , . . . p n p_1,p_2,p_3,...p_n p1,p2,p3,...pn p 1 = x i , p n = x j p_1=x_i,p_n=x_j p1=xi,pn=xj p i + 1 p_{i+1} pi+1可由 p i p_i pi密度直达,则 x j x_j xj可有 x i x_i xi密度可达(传递性)

  5. 密度相连
    若存在一个核心点 o o o,使得 x i x_i xi x j x_j xj均由 o o o密度可达
    则称 x i x_i xi x j x_j xj密度相连
    在这里插入图片描述

    i. 所有密度相连的点分为一簇,同一簇的点必定密度相连
    ii. 一个核心对象所有密度可达的点集合,分为一簇

DBSCAN基本思想

在这里插入图片描述

算法流程

python实现

sklearn库的实现

DBSCAN优点及缺点

优点

  1. 适用凸、非凸的稠密数据集
    不像KMeans/Birch之类的,只适用凸集
  2. 不需事先指定聚类簇数 k k k
  3. 聚类完成可以识别噪声点 ,对异常点不敏感

缺点

  1. 非稠密数据,距离差异大的样本集,都不适用DBSCAN
  2. 样本集大时,聚类收敛时间较长,使用kd_tree,ball_tree增加空间复杂度
  3. ε 和 M i n P t s \varepsilon 和MinPts εMinPts需联合调参,比较复杂,DBSCAN对这俩个参数比较敏感

ε 和 M i n P t s \varepsilon 和MinPts εMinPts选参

  1. 交叉验证
    ε 和 M i n P t s \varepsilon 和MinPts εMinPts合理的数值组合,使DBSCAN聚类的评价指标最优,比如轮廓系数,DB指数等
  2. 网格搜索
  3. 手肘法,根据MinPts,确定 ε \varepsilon ε
    i. MinPts取初始值 k = n + 1 k=n+1 k=n+1,即特征数加 1 1 1
    ii.迭代每个样本 x i x_i xi,计算与样本集S内其他样本的距离,取第 k k k近的距离 k d i s t k_{dist} kdist,如 [ 0 , 1 , 2 , 2 , 3 , 4 , 5 ] [0,1,2,2,3,4,5] [0,1,2,2,3,4,5]中第三近的距离为3,0表示样本与自己的距离。将所有样本的 k d i s t k_{dist} kdist放入列表 L L L
    iii. 对 L L L从大到小排序,作线性可视化,取拐点处的 k d i s t k_{dist} kdist作为 ε \varepsilon ε
    python 代码手肘法实现:
"""
    decide 'eps' according to 'MinPts'
    'MinPts'=n+1
"""
import numpy as np
from matplotlib import pyplot as plt
from sklearn.preprocessing import StandardScaler

class SelectEPS(object):
    
    def __init__(self,datapath):
        self.x=np.loadtxt(datapath)
        self.x_scale=StandardScaler().fit_transform(self.x)
        self.m,self.n=x.shape
        
    def select_eps(self):
        
        #初始化MinPts
        min_pts=self.n+1
        k_dist_list=[]
        #遍历样本点
        for i in range(self.m):
            p=self.x[i]
            p_to_other=self.l2(p)
        
            print("Current sample:",p)
            print("Distance of p with others:",p_to_other)
            k_dist_list.append(self.get_k_th_dist(min_pts,p_to_other))
            
        print(k_dist_list)
        
        k_dist_list_sort=np.sort(k_dist_list)[::-1]
        plt.scatter(range(self.m),k_dist_list_sort,marker="o")
        
        plt.xlabel("index")
        plt.ylabel("k_dist        ",rotation="horizontal")
        plt.title("k_dist of all samples")
        plt.show()
    
    def l2(self,x):
        """
            计算单个样本与样本集S内其他样本的距离
            x:single sample,1dim
            return:distance,1dim
        """
        return np.sqrt(np.sum((x-self.x)**2,axis=1))
        
    def get_k_th_dist(self,k,dist_list):
        """
            从包含0的几个距离中取最近的k个
        """
        #排序
        sort_dist=np.sort(dist_list)
        
        #取出第k近的值
        i=0
        while i<k:
            if sort_dist[i]==0:
                k+=1
                i+=1
                if i>len(sort_dist)-1:
                    return "no result"
                continue
            elif sort_dist[i]==sort_dist[i-1]:
                k+=1
                i+=1
                if i>len(sort_dist)-1:
                    return "no result"
                continue
            else:
                i+=1
                if i>len(sort_dist)-1:
                    return "no result"
        
        #取到除0外的第k个最近距离
        return sort_dist[i-1]
            
          
if __name__=="__main__":
    eps=SelectEPS("data.txt")
    eps.select_eps()
    
#    d=eps.get_k_th_dist(1,[0,0,0,0,0,1,1,1,2,2,2,3,4,4])
#    print(d) 

在这里插入图片描述

OPTICS聚类

Ordering Points To Identify Cluster Structure

  1. DBSCAN算法的衍生算法
  2. 引入可达距离,解决 ε \varepsilon ε参数确定的问题

定义

  1. 样本点 x i x_i xi的核心距离
    若样本点 x i x_i xi为核心点,则其有核心距离,否则没有核心距离
    如下图,在指定 ε \varepsilon ε距离阈值和MinPts=4时,
    样本点 x i x_i xi第一近邻点为本身(这里计入本身点),第二近邻点为样本2,第三近邻点为样本3 ( x 1 ) (x_1) (x1),第四(MinPts)近邻点为样本4,也就是说第MinPts近邻点在样本点 x i x_i xi ε \varepsilon ε邻域内,则样本点 x i x_i xi必为核心点,且其核心距离为样本点 x i x_i xi到第MinPts近邻点之间的距离,如图中 c ( x i ) c(x_i) c(xi)
    在这里插入图片描述
  2. 样本点 x j x_j xj到样本点 x i x_i xi的可达距离
    只有样本点 x i x_i xi为核心点时才被可达,否则这个可达距离不存在
    如上图样本点 x i x_i xi为核心点,则其 ε \varepsilon ε邻域内的点 x j x_j xj x i x_i xi的可达距离为:
    m a x ( d i j , c ( x i ) ) max(d_{ij},c(x_i)) max(dij,c(xi))
    d i j d_{ij} dij x i x_i xi x j x_j xj之间的距离
    c ( x i ) c(x_i) c(xi)为核心点 x i x_i xi的核心距离
    显然有
    x 1 x_1 x1 x i x_i xi的可达距离 r ( x 1 ) = c ( x i ) r(x_1)=c(x_i) r(x1)=c(xi)
    x 2 x_2 x2 x i x_i xi的可达距离 r ( x 2 ) = d i 2 r(x_2)=d_{i2} r(x2)=di2

OPTICS算法流程

  1. 对于样本集S, m 个 样 本 , n 个 特 征 m个样本,n个特征 mn
    初始化所有点的可达距离为inf, r e a c h _ d i s t = a r r a y ( [ n p . i n f ] ∗ m ) reach\_dist=array([np.inf]*m) reach_dist=array([np.inf]m)
    初始化根据可达距离从小到大排序的样本的列表全为0, o r d e r i n g = n p . z e r o s ( m , d t y p e = i n t ) ordering=np.zeros(m,dtype=int) ordering=np.zeros(m,dtype=int)
    初始化样本是否已处理的标记全为False, p r o c e s s e d = n p . z e r o s ( m , d t y p e = b o o l ) processed=np.zeros(m,dtype=bool) processed=np.zeros(m,dtype=bool)
  2. 假设 ε \varepsilon ε为inf,根据参数MinPts计算出所有点核心距离,记core_dist,核心距离大于 ε \varepsilon ε阈值,则不存在核心距离用inf 表示
  3. 从未处理的点中取当前可达距离最小的点 i d x = n p . a r g m i n ( r e a c h _ d i s t ) idx=np.argmin(reach\_dist) idx=np.argmin(reach_dist),放入 o r d e r i n g ordering ordering第一个位置,并标记是否处理为True, p r o c e s s e d [ i d x ] = T r u e processed[idx]=True processed[idx]=True,若当前 i d x idx idx样本具有核心距离,计算当前点 i d x idx idx p r o c e s s e d processed processed中为False的点之间的可达距离 r d i s t rdist rdist,若 r d i s t rdist rdist中的可达距离小于 r e a c h _ d i s t reach\_dist reach_dist中对应的可达距离值,则更新替换为 r d i s t rdist rdist中的值;若当前 i d x idx idx不具有核心距离(inf),即不是核心点,则不处理
  4. 重复3,取当前未处理的样本,即 p r o c e s s e d = F a l s e processed=False processed=False的样本,返回这些未处理的样本在 r e a c h _ d i s t reach\_dist reach_dist中可达距离最小的一个样本点 i d x idx idx,加入 o r d e r i n g ordering ordering的第二个位置,并标记是否处理为True, p r o c e s s e d [ i d x ] = T r u e processed[idx]=True processed[idx]=True. 是核心点则计算它与其他未处理的点的可达距离,否则不处理,直到所有的样本处理完,算法结束。

演示示例

有如下数据
x = [ 1 3 3 3 2 0.2 10 0.8 10.8 1.4 12 0.8 ] \begin{gathered} x=\begin{bmatrix} 1 & 3 \\ 3 & 3 \\ 2 & 0.2 \\ 10 &0.8 \\ 10.8&1.4\\ 12&0.8\end{bmatrix} \quad \end{gathered} x=1321010.812330.20.81.40.8
在这里插入图片描述

Python实现OPTICS

百度网盘:https://pan.baidu.com/s/1UUgK-uPfWpRopJ_C1FZY9w
提取码:i4tn

Sklearn库实现OPTICS

import numpy as np
from sklearn.cluster import OPTICS
from matplotlib import pyplot as plt
#load data
x=np.loadtxt("optics_sample.txt")

#instantiate
optics=OPTICS(max_eps=np.inf,eps=3,min_samples=3,cluster_method="dbscan")
optics.fit(x)

#按照可达距离从小到大排序的样本点
optics.ordering_
#[0,1,2,3,4,5]
#样本的可达距离
rdist=optics.reachability_[optics.ordering_]

#可视化可达距离
plt.plot(range(x.shape[0]),rdist,marker="o",markeredgewidth=3,linestyle="-")
plt.title("sklearn-optics")
plt.grid()
plt.xlabel("index")
plt.ylabel("reach dist")
plt.show()

排序样本的可达距离,每一个低谷为一个聚类簇
在这里插入图片描述
可视化聚类样本点:

y_pred=optics.labels_
plt.scatter(x[:,0],x[:,1],s=50,c=y_pred,marker="^",edgecolors=None,linewidths=1,cmap="cool")
plt.title("cluster samples")
plt.grid()
plt.xlabel("f1")
plt.ylabel("f2")
plt.axis("equal")
plt.show()

在这里插入图片描述

层次聚类

Birch

网格聚类

模型聚类

GMM高斯混合聚类

SOM自组织映射网络

猜你喜欢

转载自blog.csdn.net/weixin_45228198/article/details/112132990