
在數據科學和機器學習中,聚類算法是一種常用的非監督學習方法,旨在將數據分組,使同一組中的數據點之間的相似性最大化,而不同組之間的相似性最小化。根據不同的應用場景和數據特性,不同的聚類算法適合不同的數據集。
方法選擇參考
- K-means:當知道群集數量,並且數據呈現較為規則的球形結構時,選擇 K-means。
- DBSCAN:當數據包含噪音或異常值,且群集形狀不規則或密度不均時,選擇 DBSCAN。
- 層次聚類:當你想要探索數據的層次結構或進行小規模數據的聚類分析時,選擇層次聚類。
K-means
K-means 是一種基於劃分的聚類算法,它的核心思想是將數據集分成 K 個群集,使得每個數據點與其最近的群集中心的距離最小。
工作原理
- 初始化:隨機選擇 K 個初始群集中心(centroids)。
- 分配數據點:根據每個數據點與群集中心的距離,將每個數據點分配給最近的群集中心。
- 更新群集中心:重新計算每個群集的中心位置(即所有群集內數據點的均值)。
- 重複步驟 2 和 3:直到群集中心不再變動或變化非常小,達到收斂。
應用場景
- 市場細分:根據消費者行為和購買記錄,將客戶群體劃分成不同的細分市場。
- 文件分類:將大量文檔分成不同主題的群集。
- 圖像分割:根據圖像的顏色特徵,將圖像像素劃分為不同的區域。
程式碼範例
from sklearn.cluster import KMeans
from sklearn.datasets import load_iris
import pandas as pd
# 加載數據集(以 iris 為例)
data = load_iris()
X = data.data
# K-means 聚類,設置 K=3
kmeans = KMeans(n_clusters=3, random_state=42)
kmeans_labels = kmeans.fit_predict(X)
# 將結果轉換為 DataFrame 便於查看
df = pd.DataFrame(X, columns=data.feature_names)
df['Cluster'] = kmeans_labels
print(df.head()) # 顯示前幾個樣本和它們的群集標籤
"""
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) \
0 5.1 3.5 1.4 0.2
1 4.9 3.0 1.4 0.2
2 4.7 3.2 1.3 0.2
3 4.6 3.1 1.5 0.2
4 5.0 3.6 1.4 0.2
Cluster
0 1
1 1
2 1
3 1
4 1
"""
K-means 優點與缺點
優點:
- 簡單高效:計算效率高,特別適合大規模數據集。
- 易於理解和實現:K-means 的工作流程相對簡單,且廣泛應用於各個領域。
- 可擴展:可以使用 Mini-batch K-means 進行擴展,適合在線學習和即時處理。
缺點:
- 需要事先指定 K 值:必須提前指定群集數量 K,而且群集數的選擇可能需要多次嘗試。
- 對異常值敏感:異常值會顯著影響群集中心的位置,導致聚類效果不佳。
- 只能檢測球形群集:K-means 假設群集是球形的,對於形狀不規則的群集效果不佳。
- 依賴初始群集中心:K-means 的結果依賴於初始中心位置,不同的初始值可能導致不同的結果。
DBSCAN(Density-Based Spatial Clustering of Applications with Noise)
DBSCAN 是一種基於密度的聚類算法,它通過識別密度較高的區域來形成群集,同時能夠標識出噪音點。
工作原理
- 定義鄰域:給定一個鄰域半徑
eps
和最小點數min_samples
,算法會檢查每個數據點周圍有多少個點在eps
距離範圍內。 - 核心點、邊界點和噪音點:2-1 核心點:如果一個數據點周圍有超過
min_samples
個點在eps
範圍內,則該點是核心點。2-2 邊界點:不滿足核心點條件,但在其他核心點的eps
鄰域內的點。2-3 噪音點:既不是核心點,也不在任何核心點的鄰域內的點,標記為噪音點(label = -1)。 - 形成群集:從一個核心點開始,將所有相連的點(包括邊界點)歸入同一群集,直到不再有新的點可以加入該群集為止。
- 重複步驟:繼續檢查其他未被歸入群集的點,直到所有點都被處理。
應用場景
- 異常檢測:在信用卡欺詐檢測中,DBSCAN 能夠識別不規則行為並標記為異常點。
- 地理數據分析:分析地理分佈數據,識別密度較高的區域。
- 噪音數據處理:處理有噪音或異常值的數據集,例如感應器數據。
程式碼範例
from sklearn.cluster import DBSCAN
from sklearn.datasets import load_iris
from sklearn.preprocessing import StandardScaler
import pandas as pd
# 加載數據集(以 iris 為例)
data = load_iris()
X = data.data
# 標準化數據
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# DBSCAN 聚類
dbscan = DBSCAN(eps=0.5, min_samples=5)
dbscan_labels = dbscan.fit_predict(X_scaled)
# 將結果轉換為 DataFrame 便於查看
df = pd.DataFrame(X, columns=data.feature_names)
df['Cluster'] = dbscan_labels
print(df.head()) # 顯示前幾個樣本和它們的群集標籤
"""
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) \
0 5.1 3.5 1.4 0.2
1 4.9 3.0 1.4 0.2
2 4.7 3.2 1.3 0.2
3 4.6 3.1 1.5 0.2
4 5.0 3.6 1.4 0.2
Cluster
0 0
1 0
2 0
3 0
4 0
"""
DBSCAN 優點與缺點
優點:
- 不需要指定群集數:DBSCAN 不需要提前設定群集數,它會根據數據的密度自動形成群集。
- 能夠檢測任意形狀的群集:DBSCAN 可以識別不規則形狀的群集,而不僅僅是球形群集。
- 處理噪音點:DBSCAN 會自動將密度較低的點標記為噪音點,這對處理有異常值的數據非常有用。
缺點:
- 對不同密度的群集效果不佳:如果數據中的群集密度差異過大,DBSCAN 可能無法有效分辨不同群集。
- 參數敏感性:DBSCAN 的效果高度依賴於
eps
和min_samples
參數的選擇,選擇不當可能導致糟糕的聚類結果。 - 計算複雜度較高:DBSCAN 在高維數據集上的運行速度較慢。
層次聚類(Hierarchical Clustering)
層次聚類 是一種基於層次結構的聚類算法,它可以將數據從小群集逐步合併為大群集,也可以從大群集逐步分裂為小群集。層次聚類可以分為兩種類型:
- 凝聚型(Agglomerative Clustering):從每個數據點開始,逐步將最近的群集合併,直到只剩下一個群集。
- 分裂型(Divisive Clustering):從一個大群集開始,逐步將群集分裂成更小的群集。
凝聚型聚類(Agglomerative Clustering)
凝聚型聚類是從每個數據點開始,將最近的兩個群集合併,逐步形成較大的群集,最終所有數據點合併成一個群集。它是一種自底向上的方法。
工作原理
- 每個數據點是一個群集:初始時,每個數據點被視為一個單獨的群集。
- 計算群集之間的距離:計算每個群集與其他群集之間的距離,可以選擇不同的距離度量方法,如:2-1 最小距離法(Single Linkage):計算兩群集之間最近的兩個點的距離。2-2 最大距離法(Complete Linkage):計算兩群集之間最遠的兩個點的距離。2-3 平均距離法(Average Linkage):計算兩群集內所有點之間距離的平均值。2-4 質心法(Centroid Linkage):計算兩群集中心之間的距離。
- 合併最近的兩個群集:找到距離最近的兩個群集,將它們合併為一個新的群集。
- 更新距離矩陣:重新計算新合併的群集與其他群集之間的距離。
- 重複步驟:不斷合併最近的群集,直到所有數據點合併為一個群集,或達到預定的群集數。
應用場景
- 基因表達數據分析:用於基因的相似性聚類,研究不同基因之間的層次結構關係。
- 文檔分類:分析不同文檔之間的主題關聯性,進行層次分組。
- 客戶群分析:將不同特徵的客戶進行分組,展示客戶之間的層次關係。
程式碼範例
from sklearn.cluster import AgglomerativeClustering
from sklearn.datasets import load_iris
import pandas as pd
# 加載數據集(以 iris 為例)
data = load_iris()
X = data.data
# 凝聚型聚類
agg_clustering = AgglomerativeClustering(n_clusters=3)
agg_labels = agg_clustering.fit_predict(X)
# 將結果轉換為 DataFrame 便於查看
df = pd.DataFrame(X, columns=data.feature_names)
df['Cluster'] = agg_labels
print(df.head()) # 顯示前幾個樣本和它們的群集標籤
"""
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) \
0 5.1 3.5 1.4 0.2
1 4.9 3.0 1.4 0.2
2 4.7 3.2 1.3 0.2
3 4.6 3.1 1.5 0.2
4 5.0 3.6 1.4 0.2
Cluster
0 1
1 1
2 1
3 1
4 1
"""
凝聚型聚類 優點與缺點
優點:
- 不需要提前指定群集數:凝聚型聚類不需要事先指定群集數量,可以通過樹狀圖觀察群集數目。
- 生成層次結構:可以可視化整個聚類過程,清晰地展示數據點之間的層次關係,便於分析不同層級的聚類結果。
- 可以應用不同的距離度量方法:允許根據需求選擇不同的距離計算方法,靈活性高。
缺點:
- 計算複雜度高:凝聚型聚類的時間複雜度較高,對於大規模數據集不夠高效,通常為 O(n3)。
- 對異常值敏感:異常值會影響距離的計算,從而影響聚類結果。
- 無法回溯:一旦合併兩個群集,就無法撤回決策,這可能導致次優解。
分裂型聚類(Divisive Clustering)
分裂型聚類是從整個數據集作為一個群集開始,然後逐步將其分裂成更小的群集,直到每個數據點成為單獨的群集或達到預定的群集數量。它是一種自頂向下的方法。
工作原理
- 將所有數據點視為一個群集:初始時,所有數據點被視為一個大的群集。
- 選擇一個群集進行分裂:根據某種規則,選擇一個現有群集進行分裂。
- 分裂群集:將該群集分裂成兩個或多個子群集。這通常通過一些分裂標準(例如:K-means、二分法等)來實現。
- 更新群集結構:重新計算各子群集之間的距離關係。
- 重複步驟:不斷選擇群集進行分裂,直到達到所需的群集數或每個數據點都成為單獨的群集。
應用場景
- 社交網絡分析:用於分析社交網絡中的用戶層次結構,逐步將整個網絡分成更小的社群。
- 組織結構分析:分析企業或團隊內部的組織結構,逐步劃分不同的工作小組。
- 大型數據集分析:當數據量較大且整體結構較為復雜時,分裂型聚類有助於將數據逐步簡化成更小的部分。
程式碼範例
scikit-learn
並不直接支持分裂型聚類。常見的分裂型聚類可以通過 自頂向下 的策略來模擬,比如使用 K-means
或 二分法
進行每步的分裂。
這裡我們用二分法(通過 K-means)來模擬分裂型聚類:
from sklearn.cluster import KMeans
from sklearn.datasets import load_iris
import pandas as pd
# 自定義一個分裂型聚類函數,遞歸進行 K-means 分裂
def divisive_clustering(X, max_clusters=3):
# 初始情況,將所有數據視為一個群集
df = pd.DataFrame(X)
df['Cluster'] = 0 # 所有數據點都標記為群集 0
current_cluster = 0
while current_cluster < max_clusters:
# 對當前群集進行 K-means 分裂成 2 個子群集
cluster_data = df[df['Cluster'] == current_cluster].drop(columns=['Cluster'])
if len(cluster_data) > 1: # 當群集內有多於1個點時才進行分裂
kmeans = KMeans(n_clusters=2, random_state=42)
sub_clusters = kmeans.fit_predict(cluster_data)
# 更新群集標籤
df.loc[df['Cluster'] == current_cluster, 'Cluster'] = sub_clusters + current_cluster + 1
current_cluster += 1
return df
# 加載數據集(以 iris 為例)
data = load_iris()
X = data.data
# 執行分裂型聚類
df = divisive_clustering(X, max_clusters=3)
print(df.head()) # 顯示前幾個樣本和它們的群集標籤
"""
0 1 2 3 Cluster
0 5.1 3.5 1.4 0.2 3
1 4.9 3.0 1.4 0.2 3
2 4.7 3.2 1.3 0.2 3
3 4.6 3.1 1.5 0.2 3
4 5.0 3.6 1.4 0.2 3
"""
分裂型聚類 優點與缺點
優點:
- 層次結構明確:自頂向下的聚類方式能清晰展示數據如何逐步分裂成更小的群集。
- 靈活的分裂策略:可以使用不同的分裂策略來實現群集的劃分,根據需求進行調整。
- 適合全局性數據結構分析:適合分析數據的整體結構,尤其是當你對數據整體的結構感興趣時。
缺點:
- 計算複雜度高:與凝聚型聚類一樣,分裂型聚類的時間複雜度較高,尤其是當數據集規模較大時,分裂操作需要更多計算。
- 對初始分裂點敏感:初始選擇的分裂點對最終結果影響很大,次優的初始分裂可能導致整體分裂結果不佳。
- 不常用:分裂型聚類相對凝聚型聚類來說,應用較少,因為它在每一步需要進行整體分裂,計算代價更高。
凝聚型聚類 vs 分裂型聚類 對比
