聚類 DBSCAN簡介及Python實現

2021-08-19 17:39:54 字數 3882 閱讀 2439

dbscan是基於密度的聚類演算法。聚類效果比較好,不易受雜訊的影響,且不需要指定簇的個數。

以核心點為出發點,逐步擴充套件簇

核心點:若某點半徑eps球體內,樣本點個數超過minpts,則為核心點

邊界點:位於核心點的鄰域內, 但自身領域內樣本點個數不足minpts

雜訊點:不在任何核心點的鄰域內,自身也非核心點

import numpy as np

from collections import defaultdict, deque

import math

class

dbscan:

def__init__

(self):

self.eps = none

self.minpts = none

self.n = none

self.data = none

self.pair_dis = none

self.labels = none

self.cluster_labels = none

definit_param

(self, data):

# 初始化引數

self.data = data

self.n = data.shape[0]

self.pair_dis = self.cal_pair_dis()

self.cluster_labels = np.zeros(self.data.shape[0]) # 將所有點類標記設為 0

self.cal_pair_dis()

return

def_cal_dis

(self, p1, p2):

dis = 0

for i, j in zip(p1, p2):

dis += (i - j) ** 2

return math.sqrt(dis)

defcal_pair_dis

(self):

# 獲取每對點之間的距離

pair_dis = np.zeros((self.n, self.n))

for i in range(self.n):

for j in range(i + 1, self.n):

pair_dis[i, j] = self._cal_dis(self.data[i], self.data[j])

pair_dis[j, i] = pair_dis[i, j]

return pair_dis

def_cal_k_dis

(self, k):

# 計算每個點的k距離

kdis =

for i in range(self.n):

dis_arr = self.pair_dis[i, :]

inds_sort = np.argsort(dis_arr)

return kdis

defgraph2param

(self, minpts):

# 畫出k距離圖,決定引數eps, minpts

kdis = self._cal_k_dis(minpts)

kdis = sorted(kdis)

plt.plot(kdis)

plt.show()

return

defcal_eps_neighbors

(self):

# 計算某個點eps內距離點的集合

if self.eps is

none:

raise valueerror('the eps is not set')

neighs = defaultdict(list)

for i in range(self.n):

for ind, dis in enumerate(self.pair_dis[i]):

if dis <= self.eps and i != ind:

return neighs

defmark_core

(self, neighs):

# 標記核心點

if self.minpts is

none:

raise valueerror('the minpts is not set')

core_points =

for key, val in neighs.items():

if len(val) >= self.minpts: # 近鄰點數大於minpts則為核心點

return core_points

deffit(self):

# 訓練,對每個樣本進行判別

neighs = self.cal_eps_neighbors()

core_points = self.mark_core(neighs)

cluster_label = 0

q = deque()

for p in core_points:

ifnot self.cluster_labels[p]: # 若該核心點未被標記,則建立新簇, 簇標記加 1

cluster_label += 1

# 以當前核心點為出發點, 採用廣度優先演算法進行簇的擴充套件, 直到隊列為空,則停止此次擴充套件

while len(q) > 0:

p = q.pop()

self.cluster_labels[p] = cluster_label

for n in neighs[p]:

ifnot self.cluster_labels[n]: # 鄰域內的點未歸類,則加入該簇

self.cluster_labels[n] = cluster_label

if n in core_points: # 若鄰域內存在未標記的核心點,則依據該核心點繼續擴充套件簇(一定要未標記,否則造成死迴圈)

return

if __name__ == '__main__':

import matplotlib.pyplot as plt

from itertools import cycle

from sklearn.datasets import make_blobs

data, label = make_blobs(centers=5, cluster_std=1.5, random_state=5)

# plt.scatter(data[:, 0], data[:, 1])

# plt.show()

db = dbscan()

db.init_param(data)

# db.graph2param(5)

db.eps = 2.0

db.minpts = 5

db.fit()

defvisualize

(data, cluster_labels):

cluster = defaultdict(list)

for ind, label in enumerate(cluster_labels):

color = 'bgrym'

for col, label in zip(cycle(color), cluster.keys()):

if label == 0:

col = 'k'

partial_data = data[cluster[label]]

plt.scatter(partial_data[:, 0], partial_data[:, 1], color=col)

plt.show()

return

visualize(data, db.cluster_labels)

我的github

注:如有不當之處,請指正。

聚類演算法 DBSCAN

dbscan 是一種簡單的,基於密度的聚類演算法。本次實現中,dbscan 使用了基於中心的方法。在基於中心的方法中,每個資料點的密度通過對以該點為中心以邊長為 2 eps 的網格 鄰域 內的其他資料點的個數來度量。根據資料點的密度分為三類點 1 核心點 該點在鄰域內的密度超過給定的閥值 minps...

DBSCAN聚類演算法

基於密度定義,我們將點分為 dbscan演算法的本質就是隨大流,邊界點緊緊圍繞著核心點,他們抱團,不帶噪點玩兒 小團體多了,聯絡比較密切的小團體之間聚成了同個類 比較偏遠的小團體想要加入這個圈子,進不去,就單幹,我們自己玩自己的,聚成了另外的乙個類 一開始就被孤立的噪點吧,自然有自己的傲骨,接著孤芳...

DBSCAN 聚類演算法

dbscan演算法是一種基於密度聚類的演算法。核心概念 核心點 若某個點的密度達到演算法設定的閾值 即 r 鄰域內點的數量不小於 minpts 則其為核心點。直接密度可達 若某點p在點q的 r 鄰域內,且q是核心點,則稱p從q出發直接密度可達。密度可達 若有乙個點的序列q0 q1 qk,對任意qi從...