Scikit-learn中的DBSCAN及應(yīng)用

DBSCAN

DBSCAN(Density-Based Spatial Clustering of Applications with Noise)算法將簇看做高密度區(qū)域以從低密度區(qū)域中區(qū)分開编兄。由于這個(gè)算法的一般性驮瞧,DBSCAN建立的簇可以是任何形狀的。相對(duì)的抬纸,K-means則假設(shè)簇是凸的。核樣本的概念是DBSCAN的重要成分,核樣本是指高密度區(qū)域的樣本琐旁。一個(gè)簇是由互相靠近的核樣本的集合以及靠近核樣本的非核樣本組成的集合組成的。這個(gè)算法有兩個(gè)參數(shù)猜绣,

min_sampleseps 灰殴,這兩個(gè)參數(shù)表示數(shù)據(jù)的稠密性。當(dāng)min_samples增加 或者 eps 減小的時(shí)候掰邢,意味著一個(gè)簇分類有更大的密度要求验懊。

若樣本在數(shù)據(jù)集中存在eps距離內(nèi)有至少min_samples擅羞,則該樣本可以成為核樣本。也用來定義邊緣樣本义图。核樣本是向量空間的高密度區(qū)域。通過找到一個(gè)核樣本召烂,找到其附近的核樣本碱工,再找到附近核樣本的附近的核樣本遞歸地建立由核樣本組成的簇。一個(gè)簇也包含鄰居是核樣本的非核樣本奏夫。

根據(jù)定義怕篷,任何核樣本是簇的一部分。任何距離核樣本至少eps距離非核樣本是異常值酗昼。

從下圖中可以看到廊谓,不同的顏色表示不同的簇。大圈圈表示算法定義的核樣本麻削,小圈圈表示仍是簇的組成部分的非核樣本蒸痹。黑色點(diǎn)表示異常值。

dbscan_results

實(shí)現(xiàn)

這個(gè)算法是有隨機(jī)性的呛哟,雖然標(biāo)簽會(huì)變化叠荠,但是核樣本始終屬于同一個(gè)簇。非確定性主要來自非核樣本的歸屬扫责。一個(gè)非核樣本可能距離兩個(gè)簇的非核樣本都小于eps 榛鼎。根據(jù)三角不等式,這兩個(gè)核樣本之間的距離大于eps鳖孤,否則他們會(huì)屬于同一個(gè)簇者娱。非核樣本將會(huì)屬于先產(chǎn)生的簇,而簇產(chǎn)生的先后順序是隨機(jī)的苏揣。不考慮數(shù)據(jù)集的順序黄鳍,算法是確定性的,相同數(shù)據(jù)上的 結(jié)果也會(huì)相對(duì)穩(wěn)定腿准。

當(dāng)先實(shí)現(xiàn)是使用球樹和線段樹來計(jì)算點(diǎn)的鄰居际起,這避免了計(jì)算時(shí)全距離矩陣⊥麓校可以使用一般的距離度量方法街望。

內(nèi)存消耗

當(dāng)前實(shí)現(xiàn)不是一個(gè)節(jié)約內(nèi)存的算法,因?yàn)樗⒘薻d-tree和ball-tree不能使用的成對(duì)的相似矩陣弟跑≡智埃可以繞過這個(gè)的方法如下:

  • 可以通過metric='precomputed'計(jì)算稀疏的半徑臨近圖,這會(huì)節(jié)省內(nèi)存使用孟辑。
  • 數(shù)據(jù)可以壓縮哎甲,或者使用BIRCH去掉數(shù)據(jù)中的重復(fù)值蔫敲。然后大量的數(shù)據(jù)集將由小部分?jǐn)?shù)據(jù)代表,可以使用sample_weight來擬合算法

使用說明

class sklearn.cluster.DBSCAN(eps=0.5, min_samples=5, metric='euclidean', algorithm='auto', leaf_size=30, p=None, n_jobs=1)

參數(shù) 說明
eps float炭玫,可選
min_samples int奈嘿,可選
metric string,用于計(jì)算特征向量之間的距離
algorithm {‘a(chǎn)uto’, ‘ball_tree’, ‘kd_tree’, ‘brute’}吞加,可選
leaf_size 傳遞給球樹裙犹,影響速度、內(nèi)存衔憨,根據(jù)情況自己選擇
p 明氏距離的冪次叶圃,用于計(jì)算距離
n_jobs CPU并行數(shù)
方法 說明
fit(X[, y, sample_weight]) 從特征矩陣進(jìn)行聚類
fit_predict(X[, y, sample_weight]) 實(shí)行聚類并返回標(biāo)簽(n_samples, n_features)
get_params([deep]) 取得參數(shù)
set_params(**params) 設(shè)置參數(shù)
屬性 類型 大小 說明
core_sample_indices_ array [n_core_samples] 核樣本的目錄
components_ array [n_core_samples, n_features] 訓(xùn)練樣本的核樣本
labels_ array [n_samples] 聚類標(biāo)簽。噪聲樣本標(biāo)簽為-1

例子

程序地址:http://scikit-learn.org/stable/auto_examples/cluster/plot_dbscan.html#sphx-glr-auto-examples-cluster-plot-dbscan-py

import numpy as np

from sklearn.cluster import DBSCAN
from sklearn import metrics
from sklearn.datasets.samples_generator import make_blobs
from sklearn.preprocessing import StandardScaler


##############################################################################
# Generate sample data
centers = [[1, 1], [-1, -1], [1, -1]]
X, labels_true = make_blobs(n_samples=750, centers=centers, cluster_std=0.4,
                            random_state=0)

X = StandardScaler().fit_transform(X)

##############################################################################
# Compute DBSCAN
db = DBSCAN(eps=0.3, min_samples=10).fit(X)
core_samples_mask = np.zeros_like(db.labels_, dtype=bool)
core_samples_mask[db.core_sample_indices_] = True
labels = db.labels_

# Number of clusters in labels, ignoring noise if present.
n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)

print('Estimated number of clusters: %d' % n_clusters_)
print("Homogeneity: %0.3f" % metrics.homogeneity_score(labels_true, labels))
print("Completeness: %0.3f" % metrics.completeness_score(labels_true, labels))
print("V-measure: %0.3f" % metrics.v_measure_score(labels_true, labels))
print("Adjusted Rand Index: %0.3f"
      % metrics.adjusted_rand_score(labels_true, labels))
print("Adjusted Mutual Information: %0.3f"
      % metrics.adjusted_mutual_info_score(labels_true, labels))
print("Silhouette Coefficient: %0.3f"
      % metrics.silhouette_score(X, labels))

##############################################################################
# Plot result
import matplotlib.pyplot as plt

# Black removed and is used for noise instead.
unique_labels = set(labels)
colors = plt.cm.Spectral(np.linspace(0, 1, len(unique_labels)))
for k, col in zip(unique_labels, colors):
    if k == -1:
        # Black used for noise.
        col = 'k'

    class_member_mask = (labels == k)

    xy = X[class_member_mask & core_samples_mask]
    plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=col,
             markeredgecolor='k', markersize=14)

    xy = X[class_member_mask & ~core_samples_mask]
    plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=col,
             markeredgecolor='k', markersize=6)

plt.title('Estimated number of clusters: %d' % n_clusters_)
plt.show()
../../_images/sphx_glr_plot_dbscan_001.png

應(yīng)用

關(guān)鍵在于調(diào)節(jié)前面提到的兩個(gè)參數(shù)践图,需要不斷修正掺冠。如果需要測(cè)試數(shù)據(jù),可以留言码党。

import scipy.io as sio
import numpy as np
from sklearn.cluster import DBSCAN
#from sklearn import metrics
import matplotlib.pyplot as plt

data_smile = sio.loadmat('data\smile.mat')

X = data_smile['smile'][:, :2]
labels_true = data_smile['smile'][:, 2]


db = DBSCAN(eps=0.05, min_samples=3).fit(X)
core_samples_mask = np.zeros_like(db.labels_, dtype=bool)
core_samples_mask[db.core_sample_indices_] = True
labels = db.labels_

# Number of clusters in labels, ignoring noise if present.
n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)
      

# Black removed and is used for noise instead.
unique_labels = set(labels)
colors = plt.cm.Spectral(np.linspace(0, 1, len(unique_labels)))
for k, col in zip(unique_labels, colors):
    if k == -1:
        # Black used for noise.
        col = 'k'

    class_member_mask = (labels == k)

    xy = X[class_member_mask & core_samples_mask]
    plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=col,
             markeredgecolor='k', markersize=14)

    xy = X[class_member_mask & ~core_samples_mask]
    plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=col,
             markeredgecolor='k', markersize=6)

plt.title('Estimated number of clusters: %d' % n_clusters_)
plt.show() 

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末德崭,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子闽瓢,更是在濱河造成了極大的恐慌接癌,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件扣讼,死亡現(xiàn)場(chǎng)離奇詭異缺猛,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)椭符,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門荔燎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人销钝,你說我怎么就攤上這事有咨。” “怎么了蒸健?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵座享,是天一觀的道長。 經(jīng)常有香客問我似忧,道長渣叛,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任盯捌,我火速辦了婚禮淳衙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己箫攀,他們只是感情好肠牲,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著靴跛,像睡著了一般缀雳。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上汤求,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天俏险,我揣著相機(jī)與錄音,去河邊找鬼扬绪。 笑死,一個(gè)胖子當(dāng)著我的面吹牛裤唠,可吹牛的內(nèi)容都是我干的挤牛。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼种蘸,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼墓赴!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起航瞭,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤诫硕,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后刊侯,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體章办,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年滨彻,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了藕届。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡亭饵,死狀恐怖休偶,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情辜羊,我是刑警寧澤踏兜,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站八秃,受9級(jí)特大地震影響碱妆,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜喜德,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一山橄、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦航棱、人聲如沸睡雇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽它抱。三九已至,卻和暖如春朴艰,著一層夾襖步出監(jiān)牢的瞬間观蓄,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來泰國打工祠墅, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留侮穿,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓毁嗦,卻偏偏與公主長得像亲茅,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子狗准,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容