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從...