密度聚类算法总结

核心思想:使用一个点邻域内的邻居点数量衡量该点所在空间的密度,

                  找出形状不规则的聚类,不需要先确定聚类数量。

DBSCAN聚类需要两个参数:Eps,确定邻域范围(半径);MinPts,核心点的阈值(密度数量)。

核心点对应稠密区局内部的点,边界点对应稠密区边缘点,噪音点在稀疏区域。

密度:在某距离内含有对象的最小数目。
核心对象:如果一个对象的eps邻域内至少包含MinPt个对象,则称该对象是核心对象。
直接密度可达:给定集合D,如果 p 在 q 的eps邻域内,且 q 是一个核心对象,

                         则 p 是从 q 直接密度可达的。

                         eps 为一个超球体的半径,Minp就是这个超球体内的点。

密度可达:q 和 p 之间,有样本序列p1,p2,p3,……,pn, 其中p1=q, pn=p,

                  若Pi+1是由Pi直接密度可达的,则 p 是由 q 关于eps 和 MinPts 密度可达的。

                  即 p 不在核心对象 q 的邻域内,但在 q 邻域内点的邻域内。

DBSCAN算法:从选定的核心点出发,不断向密度可达的区域扩张,

                          得到含有核心点和边界点的最大化区域,区域中任意两点密度相连。

DBSCAN 需要访问 X 所有节点,复杂度取决于区域查询(获取节点的邻域)的次数,时间复杂度O(N^2);通常需要用 N 阶距离矩阵存储距离,避免重复计算,需要O(N^2)空间开销。

优点:无需指定聚类数目;可发现任意形状的聚类;可找到噪音,且对噪音敏感;

           只有两个参数;不依赖于节点的遍历顺序。

缺点:DBSCAN聚类效果依赖于距离公式的选取,常用欧几里得距离;

           但对高维数据,由于维度灾难,距离的度量变的不重要了。

           不适用于数据集中密度差异很大的情况,此时参数很难选择。

参数选择方法: 

半径:K距离可帮助设定半径r,就是找到突变点;可先选择一个点,计算到其它所有点的距离,

          从小到大排序,找到距离间差异最大的,使用前一个距离作为半径。

          例如计算得到的距离为 d1, d2, d3, d4, d5,其中d2和d3间差异最大,则使用 d2 作为半径。

          k距离需要做大量实验观察,很难一次性选准。

密度值:一般这个值都是偏小一些,然后进行多次尝试。

DBSCAN的可视化演示:Visualizing DBSCAN Clustering

评估方法:轮廓系数

  1. 计算样本 i 到同簇其它样本的平均距离 ai。ai越小,说明样本i越应该被聚类到该簇(将ai称为样本 i 到簇内不相似度)。
  2. 计算样本 i 到其它簇 Cj 的所有样本的平均距离 bij,称为样本 i 与簇 Cj 的不相似度。定义为样本 i 的簇间不相似度:bi=min(bi1,bi2,...,bik2)
  • si接近1,则说明样本i聚类合理
  • si接近-1,则说明样本i更应该分类到另外的簇
  • 若si近似为0,则说明样本i在两个簇的边界上

Sklearn 中的密度聚类 DBSCAN:

参数:DBSCAN 的重要参数分为两类,一是DBSCAN 本身的参数,一类是最近邻度量参数。

1)eps: DBSCAN 算法参数,即ϵ-邻域的距离阈值,和样本距离超过ϵ-的样本点不在ϵ-邻域内。默认值是0.5。一般需要通过在多组值里面选择一个合适的阈值。eps过大会有更多的点会落在核心对象的ϵ-邻域,此时类别数可能会减少, 本来不是一类的样本也会被划为一类。反之则类别数可能会增大,本来是一类的样本却被划分开。

2)min_samples: DBSCAN算法参数,即样本点要成为核心对象所需要的ϵ-邻域的样本数阈值。默认值是5.。一般需要通过在多组值里面选择一个合适的阈值。通常和eps一起调参。在eps一定的情况下,min_samples过大,则核心对象会过少,此时簇内部分本来是一类的样本可能会被标为噪音点,类别数会变多。反之min_samples过小的话,则会产生大量的核心对象,导致类别过少。

3)metric:最近邻距离度量参数。可以使用的距离度量较多,一般来说DBSCAN使用默认的欧式距离(即p=2的闵可夫斯基距离)就可以满足我们的需求。可以使用的距离度量参数有:

在sklearn源码中找到的距离各种距离公式名称,补充如下
PAIRWISE_DISTANCE_FUNCTIONS = {
    # If updating this dictionary, update the doc in both distance_metrics()
    # and also in pairwise_distances()!
    'cityblock': manhattan_distances,
    'cosine': cosine_distances,
    'euclidean': euclidean_distances,
    'haversine': haversine_distances,
    'l2': euclidean_distances,
    'l1': manhattan_distances,
    'manhattan': manhattan_distances,
    'precomputed': None,  # HACK: precomputed is always allowed, never called
    'nan_euclidean': nan_euclidean_distances,
}
['braycurtis', 'canberra', 'chebyshev', 'correlation', 'cosine', 'dice', 'hamming',
 'jaccard', 'kulsinski', 'mahalanobis', 'matching', 'minkowski', 'rogerstanimoto',
 'russellrao', 'seuclidean', 'sokalmichener', 'sokalsneath', 'sqeuclidean', 'yule',    
'wminkowski']

4)algorithm:最近邻搜索算法参数,autoball_tree(球树)、kd_tree(kd树)、brute(暴力搜索),默认是auto。如果输入样本特征是稀疏的时候,sklearn 都会用蛮力实现。一般情况使用默认的 ‘auto’就够了。 如果数据量很大或者特征也很多,用"auto"建树时间可能会很长,效率不高,建议选择KD树实现‘kd_tree’,如果发现‘kd_tree’速度比较慢或者已经知道样本分布不是很均匀时,可以尝试用‘ball_tree’。

5)leaf_size:最近邻搜索算法参数,为使用KD树或者球树时, 停止建子树的叶子节点数量的阈值。这个值越小,则生成的KD树或者球树就越大,层数越深,建树时间越长,反之生成的KD树或者球树会小,层数较浅,建树时间较短。默认是30.。此值一般只影响算法运行速度和使用内存大小,一般情况下可以不管它。

6) p: 最近邻距离度量参数。只用于闵可夫斯基距离和带权重闵可夫斯基距离中p值的选择,

       p=1为曼哈顿距离, p=2为欧式距离。如果使用默认的欧式距离不需要管这个参数。

DBSCAN 算法优缺点

优点:

  • 不需要事先给定cluster的数目
  • 可以发现任意形状的cluster
  • 能够找出数据中的噪音,且对噪音不敏感
  • 算法只需要两个输入参数
  • 聚类结果几乎不依赖节点的遍历顺序

缺点:

  • DBSCAN 算法聚类效果依赖距离公式的选取,最常用的距离公式为欧几里得距离。但是对于高维数据,由于维数太多,距离的度量已变得不是那么重要,密度定义更加困难
  • DBSCAN 算法不适合数据集中密度差异很小的情况

密度聚类对于密度变化不大,且有重叠的数据的效果不好,两个簇有重叠很容易被聚类为同一个簇

设置合适的参数,可以很好的聚类环形嵌套的数据

属性值

core_sample_indices_:核心对象数。
labels_:每个样本点的对应的类别,对于噪声点将赋值为-1。

import numpy as np
from collections import Counter
from sklearn.cluster import DBSCAN
model = DBSCAN(eps=0.1, min_samples=1, metric="cosine")
model.fit(X)

y_hat = model.labels_
unique_y_hat = np.unique(y_hat)
n_clusters = len(unique_y_hat) - (1 if -1 in y_hat else 0)
print("类别:", unique_y_hat, ";聚类簇数目:", n_clusters)
print(Counter(y_hat))

使用 cosine_similarity作为度量距离:

1. 使用余弦相似度作为距离度量标准预先计算距离矩阵,对距离矩阵预处理,使其符合定制的距离标准(可能类似于D = np.abs(np.abs(CD) -1),其中CD是余弦距离矩阵),metric为precomputed。

import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.cluster import DBSCAN

total_samples = 1000
dimensionality = 3
points = np.random.rand(total_samples, dimensionality)
cosine_distance = cosine_similarity(points)
# option 1) vectors are close to each other if they are parallel
bespoke_distance = np.abs(np.abs(cosine_distance) -1)
# option 2) vectors are close to each other if they point in the same direction
bespoke_distance = np.abs(cosine_distance - 1)
results = DBSCAN(metric='precomputed', eps=0.25).fit(bespoke_distance)

2. 余弦距离= 1-余弦相似度;可能导致sklearn实现在O(n2)中运行。

3. 可以通过 -cosinesimilarity 作为预先计算的距离矩阵,使用-0.75作为eps。

4. 仅制作一个二进制距离矩阵(不过在O(n2)内存中是如此之慢),其中余弦相似度的距离= 0大于阈值,否则为0。然后使用eps = 0.5的DBSCAN。仅当相似度>阈值时,才能显示距离。

聚类的确不是分类,群集未标记。如果将其压缩到一种预测心态中(这不是最好的主意),实际上是在无需学习的情况下进行预测的。因为没有标记的训练数据可用于聚类。必须根据现有的内容为数据创建新的标签。但是不能在单个实例上执行此操作,只能"批量预测"。

但分配新点的功能很有用,如下一个快速实现:

import numpy as np
import scipy as sp

def dbscan_predict(dbscan_model, X_new, metric=sp.spatial.distance.cosine):
    # Result is noise by default
    y_new = np.ones(shape=len(X_new), dtype=int)*-1

    # Iterate all input samples for a label
    for j, x_new in enumerate(X_new):
        # Find a core sample closer than EPS
        for i, x_core in enumerate(dbscan_model.components_):
            if metric(x_new, x_core) < dbscan_model.eps:
                # Assign label of x_core to x_new
                y_new[j] = dbscan_model.labels_[dbscan_model.core_sample_indices_[i]]
                break

    return y_new
def dbscan_predict(model, X):  # 采用最接近样本的核心点
    nr_samples = X.shape[0]
    y_new = np.ones(shape=nr_samples, dtype=int) * -1
    for i in range(nr_samples):
        diff = model.components_ - X[i, :]  # NumPy broadcasting
        dist = np.linalg.norm(diff, axis=1)  # Euclidean distance
        shortest_dist_idx = np.argmin(dist)
        if dist[shortest_dist_idx] < model.eps:
            y_new[i] = model.labels_[model.core_sample_indices_[shortest_dist_idx]]

    return y_new

也可尝试 sklearn HDBSCAN 中的approximate_predict对新点进行近似预测:

clusterer = hdbscan.HDBSCAN(min_cluster_size=15, prediction_data=True).fit(data)
test_labels, strengths = hdbscan.approximate_predict(clusterer, test_points)

谱聚类

基于谱图理论的一种聚类方法,具有在任意形状的样本空间上聚类并且收敛于全局最优解的优点。

  • 通过对样本数据的 拉普拉斯矩阵的特征向量进行聚类,从而达到对样本数据进行聚类的目的;本质是将聚类问题转换为图的最优划分问题 ,是一种点对聚类算法。

  • 谱聚类算法将数据集中的每个对象看做图的顶点V,将顶点间的相似度量化为相应顶点连接边E的权值w,这样就构成了一个基于相似度的无向加权图G(V,E),于是聚类问题就转换为图的划分问题。基于图的最优划分规则就是子图内的相似度最大,子图间的相似度最小。

谱聚类构建的主要步骤

  • 构建表示对象相似度的矩阵W
  • 构建度矩阵D(对角矩阵)
  • 构建拉普拉斯矩阵L
  • 计算矩阵L的前k个特征值的特征向量(k个列向量)
  • 将k个列向量组成矩阵U
  • 对矩阵U中的n行数据利用K-means或其它经典聚类算法进行聚类得出最终结果

应用场景

  • 图形聚类、计算机视觉、非凸球形数据聚类等

问题

  • 相似度矩阵的构建问题:业界一般使用高斯相似函数或者k近邻来作为相似度量,一般建议使用k近邻的方式来计算相似度权值
  • 聚类数目的给定
  • 如何选择特征向量
  • 如何提高谱聚类的执行效率

参考:

聚类算法初探(五)DBSCAN_peghoty-CSDN博客_dbscan

DBSCAN聚类算法——机器学习(理论+图解+python代码)_huacha__的博客-CSDN博客_dbscan聚类算法

用scikit-learn学习DBSCAN聚类 - 刘建平Pinard - 博客园

关于集群分析:Scikit-Learn:使用DBSCAN预测新点 | 码农家园

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值