聚类--DBSCAN算法

文章目录

  • 算法原理
  • sklearn实现
  • python代码实现(聚类效果同sklearn一样)

算法原理

  1. DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一个比较有代表性的基于密度的聚类算法,能够将具有高密度的区域划分为簇,并且能够在具有噪声的样本中发现任意形状的簇。
  2. DBSCAN算法需要选择一种距离度量,计算两点之间的距离,反映点之间的密度,一般选择欧氏距离。
  3. 该算法需要输入两个参数:一个参数是半径(eps),表示以给定点P为中心的圆形邻域半径;另一个参数是以P为中心的圆形领域内最少包含点的数量(MinPts)。如果以点P为圆心、eps为半径的圆形领域内点的数量不少于MinPts,则成点P为核心点。
  4. 参数选取方法
    首先介绍k-距离概念。k-距离是指:计算给定数据点P(i)到数据集D(除去P(i))中各点的距离,按照升序排列,取第k个值作为该点的k-距离。对于聚类集合中的每个点P(i)都计算k-距离,得到集合E={e(1),e(2),…,e(n)}。
    (1)根据经验计算eps大小:绘制出集合E的变化曲线,将急剧发生变化的位置所对应k-距离的值作为eps的大小
    (2)根据经验确定MinPts的大小
    如果MinPts不变,eps值过大,会导致大多数点聚到一个簇,eps过小会导致一个簇的分裂;如果eps值不变,MinPts过小,会导致出现大量核心点,MinPts过大会导致同一个簇中的某些点变为噪声点。
  5. 算法流程
    输入:数据集D,参数(eps,MinPts)
    方法:(1)计算出数据集中的核心点集;(2)遍历所有核心点,对于该核心点和由该核心点密度可达的点划分为一个簇,贴上标签,对于已经贴上标签的核心点不再执行上述操作;最后数据集中几乎所有点均由标签,未有标签的点为噪声点。
    输出:含有类别划分标签的数据集

sklearn实现

模型:
sklearn.cluster.DBSCAN(eps=0.5, min_samples=5, metric=‘euclidean’, metric_params=None, algorithm=‘auto’, leaf_size=30, p=None, n_jobs=None)

  1. 主要参数为eps和min_sample(MinPts)
  2. 主要属性
    core_sample_indices_: ndarray of shape (n_core_samples,)
    components_: ndarray of shape (n_core_samples, n_features),Copy of each core sample found by training.
    labels_: ndarray of shape (n_samples),Cluster labels for each point in the dataset given to fit(). Noisy samples are given the label -1.
  3. 主要方法
    fit(X, y=None, sample_weight=None)

首先看下数据集分布是什么样的

#可视化数据
import numpy as np
import matplotlib.pyplot as plt
import scipy.io as sio
from sklearn.cluster import DBSCAN
%matplotlib notebook
path='D:\code\python\database\ex7data2'
data=sio.loadmat(path)
X=data['X']
plt.scatter(X[:,0],X[:,1])


利用sklearn模型聚类

model = DBSCAN(0.5,4)  #取eps=0.5,MinPts=4
model.fit(X)
print(set(model.labels_)) #输出聚类簇数
plt.scatter(X[:,0],X[:,1],c=model.labels_,cmap='rainbow')
{0, 1, 2, -1}





结果显示聚类簇数为3,蓝色点为噪声点

python代码实现(聚类效果同sklearn一样)

class DBSCAN_my:
    def __init__(self,eps,min_samples):
        self.eps = eps
        self.min_samples = min_samples

    def calCoreSamples(self,X):
        m = X.shape[0]
        core_samples = {}  #用字典保存核心对象集合
        for i in range(m):
            samples = []  #用列表保存核心对象密度直达的点
            count = 0
            for j in range(m):
                dist = np.sqrt(np.sum((X[i]-X[j])**2))
                if dist < self.eps:
                    samples.append(j)
                    count += 1
            if count > self.min_samples:
                samples.remove(i)
                core_samples[i] = samples
        return core_samples

    def cluster(self,value,core_samples,k):
        for i in value:
            if self.labels[i]==-1:
                self.labels[i] = k
                if i in core_samples:
                    self.cluster(core_samples[i],core_samples,k)


    def fit(self,X):
        #计算样本集的核心对象
        core_samples = self.calCoreSamples(X)
        #初始化样本集的标签,设置为-1
        self.labels = -np.ones(X.shape[0])
        k = 0 #用k表示类别
        #开始聚类
        for key,value in core_samples.items():
            if self.labels[key] == -1:
                #对该核心点设置标签
                self.labels[key] = k
                #对该核心点密度可达的样本点设置标签
                self.cluster(value,core_samples,k)
                k += 1

model = DBSCAN_my(0.5,4)
model.fit(X)
print(set(model.labels))
plt.scatter(X[:,0],X[:,1],c=model.labels,cmap='rainbow')
{0.0, 1.0, 2.0, -1.0}





你可能感兴趣的:(机器学习,聚类,算法,机器学习)