一、k-medoids聚類算法
k-medoids是一種聚類算法,它是基于k-means聚類算法的一種改進。k-medoids算法也是一種迭代算法,但是它將中心點限定為數據集中的實際樣本點,而不是任意的點。
具體來說,k-medoids算法從數據集中選擇k個初始中心點,然后將數據集中的每個樣本分配給最近的中心點,并計算每個中心點的總距離。接下來,算法會嘗試用一個未被選中的樣本替換每個中心點,并計算新的總距離,選擇總距離最小的替換。重復這個過程,直到中心點的位置不再改變或達到預定的迭代次數。
1.1 k-medoids與k-means算法的異同點
k-medoids算法是k-means算法的一個變種,它們都是聚類算法,但在一些方面有所不同。
相同點:
- 目標函數:k-medoids和k-means算法的目標都是將數據點劃分到k個簇中,使得簇內的數據點相似度最大化,簇間的相似度最小化。
- 選擇中心點:k-medoids和k-means算法都需要選擇k個中心點作為初始點,然后通過迭代算法來更新中心點,直到收斂。
- 簇分配:k-medoids和k-means算法都是通過計算數據點與中心點之間的距離來確定數據點的簇分配。
不同點:
- 中心點的選擇:k-medoids算法選擇的中心點必須是實際數據點,而k-means算法的中心點可以是任意點。
- 距離度量:k-medoids算法使用的是曼哈頓距離(或其他適合計算離散特征的距離度量),而k-means算法使用的是歐幾里德距離(適用于計算連續特征的距離度量)。
- 簇的劃分:k-medoids算法的簇劃分更加穩定,因為每個簇的中心點必須是實際數據點,而k-means算法的簇劃分可能會受到初始點的選擇影響,可能會得到不同的結果。
- 計算復雜度:k-medoids算法的計算復雜度要高于k-means算法,因為它需要計算每個數據點到中心點的距離,并選擇最近的中心點作為簇分配。
1.2 k-medoids算法原理和實例
k-medoids算法是一種聚類算法,它的原理是通過將數據集中的每個數據點分配給最近的一個中心點,然后重新計算每個中心點的位置,直到達到收斂的效果為止。
下面是k-medoids算法的步驟:
- 初始化k個中心點,可以隨機選擇k個數據點作為中心點。
- 對于每個數據點,計算其到所有中心點的距離,將它分配給距離最近的中心點。
- 對于每個中心點,計算它與其他被分配給它的數據點的總距離,選擇具有最小總距離的數據點作為新中心點。
- 重復步驟2和步驟3,直到中心點不再改變或達到最大迭代次數。
下面是一個簡單的示例代碼來實現k-medoids算法:
import numpy as npdef k_medoids(X, k):# 隨機初始化質心m, n = X.shapecentroids_idx = np.random.choice(m, size=k, replace=False)centroids = X[centroids_idx]# 迭代更新質心max_iter = 100for _ in range(max_iter):# 分配每個樣本到最近的質心distances = np.linalg.norm(X[:, np.newaxis] - centroids, axis=2)labels = np.argmin(distances, axis=1)# 更新質心為最小代價for i in range(k):cluster_X = X[labels == i]cluster_distances = np.linalg.norm(cluster_X[:, np.newaxis] - cluster_X, axis=2)costs = np.sum(cluster_distances, axis=1)best_idx = np.argmin(costs)centroids[i] = cluster_X[best_idx]return centroids, labels# 示例用法
X = np.array([[1, 2], [2, 1], [3, 2], [9, 10], [10, 9], [11, 10]])
k = 2
centroids, labels = k_medoids(X, k)print("質心:")
print(centroids)
print("標簽:")
print(labels)
該示例代碼中,X
是輸入數據的特征矩陣,k
是聚類的類別數。k_medoids
函數使用k-medoids算法進行聚類。它首先隨機選擇k個樣本作為質心,然后迭代更新質心和樣本的分配,直到達到最大迭代次數為止。最后返回最終的質心和樣本的標簽。
1.3 k-medoids聚類算法的優缺點
k-medoids聚類算法是一種基于劃分的聚類算法,優點和缺點如下:
優點:
- 不受離群值的影響:k-medoids聚類算法使用實際數據點作為聚類中心(medoids),因此對離群值不敏感。這使得k-medoids算法在處理存在離群值的數據集時表現較好。
- 適用于任意距離度量:k-medoids算法可以使用任意距離度量來計算數據點之間的相似度,因此可以適用于各種類型的數據集。這使得k-medoids算法在處理非歐幾里德空間的數據時具有靈活性。
- 可解釋性:k-medoids算法生成的聚類結果直觀易懂,因為每個聚類中心都是數據集中實際存在的數據點。
缺點:
- 對初始聚類中心的敏感性:k-medoids算法對初始聚類中心的選擇非常敏感,不同的初始中心可能會導致不同的聚類結果。因此,為了獲取穩定和準確的聚類結果,需要使用合適的初始聚類中心選擇方法。
- 計算復雜度高:k-medoids算法的計算復雜度較高,特別是在處理大規模數據集時。因為算法需要計算每個數據點到每個聚類中心的距離,并且在每一次迭代中都需要重新選擇最優的聚類中心。
1.4 k-medoids聚類算法的代碼實現
Sklearn 的正式發行版 0.22 并沒有提供 k-medoids 聚類模塊,但在 GitHub網站中,可下載 k-medoids聚類模塊的測試版,網址為https://github.com/terkkila/scikit-learn/tree/kmedoids/sklearn/clusterhttps://github.com/terkkila/scikit-learn/tree/kmedoids/sklearn/cluster在該頁面中,需要下載_ _init_ _.py和k_medoids_.py兩個文件,將其復制到 X:\Anaconda3\lib\site-packages\sklearn\cluster 目錄下(會替換掉原來的_ _init_ _.py文件),即可使用 k_medoids 聚類模塊。
k-medoids 聚類模塊實際上是一個 k_medoids類,k_medoids類的使用方法和 k-means類很相似,它的構造函數的參數有:①簇的個數 n_clusters;②初始簇中心的獲取方法 init();③獲取初始簇中心的更迭次數 n_init。
用 k_medoids聚類算法將數據聚成2類(數據文件km.txt)。
km.txt?文件內容如下:(與上篇文章中的相同)
import numpy as np
import matplotlib.pyplot as plt
from pyclust import KMedoids
import treelibX1, X2 = [], []
fr = open('km.txt')
for line in fr.readlines():lineArr = line.strip().split()X1.append([int(lineArr[0])])X2.append([int(lineArr[1])])
X = np.array(list(zip(X1, X2))).reshape(len(X1), 2)model = KMedoids(2).fit(X) # 調用估計器fit()方法進行聚類,聚類數為2
colors = ['b', 'g', 'r', 'c']
markers = ['o', 's', 'x', 'o']for i, l in enumerate(model.labels_):plt.plot(X1[i], X2[i], color=colors[l], marker=markers[i], ls='None')# 下面用X形繪制中心點
centroids = model.cluster_centers_ # centroids保存了所有中心點for i in range(2):plt.plot(centroids[i][0], centroids[i][1], markers[2])
plt.show()
二、DBSCAN聚類算法
DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一種基于密度的聚類算法。它通過將數據點劃分為核心點、邊界點和噪音點來進行聚類。DBSCAN算法的基本思想是尋找具有足夠密度的數據點,將它們劃分為一個簇,并通過連接具有足夠密度的相鄰數據點來擴展該簇。
2.1 DBSCAN聚類算法中的幾個定義
- ?-領域:?-領域是指一個點周圍半徑為?的范圍內的所有點的集合。具體地說,對于給定的一個點p,其?-領域包括了所有與p的距離小于等于?的點。
- 核心對象:核心對象是指一個數據點,如果在指定的半徑r內至少有minPts個數據點,則該數據點被視為核心對象。具體來說,一個核心對象需要滿足以下兩個條件:
- 這些數據點必須是在半徑r內的,即它們之間的距離必須小于等于r。
- 在半徑r內至少有minPts個數據點,包括自身。
- 密度可達:對于DBSCAN算法中的一個樣本點p,如果存在樣本點q,使得q在p的ε領域內,并且q的密度達到了MinPts的要求,那么我們稱q在以p為中心的ε領域內與p密度可達。而如果存在一系列樣本點p1,p2,...,pn,使得p1與p2密度可達,p2與p3密度可達,...,pn-1與pn密度可達,那么我們稱pn在以p1為中心的ε領域內與p1密度可達。
- 直接密度可達:對于DBSCAN算法中的一個樣本點A,如果在半徑ε內存在另一個樣本點B,且B在A的ε-鄰域內,即距離A小于等于ε,則樣本點A的直接密度可達于樣本點B。
2.2 DBSCAN聚類算法步驟
DBSCAN (Density-Based Spatial Clustering of Applications with Noise) 是一種聚類算法,用于在基于密度的空間中發現聚類。
DBSCAN算法的步驟如下:
- 初始化參數:設置半徑ε和最小點數MinPts。
- 計算密度:對于數據集中的每個數據點,計算它的ε-鄰域內的點的數量。如果該數量大于等于MinPts,則將該點標記為核心點。
- 標記邊界點:對于每個核心點,將其ε-鄰域內的點(不包括核心點)標記為邊界點。
- 構建聚類:初始化一個空的聚類集合,并對每個核心點執行以下步驟: a. 如果該核心點尚未被訪問過,則創建一個新的聚類,并將其加入到聚類集合中。 b. 將該核心點加入到當前聚類中。 c. 對于該核心點的ε-鄰域內的所有點,如果該點是核心點,則將其加入到當前聚類中;如果該點是邊界點且尚未被訪問過,則將其加入到當前聚類中,并標記為已訪問。
- 標記噪音點:對于所有未被訪問過的點,如果其不屬于任何聚類,則將其標記為噪音點。
- 輸出結果:返回聚類集合。
2.3 DBSCAN聚類算法舉例
假設有一組二維數據點,如下所示:
數據點1:(2, 3) 數據點2:(4, 5) 數據點3:(6, 7) 數據點4:(9, 10) 數據點5:(11, 12) 數據點6:(13, 14) 數據點7:(15, 16) 數據點8:(16, 17) 數據點9:(18, 19)
首先,我們需要選擇兩個參數:鄰域半徑eps和最小密度minPts。鄰域半徑eps決定了一個點的鄰域范圍,而最小密度minPts決定了一個核心點所需要的鄰域內的最小數據點數。
假設我們選擇eps=2和minPts=3,然后進行DBSCAN聚類算法。
- 隨機選擇一個未訪問的數據點,比如數據點1。
- 檢查數據點1的鄰域內是否有至少minPts個數據點。
- 數據點2和數據點3在數據點1的鄰域內,那么數據點1為核心點,并且將數據點2和數據點3添加到同一個簇中。
- 數據點4、數據點5、數據點6和數據點7不在數據點1的鄰域內,不滿足最小密度要求。
- 數據點8和數據點9不在數據點1的鄰域內,不滿足最小密度要求。
- 隨機選擇一個未訪問的核心點,比如數據點2。
- 檢查數據點2的鄰域內是否有至少minPts個數據點。
- 數據點3在數據點2的鄰域內,那么數據點2為核心點,并且將數據點3添加到同一個簇中。
- 數據點1不在數據點2的鄰域內,不滿足最小密度要求。
- 隨機選擇一個未訪問的核心點,比如數據點3。
- 檢查數據點3的鄰域內是否有至少minPts個數據點。
- 數據點2在數據點3的鄰域內,那么數據點3為核心點,并且將數據點2添加到同一個簇中。
- 數據點1不在數據點3的鄰域內,不滿足最小密度要求。
- 繼續選擇下一個未訪問的核心點,并進行相同的操作,直到所有的核心點都被訪問過為止。
- 如果還有未訪問的數據點,則將其標記為噪聲點。
根據上述步驟,我們可以得到以下聚類結果:
- 簇1:數據點1、數據點2、數據點3
- 噪聲點:數據點4、數據點5、數據點6、數據點7、數據點8、數據點9
2.4 DBSCAN聚類算法的優缺點
DBSCAN(Density-Based Spatial Clustering of Applications with Noise)聚類算法的優點和缺點如下:
優點:
- 不需要事先指定聚類數量,能夠自動發現數據中的聚類。
- 能夠處理任意形狀的聚類,并且對噪聲數據具有較強的魯棒性。
- 對于較大的數據集,DBSCAN算法具有較高的計算效率。
- 對于具有不同密度的聚類,DBSCAN能夠自適應地調整聚類的形狀和大小。
缺點:
- 對于高維數據,DBSCAN聚類算法表現不佳,容易出現維度災難。
- 對于數據集中密度不均勻的聚類,DBSCAN算法可能難以找到合適的聚類結果。
- 對于數據集中聚類之間存在較大密度差距的情況,DBSCAN算法可能無法準確地劃分聚類。
- 對于數據集的參數選擇較為敏感,需要事先對參數進行調優。
2.5 Sklearn實現DBSCAN聚類算法
使用sklearn庫實現DBSCAN聚類算法對三維點進行聚類的示例代碼:
from sklearn.cluster import DBSCAN
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt# 生成示例數據集
np.random.seed(0)
n_samples = 150
X = np.random.randn(n_samples, 3)# 使用DBSCAN聚類算法進行聚類
dbscan = DBSCAN(eps=0.4, min_samples=10)
y_pred = dbscan.fit_predict(X)# 繪制聚類結果
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
colors = ['blue', 'green', 'red', 'purple', 'yellow']
for i in range(len(np.unique(y_pred))):ax.scatter(X[y_pred == i, 0], X[y_pred == i, 1], X[y_pred == i, 2], c=colors[i], label='Cluster {}'.format(i))
ax.set_xlabel('Feature 1')
ax.set_ylabel('Feature 2')
ax.set_zlabel('Feature 3')
ax.set_title('DBSCAN Clustering')
plt.legend()
plt.show()
在上述代碼中,我們使用np.random.randn
函數生成了一個包含150個三維點的示例數據集。然后,我們使用DBSCAN
類初始化了一個DBSCAN聚類算法的實例,并指定了eps
和min_samples
參數。最后,我們調用fit_predict
方法對數據進行聚類,并將聚類結果繪制在三維散點圖中。
三、OPTICS聚類算法
OPTICS(Ordering Points To Identify the Clustering Structure)是一種基于密度的聚類算法,它通過識別數據集中的密度相對較高的區域來發現聚類結構。與傳統的基于密度的聚類算法DBSCAN不同,OPTICS不需要設置鄰域大小參數,而是通過自適應地計算鄰域大小來進行聚類。
OPTICS算法的基本思想是,對于數據集中的每個點,計算它與其他點之間的距離,然后根據距離將數據點排序。通過這種排序方式,OPTICS算法可以在每個數據點的鄰域中找到密度相對較高的數據點,從而識別出聚類的結構。
OPTICS算法的輸出結果是一個可達距離圖(Reachability Plot),它可以用于確定聚類的閾值參數,從而將數據點分為不同的聚類簇。通過分析可達距離圖,可以識別出密度相對較高的聚類簇和稀疏區域。
OPTICS算法的主要步驟如下:
- 計算每個數據點與其他點之間的距離,構建距離矩陣。
- 根據距離矩陣,計算每個數據點的核心距離(core distance)。核心距離是一個自適應的鄰域大小,用于判斷一個點是否是核心點(core point)。
- 根據核心距離和距離矩陣,計算每個數據點的可達距離(reachability distance)。可達距離表示從一個數據點到另一個數據點的最短路徑的最大距離。
- 根據可達距離,構建可達距離圖。
- 分析可達距離圖,確定聚類的閾值參數,將數據點分為不同的聚類簇。
3.1 Sklearn實現OPTICS聚類算法
使用sklearn庫中的cluster.OPTICS
類來實現OPTICS聚類算法。
下面是一個使用sklearn庫實現OPTICS聚類算法的示例代碼:
from sklearn.cluster import OPTICS
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt# 生成示例數據
X, y = make_blobs(n_samples=200, centers=4, random_state=0)# 創建OPTICS聚類模型
optics = OPTICS(min_samples=10, xi=0.05, min_cluster_size=0.1)# 擬合數據
optics.fit(X)# 獲取聚類標簽
labels = optics.labels_# 獲取核心樣本的可達距離
reachability_distances = optics.reachability_# 繪制聚類結果
unique_labels = set(labels)
colors = [plt.cm.Spectral(each) for each in np.linspace(0, 1, len(unique_labels))]for label, color in zip(unique_labels, colors):if label == -1:color = [0, 0, 0, 1] # 將噪聲樣本用黑色表示class_member_mask = (labels == label)xy = X[class_member_mask]plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=tuple(color),markeredgecolor='k', markersize=14)# 顯示聚類結果
plt.title('OPTICS clustering')
plt.show()
在上述示例代碼中,make_blobs
函數用于生成示例數據。OPTICS
類是OPTICS聚類算法的實現類,通過調用fit
方法可以擬合數據并進行聚類。labels_
屬性用于獲取聚類標簽。reachability_
屬性用于獲取核心樣本的可達距離。