国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【機器學(xué)習(xí)】DBSCAN算法

這篇具有很好參考價值的文章主要介紹了【機器學(xué)習(xí)】DBSCAN算法。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

參考鏈接:
https://blog.csdn.net/haveanybody/article/details/113092851
https://www.jianshu.com/p/dd6ce77bfb8a
https://blog.csdn.net/qq_38563206/article/details/120941479

1 介紹

DBSCAN(Density-Based Spatial Clustering of Applica tion with Noise)算法是于1996年提出的一種簡單的、有效的基于密度的聚類算法,該算法利用類的密度連通性快速發(fā)現(xiàn)任意形狀的類。該算法的中心思想是:對于一個類中的每一個點P(不包括邊界點),在給定的某個Eps鄰域內(nèi)數(shù)據(jù)點的個數(shù)不少于Minpts。

DBSCAN算法不屬于圖聚類算法。圖聚類算法是一種基于圖結(jié)構(gòu)的聚類算法,它利用圖中的頂點和邊的信息來劃分聚類。DBSCAN算法不需要構(gòu)建圖結(jié)構(gòu),它只需要計算數(shù)據(jù)點之間的距離,然后根據(jù)密度閾值和鄰域半徑來判斷數(shù)據(jù)點是否屬于某個聚類。

DBSCAN算法的主要優(yōu)點是:

  • 它可以發(fā)現(xiàn)任意形狀的聚類,而不是像K-means算法那樣只能發(fā)現(xiàn)球形的聚類。
  • 它可以識別噪聲點,并將它們從聚類中排除,而不是像層次聚類算法那樣將所有的數(shù)據(jù)點都分配到某個聚類中。
  • 它不需要事先指定聚類的個數(shù),而是根據(jù)數(shù)據(jù)的密度自動確定聚類的個數(shù)。

DBSCAN算法的主要缺點是:

  • 它對密度閾值和鄰域半徑的選擇非常敏感,不同的參數(shù)設(shè)置可能導(dǎo)致不同的聚類結(jié)果。
  • 它對高維數(shù)據(jù)的處理效果不佳,因為高維空間中的距離計算很難反映數(shù)據(jù)的真實相似度。
  • 它對不同密度的聚類的劃分效果不佳,因為它使用的是全局的密度閾值,而不是針對每個聚類的局部密度閾值。

2 代碼

2.1 直接調(diào)用sklearn的接口

本小節(jié)最后會給出完整代碼,在這之前,先對代碼中出現(xiàn)的一些關(guān)鍵點做一個簡單的筆記。

2.1.0 sklearn.cluster.DBSCAN接口

sklearn.cluster.DBSCAN(
    eps=0.5,
    min_samples=5,  # 指定核心樣本的最小樣本數(shù),鄰域內(nèi)至少需要有 min_samples 個樣本點(不包括樣本點自身)
    metric='euclidean',  # 距離度量方式,默認(rèn)是歐氏距離,具體選擇可參考KNN篇,選擇precomputed表示自己計算距離,fit時X傳入距離矩陣即可
    metric_params=None,  # metric的輔助參數(shù),根據(jù)metric的值決定
    algorithm='auto',  # 近鄰點的查找方法,可選‘a(chǎn)uto’, ‘ball_tree’, ‘kd_tree’, ‘brute’。默認(rèn)auto會根據(jù)樣本數(shù)量自動選擇,具體可參考前面KNN的文章
    leaf_size=30,  # BallTree or cKDTree參數(shù)
    p=None,  # 閔可夫斯基距離的p,默認(rèn)None就是2,表示歐式距離
    n_jobs=None
)

詳細(xì)參考:
https://scikitlearn.com.cn/0.21.3/22/#237-dbscan
https://scikit-learn.org.cn/view/379.html

2.1.1 數(shù)據(jù)標(biāo)準(zhǔn)化方法

# 生成包含750個樣本的聚類數(shù)據(jù)集,其中每個樣本屬于上述三個中心之一,cluster_std 控制聚類的標(biāo)準(zhǔn)差
X, labels_true = make_blobs(n_samples=750, centers=centers, cluster_std=0.4, random_state=0)
X = StandardScaler().fit_transform(X)  # 對樣本數(shù)據(jù)進行標(biāo)準(zhǔn)化處理,確保每個特征的均值為0,標(biāo)準(zhǔn)差為1
# X = MinMaxScaler().fit_transform(X)  # 對數(shù)據(jù)進行歸一化處理

數(shù)據(jù)預(yù)處理方法有很多,像常用的標(biāo)準(zhǔn)化、歸一化、特征工程之類,這里主要介紹一下標(biāo)準(zhǔn)化和歸一化。

標(biāo)準(zhǔn)化處理通常是為了確保不同特征的尺度一致,使得模型更容易收斂并提高算法的性能。雖然標(biāo)準(zhǔn)化處理在大多數(shù)情況下是有益的,但對于不規(guī)則數(shù)據(jù)(如存在極端離群值或不符合正態(tài)分布的數(shù)據(jù)),有時候可能需要謹(jǐn)慎處理。
對于不規(guī)則數(shù)據(jù),可以考慮使用其他數(shù)據(jù)預(yù)處理方法,例如:

  1. 歸一化(Normalization): 將數(shù)據(jù)縮放到一個固定的范圍,例如 [0, 1]。這對于受極端值影響較大的情況可能更合適。
  2. RobustScaler: 該方法對數(shù)據(jù)中的離群值具有魯棒性,因此在存在離群值的情況下可能更適用。
  3. 特征工程: 根據(jù)數(shù)據(jù)的特點進行定制的特征變換,以滿足特定的數(shù)據(jù)分布。

最終選擇哪種預(yù)處理方法取決于數(shù)據(jù)的性質(zhì)和模型的需求。在處理不規(guī)則數(shù)據(jù)時,建議進行實驗比較不同的方法,以找到最適合特定數(shù)據(jù)集的預(yù)處理策略。
歸一化(Normalization)和標(biāo)準(zhǔn)化(Standardization)是兩種不同的數(shù)據(jù)縮放方法,盡管它們的目標(biāo)都是使得特征在數(shù)值上更一致,但采用的處理方式略有不同。

  1. 歸一化: 歸一化的目標(biāo)是將數(shù)據(jù)縮放到一個固定的范圍,通常是 [0, 1]。最常見的歸一化方法是使用最小-最大縮放,公式為:

    X normalized = X ? X min X max ? X min X_{\text{normalized}} = \frac{X - X_{\text{min}}}{X_{\text{max}} - X_{\text{min}}} Xnormalized?=Xmax??Xmin?X?Xmin??

    這確保了所有特征的值都在 0 到 1 之間。

  2. 標(biāo)準(zhǔn)化: 標(biāo)準(zhǔn)化的目標(biāo)是使得數(shù)據(jù)的分布具有標(biāo)準(zhǔn)正態(tài)分布的特性,即均值為 0,標(biāo)準(zhǔn)差為 1。最常見的標(biāo)準(zhǔn)化方法是使用 Z 分?jǐn)?shù)標(biāo)準(zhǔn)化,公式為:

    X standardized = X ? μ σ X_{\text{standardized}} = \frac{X - \mu}{\sigma} Xstandardized?=σX?μ?

    其中 (\mu) 是均值,(\sigma) 是標(biāo)準(zhǔn)差。標(biāo)準(zhǔn)化處理后的數(shù)據(jù)集具有均值為 0,標(biāo)準(zhǔn)差為 1 的性質(zhì)。

雖然這兩種方法有不同的數(shù)學(xué)表達(dá)式,但它們的目的都是為了處理不同尺度的特征,使得模型更容易學(xué)習(xí)和收斂。選擇使用歸一化還是標(biāo)準(zhǔn)化通常取決于具體的任務(wù)和數(shù)據(jù)集的特點。

需要注意的是,在本文的示例代碼中,直接將X = StandardScaler().fit_transform(X)換成X = MinMaxScaler().fit_transform(X)最后計算輪廓系數(shù)的時候會報錯:ValueError: Number of labels is 1. Valid values are 2 to n_samples - 1 (inclusive),為啥我目前也還不知道,有知道的好兄弟記得評論區(qū)踢我。

2.1.2 算法評估指標(biāo)

當(dāng)對聚類結(jié)果進行評估時,這些指標(biāo)提供了關(guān)于聚類性能的不同方面的信息:

  1. 同質(zhì)性(Homogeneity): 衡量每個聚類中的成員是否都屬于同一類別。同質(zhì)性得分越高,表示聚類結(jié)果越好。
  2. 完整性(Completeness): 度量是否找到了每個真實類別的所有成員。完整性得分越高,表示聚類結(jié)果越完整。
  3. V-measure: 同質(zhì)性和完整性的調(diào)和平均,提供了對聚類結(jié)果的整體評估。
  4. 調(diào)整蘭德指數(shù)(Adjusted Rand Index): 用于度量聚類結(jié)果與真實標(biāo)簽之間的相似性,接近 1 表示較高的相似性。
  5. 調(diào)整互信息(Adjusted Mutual Information): 度量聚類結(jié)果與真實標(biāo)簽之間的信息一致性。
  6. 輪廓系數(shù)(Silhouette Coefficient): 用于度量聚類結(jié)果的緊密性和分離性,值越接近 1 表示聚類結(jié)果越好。

DBSCAN是一種無監(jiān)督聚類算法,它不要求輸入數(shù)據(jù)包含真實標(biāo)簽。在正常的使用情況下,DBSCAN 是無需真實標(biāo)簽的。然而,在示例代碼中,labels_true 是提供的真實標(biāo)簽,主要是用于驗證聚類算法的性能,以評估聚類結(jié)果與真實標(biāo)簽之間的相似性。

通常情況下,對于無監(jiān)督聚類算法,我們在實際應(yīng)用中不知道數(shù)據(jù)的真實標(biāo)簽,因此評估聚類算法的性能時使用的是無監(jiān)督的內(nèi)部評估指標(biāo),如輪廓系數(shù)、Calinski-Harabasz指數(shù)、DB指數(shù)等,它們不依賴于真實標(biāo)簽。這些指標(biāo)可以在沒有真實標(biāo)簽的情況下,通過對聚類結(jié)果自身進行評估,提供一些關(guān)于聚類質(zhì)量的信息。

  1. Calinski-Harabasz指數(shù)
    Calinski-Harabasz指數(shù)(也稱為方差比標(biāo)準(zhǔn))是一種用于評估聚類結(jié)果的有效性的指標(biāo)。它通過計算簇內(nèi)的離散度與簇間的分離度之間的比率來度量聚類的緊密度和分離度。指數(shù)值越高,表示聚類效果越好。

具體計算方式為:

Calinski-Harabasz指數(shù) = 簇間離散度 簇內(nèi)離散度 × 樣本數(shù)量 ? 簇數(shù)量 簇數(shù)量 ? 1 \text{Calinski-Harabasz指數(shù)} = \frac{\text{簇間離散度}}{\text{簇內(nèi)離散度}} \times \frac{\text{樣本數(shù)量} - \text{簇數(shù)量}}{\text{簇數(shù)量} - 1} Calinski-Harabasz指數(shù)=簇內(nèi)離散度簇間離散度?×簇數(shù)量?1樣本數(shù)量?簇數(shù)量?

其中,簇內(nèi)離散度是各個簇內(nèi)樣本與其簇內(nèi)均值的距離的總和,簇間離散度是所有簇中心與數(shù)據(jù)整體均值的距離的總和。

Calinski-Harabasz指數(shù)越高,表示簇間的分離度較高,簇內(nèi)的離散度較低,聚類效果越好。

在 scikit-learn 中,可以使用 metrics.calinski_harabasz_score 函數(shù)來計算Calinski-Harabasz指數(shù)。例如:

from sklearn import metrics
calinski_harabasz_score = metrics.calinski_harabasz_score(X, labels)
print("Calinski-Harabasz指數(shù):%0.3f" % calinski_harabasz_score)
  1. DB指數(shù)
    對于密度聚類算法(如DBSCAN),DB指數(shù)(Davies-Bouldin指數(shù))是一種用于評估聚類結(jié)果的指標(biāo)。DB指數(shù)考慮了簇的緊密度和分離度,越小的值表示聚類結(jié)果越好。

DB指數(shù)的計算方式是對每個簇,計算該簇內(nèi)每個點與簇內(nèi)其他點的平均距離(緊密度),然后找到與該簇最近的其他簇,計算兩個簇中心的距離(分離度)。DB指數(shù)是緊密度與分離度的加權(quán)平均值,公式如下:

D B = 1 k ∑ i = 1 k max ? j ≠ i ( S i + S j d ( C i , C j ) ) DB = \frac{1}{k} \sum_{i=1}^{k} \max_{j \neq i} \left( \frac{S_i + S_j}{d(C_i, C_j)} \right) DB=k1?i=1k?j=imax?(d(Ci?,Cj?)Si?+Sj??)

其中:

  • (k) 是簇的數(shù)量。
  • (S_i) 是簇內(nèi)點到簇中心的平均距離。
  • (d(C_i, C_j)) 是簇中心之間的距離。

DB指數(shù)的優(yōu)點是越小越好,表示簇內(nèi)緊密度越高,簇間分離度越好。但請注意,DB指數(shù)的計算也涉及到對距離的定義,這在密度聚類中可能涉及到一些具體的選擇。

在 scikit-learn 中,可以使用 metrics.davies_bouldin_score 函數(shù)來計算DB指數(shù)。例如:

from sklearn import metrics

db_score = metrics.davies_bouldin_score(X, labels)
print("DB指數(shù):%0.3f" % db_score)

DB指數(shù)是一種適用于密度聚類算法的評估指標(biāo),對于不同形狀和大小的簇都比較穩(wěn)健。

在計算DB指數(shù)時,涉及到對距離的定義,特別是在密度聚類中,選擇距離的度量方式可能會影響DB指數(shù)的計算結(jié)果。通常來說,DB指數(shù)的計算可以使用不同的距離度量方法,其中 Euclidean 距離是最常見的選擇。

在 scikit-learn 中,默認(rèn)的距離度量方式通常是 Euclidean 距離,因為 Euclidean 距離在許多情況下都是一種合理的選擇。然而,對于一些特定的密度聚類場景,也可以考慮使用其他距離度量方法,例如 Mahalanobis 距離,特別是當(dāng)數(shù)據(jù)具有不同的方差和協(xié)方差結(jié)構(gòu)時。

在使用 metrics.davies_bouldin_score 函數(shù)計算DB指數(shù)時,你可以通過傳遞 metric 參數(shù)來指定距離度量方式。例如,使用 Mahalanobis 距離:

from sklearn import metrics
from scipy.spatial.distance import mahalanobis

# 自定義 Mahalanobis 距離的度量方式
def mahalanobis_distance(X, Y):
    # 在這里實現(xiàn) Mahalanobis 距離的計算方式
    # ...

# 計算DB指數(shù),使用 Mahalanobis 距離
db_score = metrics.davies_bouldin_score(X, labels, metric=mahalanobis_distance)
print("DB指數(shù):%0.3f" % db_score)

需要注意的是,Mahalanobis 距離的計算需要對每個簇內(nèi)的協(xié)方差矩陣進行估計,這可能會增加計算的復(fù)雜性。選擇合適的距離度量方式應(yīng)該根據(jù)具體的數(shù)據(jù)特點和任務(wù)需求來進行。

  1. 輪廓系數(shù)
    輪廓系數(shù)(Silhouette Coefficient)是一種用于評估聚類結(jié)果好壞的指標(biāo),它結(jié)合了簇內(nèi)的緊密度和簇間的分離度。輪廓系數(shù)的取值范圍在 [-1, 1] 之間,具體定義如下:

對于每個樣本:

  1. 計算該樣本與同簇內(nèi)其他樣本的平均距離,記為 (a)(簇內(nèi)緊密度)。
  2. 計算該樣本與最近的其他簇中所有樣本的平均距離,記為 (b)(簇間分離度)。
  3. 輪廓系數(shù) (s) 的計算方式為 ( b ? a ) / max ? ( a , b ) (b - a) / \max(a, b) (b?a)/max(a,b)。

對于整個數(shù)據(jù)集,輪廓系數(shù)是所有樣本輪廓系數(shù)的平均值。

輪廓系數(shù)的解釋:

  • 輪廓系數(shù)接近1表示簇內(nèi)樣本距離緊密,簇間樣本距離相對較遠(yuǎn),聚類效果較好。
  • 輪廓系數(shù)接近0表示簇內(nèi)樣本距離和簇間樣本距離相近,表明聚類結(jié)果不清晰。
  • 輪廓系數(shù)接近-1表示簇內(nèi)樣本距離松散,簇間樣本距離較近,聚類效果差。

輪廓系數(shù)可以用于選擇合適的聚類數(shù)目,因為它在聚類數(shù)目選擇上的峰值通常對應(yīng)于較好的聚類結(jié)果。在使用輪廓系數(shù)時,需要注意對于某些不適合聚類的數(shù)據(jù)集,輪廓系數(shù)可能并不是一個有效的指標(biāo)。

2.1.3 繪圖顏色

colors = [plt.cm.Spectral(each) for each in np.linspace(0, 1, len(unique_labels))]

這行代碼用于生成一組顏色,以便在可視化中為不同的聚類標(biāo)簽選擇不同的顏色。

  • np.linspace(0, 1, len(unique_labels)): 生成一個從 0 到 1 的等差數(shù)列,數(shù)列的長度與聚類標(biāo)簽的數(shù)量相同。這個數(shù)列將用于確定顏色映射的位置,確保每個聚類標(biāo)簽都有一個對應(yīng)的顏色。
  • plt.cm.Spectral(each): 使用 Spectral 顏色映射,根據(jù)上面生成的等差數(shù)列中的每個值,獲取相應(yīng)位置的顏色。這樣就得到了一組不同的顏色,每個顏色對應(yīng)一個聚類標(biāo)簽。

這種方式確保了在可視化中使用了一組視覺上區(qū)分度較高的顏色,以區(qū)分不同的聚類。每個聚類標(biāo)簽都被分配一種顏色,使得在可視化中可以清晰地區(qū)分不同的簇。

2.1.4 完整代碼

import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import DBSCAN
from sklearn import metrics
from sklearn.datasets import make_blobs
from sklearn.preprocessing import StandardScaler, MinMaxScaler

# 生成三個聚類中心的樣本數(shù)據(jù)
centers = [[1, 1], [-1, -1], [1, -1], [-1,1]]

# 生成包含750個樣本的聚類數(shù)據(jù)集,其中每個樣本屬于上述三個中心之一,cluster_std 控制聚類的標(biāo)準(zhǔn)差
X, labels_true = make_blobs(n_samples=750, centers=centers, cluster_std=0.4, random_state=0)
X = StandardScaler().fit_transform(X)  # 對樣本數(shù)據(jù)進行標(biāo)準(zhǔn)化處理,確保每個特征的均值為0,標(biāo)準(zhǔn)差為1
# X = MinMaxScaler().fit_transform(X)  # 對數(shù)據(jù)進行歸一化處理

# 使用 DBSCAN 算法進行聚類
# eps 控制鄰域的半徑,min_samples 指定一個核心點所需的最小樣本數(shù)
db = DBSCAN(eps=0.3, min_samples=20).fit(X)

# 創(chuàng)建一個布爾掩碼,標(biāo)記核心樣本點
core_samples_mask = np.zeros_like(db.labels_, dtype=bool)   # 創(chuàng)建一個與 db.labels_ 具有相同形狀的全零數(shù)組,數(shù)據(jù)類型為布爾型
core_samples_mask[db.core_sample_indices_] = True   # 將核心樣本的位置標(biāo)記為True

# 獲取每個樣本點的聚類標(biāo)簽
labels = db.labels_  # labels_ 屬性可以返回聚類結(jié)果,-1表示是離群點。
# print(labels)

# 統(tǒng)計聚類結(jié)果的一些信息
n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)  # 計算聚類的數(shù)量,忽略噪聲點(標(biāo)簽為-1的點)
n_noise_ = list(labels).count(-1)  # 統(tǒng)計噪聲點的數(shù)量

print('估計的聚類數(shù)量:%d' % n_clusters_)
print('估計的噪聲點數(shù)量:%d' % n_noise_)
# 同質(zhì)性和完整性的得分越高越好
print("同質(zhì)性:%0.3f" % metrics.homogeneity_score(labels_true, labels))  # 同質(zhì)性,衡量每個群集中的成員是否都屬于同一類別
print("完整性:%0.3f" % metrics.completeness_score(labels_true, labels))  # 完整性,度量是否找到了每個真實類別的所有成員
print("V-measure:%0.3f" % metrics.v_measure_score(labels_true, labels))  # V-measure,同質(zhì)性和完整性的調(diào)和平均
# 調(diào)整蘭德指數(shù)越接近1,說明聚類結(jié)果與真實標(biāo)簽之間具有越高的相似度
print("調(diào)整蘭德指數(shù):%0.3f" % metrics.adjusted_rand_score(labels_true, labels))  # 調(diào)整蘭德指數(shù),用于度量聚類結(jié)果與真實標(biāo)簽之間的相似性
print("調(diào)整互信息:%0.3f" % metrics.adjusted_mutual_info_score(labels_true, labels))  # 調(diào)整互信息,度量聚類結(jié)果與真實標(biāo)簽之間的信息一致性
print("輪廓系數(shù):%0.3f" % metrics.silhouette_score(X, labels))  # 輪廓系數(shù),度量聚類結(jié)果的緊密性和分離性,接近1表示聚類結(jié)果越好
print("DB指數(shù):%0.3f" % metrics.davies_bouldin_score(X, labels))  # DB指數(shù),衡量簇內(nèi)緊密度和簇間分離度的指標(biāo),越小越好

# 畫圖
# 移除黑色(表示噪聲),用于標(biāo)識噪聲點
unique_labels = set(labels)  # 聚類得到的標(biāo)簽,即聚類得到的簇,標(biāo)記為{0,1,2,-1},其中-1為噪聲點
colors = [plt.cm.Spectral(each) for each in
          np.linspace(0, 1, len(unique_labels))]  # 生成一組顏色,以便在可視化中為不同的聚類標(biāo)簽選擇不同的顏色,color.shape=(4,4)
# 遍歷每個聚類標(biāo)簽,為每個簇選擇顏色進行可視化
for k, col in zip(unique_labels, colors):
    if k == -1:
        # 對于標(biāo)簽為-1的噪聲點,使用黑色
        col = (0, 0, 0, 1)

    # 獲取屬于當(dāng)前聚類的樣本點
    class_member_mask = (labels == k)

    # 繪制核心樣本點(大圓點)
    xy1 = X[class_member_mask & core_samples_mask]
    plt.plot(xy1[:, 0], xy1[:, 1], 'o', markerfacecolor=tuple(col),
             markeredgecolor='k', markersize=8)

    # 繪制非核心樣本點(小圓點)
    xy2 = X[class_member_mask & ~core_samples_mask]
    plt.plot(xy2[:, 0], xy2[:, 1], 'o', markerfacecolor=tuple(col),
             markeredgecolor='k', markersize=6)

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

2.2 不使用sklearn接口

從別處copy過來的代碼,加上了一些必要的注釋,代碼比較簡單就不寫詳細(xì)說明了哇。文章來源地址http://www.zghlxwxcb.cn/news/detail-802962.html

# -*- coding: utf-8 -*-
import math
import random
import matplotlib.pyplot as plt


class DBSCAN(object):
    STATUS_UNVISITED = 'unvisited'  # 數(shù)據(jù)點的訪問狀態(tài)
    STATUS_VISITED = 'visited'

    STATUS_GROUP = 1  # 數(shù)據(jù)點是否被分類到聚類簇
    STATUS_NOGROUP = 0

    data = dict()  # 類屬性,用于存儲數(shù)據(jù)點的信息

    def __init__(self, e, minPts):
        """
        e: 最小距離
        minPts: 最少樣本數(shù)量
        """
        self.e = e
        self.minPts = minPts

    def nearby(self, id):
        """
        返回與給定樣本點 id 在最小距離內(nèi)的鄰近樣本點列表
        """
        nearby_points = list()
        for link_id in self.scores[id]:  # self.score是距離矩陣,用字典或者二維列表表示
            if self.scores[id][link_id] <= self.e:  # 如果當(dāng)前樣本點id到link_id的距離小于鄰域半徑,則加入nearby_points列表
                nearby_points.append(link_id)

        return nearby_points

    def visit_nearby_points(self, points, group):
        """
        遞歸訪問與給定樣本點列表 points 在最小距離內(nèi)的鄰近樣本點,并將其加入 group 中
        """
        for id in points:
            if self.data[id]['is_visited'] == self.STATUS_VISITED \
                    and self.data[id]['is_group'] == self.STATUS_GROUP:
                continue
            self.data[id]['is_visited'] = self.STATUS_VISITED

            if self.data[id]['is_group'] == self.STATUS_NOGROUP:
                group.append(id)
                self.data[id]['is_group'] = self.STATUS_GROUP

            nearby_points = self.nearby(id)
            if len(nearby_points) >= self.minPts:
                self.visit_nearby_points(nearby_points, group)

    def fit(self, data_set, scores):
        """
        運行 DBSCAN 算法,返回聚類結(jié)果
        data_set: 輸入數(shù)據(jù)集
        scores: 樣本之間的距離矩陣或字典
        """
        self.scores = scores
        groups = list()

        # 初始化數(shù)據(jù)狀態(tài)
        for index, item in enumerate(data_set):
            self.data[index] = {'id': index,
                                'is_visited': self.STATUS_UNVISITED,
                                'is_group': self.STATUS_NOGROUP
                                }

        # 遍歷每個樣本點
        for id in self.data:  # self.data是一個字典,id是key
            if self.data[id]['is_visited'] == self.STATUS_VISITED:
                continue

            # 標(biāo)記樣本點為已訪問
            self.data[id]['is_visited'] = self.STATUS_VISITED
            nearby_points = self.nearby(id)

            # 如果鄰近樣本點數(shù)量大于等于最小樣本數(shù)量,則形成一個新的簇
            if len(nearby_points) >= self.minPts:
                group = list()
                group.append(id)
                self.data[id]['is_group'] = self.STATUS_GROUP
                self.visit_nearby_points(nearby_points, group)
                groups.append(group)

        # 處理未被歸為任何簇的樣本點
        for id in self.data:
            if self.data[id]['is_group'] == self.STATUS_NOGROUP:
                groups.append([id])
        # print(self.data)    # {0: {'id': 0, 'is_visited': 'visited', 'is_group': 1},...}
        return groups


def init_data(num, min, max):
    # 生成隨機數(shù)據(jù),data.shape=(num,2),即
    data = []
    for i in range(num):
        data.append([random.randint(min, max), random.randint(min, max)])

    return data


def mat_score(data_set):
    """
    計算輸入數(shù)據(jù)集中每兩個樣本點之間的歐式距離,并返回一個距離字典
    data_set: 輸入數(shù)據(jù)集,每個樣本點表示為 [x, y] 形式的坐標(biāo)
    """
    # 初始化距離字典
    score = dict()
    for i in range(len(data_set)):
        score[i] = dict()

    # 計算每兩個樣本點之間的歐式距離
    for i in range(len(data_set) - 1):
        j = i + 1
        while j < len(data_set):
            # 計算歐式距離
            distance = math.sqrt(abs(data_set[i][0] - data_set[j][0]) ** 2 + abs(data_set[i][1] - data_set[j][1]) ** 2)

            # 將距離保存到距離字典中
            score[i][j] = distance
            score[j][i] = distance
            j += 1

    return score


def show_cluster(data_set, groups):
    plt.title(u'DBSCAN')
    mark = ['or', 'ob', 'og', 'ok', '^r', '+r', 'sr', 'dr', '<r', 'pr']
    for index, group in enumerate(groups):
        for i in group:
            plt.plot(data_set[i][0], data_set[i][1], mark[index])

    plt.xlim(0.0, 100)
    plt.ylim(0.0, 100)
    plt.show()


if __name__ == '__main__':
    data_set1 = init_data(20, 0, 30)
    data_set2 = init_data(20, 40, 60)
    data_set3 = init_data(20, 70, 100)
    data_set = data_set1 + data_set2 + data_set3

    score_mat = mat_score(data_set)

    groups = DBSCAN(20, 5).fit(data_set, score_mat)
    show_cluster(data_set, groups)

到了這里,關(guān)于【機器學(xué)習(xí)】DBSCAN算法的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包