Python-sklearn-聚类

Sklearn 聚类算法

sklearn.cluster 提供 K-Means、层次聚类、DBSCAN、GMM 等经典聚类算法。


🎯 基于划分的聚类

1. KMeans — K 均值聚类 ⭐

from sklearn.cluster import KMeans

model = KMeans(
    n_clusters=8,              # 簇的数量
    init='k-means++',          # 'k-means++' 或 'random' 或 ndarray
    n_init='auto',             # 初始化运行次数('auto'=1 次,int=多次取最优)
    max_iter=300,              # 单次运行的最大迭代次数
    tol=1e-4,                  # 收敛容忍度
    verbose=0,
    random_state=42,
    copy_x=True,
    algorithm='lloyd'          # 'lloyd','elkan'(密集数据快),'full','auto'
)

model.fit(X)

# 核心属性
print(model.cluster_centers_)  # 簇中心 (n_clusters, n_features)
print(model.labels_)           # 每个样本的簇标签
print(model.inertia_)          # 样本到最近簇中心的平方距离之和 ⭐
print(model.n_iter_)           # 迭代次数
print(model.n_features_in_)    # 特征数

# 预测新样本
labels = model.predict(X_new)
# 将新样本分配到最近簇

# 变换(到各簇中心的距离)
distances = model.transform(X)
# (n_samples, n_clusters) → 可以用作降维特征

# 一步到位
labels = model.fit_predict(X)

2. MiniBatchKMeans — 小批量 K 均值

from sklearn.cluster import MiniBatchKMeans

model = MiniBatchKMeans(
    n_clusters=8,
    init='k-means++',
    max_iter=100,
    batch_size=1024,         # 每批样本数
    verbose=0,
    random_state=42,
    tol=0.0,
    max_no_improvement=10,   # 连续无改善轮数
    init_size=None,          # 初始化的样本数
    n_init=3,
    reassignment_ratio=0.01  # 重新分配中心的比例
)

model.fit(X)

# 支持 partial_fit(在线学习)
model.partial_fit(X_batch)

📊 基于密度的聚类

1. DBSCAN — 密度聚类 ⭐

from sklearn.cluster import DBSCAN

model = DBSCAN(
    eps=0.5,               # 邻域半径
    min_samples=5,         # 核心点所需的最小邻域点数
    metric='euclidean',    # 距离度量
    metric_params=None,
    algorithm='auto',      # 'auto','ball_tree','kd_tree','brute'
    leaf_size=30,          # BallTree/KDTree 的叶大小
    p=None,                # Minkowski 度量的幂参数
    n_jobs=None
)

model.fit(X)

# 核心属性
print(model.labels_)        # -1=噪音, >=0=簇标签
print(model.core_sample_indices_)  # 核心样本的索引
print(model.components_)    # 每个核心样本的副本

# 注意: DBSCAN 没有 predict 方法!
# 对新数据需使用训练后的 dbscan 作为 nearest neighbors 查询

调参指南:

from sklearn.neighbors import NearestNeighbors
import numpy as np
import matplotlib.pyplot as plt

# K-距离图选择合适的 eps
k = 5  # 一般取 min_samples 值
nbrs = NearestNeighbors(n_neighbors=k).fit(X)
distances, indices = nbrs.kneighbors(X)
k_dist = np.sort(distances[:, -1])

plt.plot(k_dist)
plt.xlabel('Points sorted by distance')
plt.ylabel(f'{k}-NN distance')
plt.title('K-distance Graph (elbow method)')
plt.show()
# 曲线的"肘部"即为合适的 eps

2. OPTICS — 排序点识别聚类结构

from sklearn.cluster import OPTICS

model = OPTICS(
    min_samples=5,
    max_eps=np.inf,        # 最大邻域半径
    metric='minkowski',
    p=2,
    cluster_method='xi',   # 'xi' 或 'dbscan'
    eps=None,              # 提取簇的阈值(cluster_method='dbscan' 时需要)
    xi=0.05,               # 最小陡度(cluster_method='xi' 时)
    predecessor_correction=True,
    min_cluster_size=None,  # 最小簇大小
    algorithm='auto',
    leaf_size=30,
    n_jobs=None
)

model.fit(X)

print(model.labels_)           # 簇标签(-1=噪音)
print(model.reachability_)     # 可达距离
print(model.ordering_)         # 簇排序
print(model.core_distances_)   # 核心距离
print(model.predecessor_)      # 前驱索引

3. HDBSCAN — 层次 DBSCAN

from sklearn.cluster import HDBSCAN

model = HDBSCAN(
    min_cluster_size=5,        # 最小簇大小
    min_samples=None,          # 保守性(越大越保守)
    cluster_selection_epsilon=0.0,
    max_cluster_size=None,     # 最大簇大小
    metric='euclidean',
    alpha=1.0,                 # 距离持久性
    algorithm='auto',
    leaf_size=40,
    n_jobs=None,
    cluster_selection_method='eom',  # 'eom'(Excess of Mass) 或 'leaf'
    allow_single_cluster=False,
    store_centers=None
)

model.fit(X)

print(model.labels_)
print(model.probabilities_)          # 每个样本的簇成员强度 (0~1)
print(model.cluster_persistence_)    # 每个簇的持久性分数

# HDBSCAN 特有的方法
soft_clusters = model.membership_vector()  # 软聚类向量

🏗️ 基于层次的聚类

1. AgglomerativeClustering — 凝聚层次聚类 ⭐

from sklearn.cluster import AgglomerativeClustering

model = AgglomerativeClustering(
    n_clusters=2,               # 目标簇数
    metric='euclidean',         # 距离度量
    linkage='ward',             # 链接准则
    # 'ward'     — 最小方差(仅 euclidean)
    # 'complete' — 最大距离(最远邻)
    # 'average'  — 平均距离
    # 'single'   — 最小距离(最近邻)
    connectivity=None,          # 连接性约束矩阵
    compute_distances=False,    # 存储距离矩阵
    distance_threshold=None,    # 距离阈值(代替 n_clusters)
)

model.fit(X)

print(model.labels_)
print(model.n_clusters_)        # 估计的簇数
print(model.n_leaves_)          # 树的叶节点数
print(model.children_)          # 每个合并步骤的子节点 (2, n_samples-1)
print(model.distances_)         # 每个合并步骤的距离(compute_distances=True)

使用距离阈值而非指定 K:

model = AgglomerativeClustering(
    n_clusters=None,
    distance_threshold=0,   # 设置为 0 会计算全树
    linkage='ward'
)
model.fit(X)

2. FeatureAgglomeration — 特征凝聚

from sklearn.cluster import FeatureAgglomeration

model = FeatureAgglomeration(
    n_clusters=2,
    metric='euclidean',
    linkage='ward',
    pooling_func=np.mean  # 合并后特征的聚合函数
)

X_reduced = model.fit_transform(X)
print(model.labels_)      # 每个原始特征的簇标签

3. Birch — 层次聚类(大数据友好)

from sklearn.cluster import Birch

model = Birch(
    threshold=0.5,          # 子簇合并阈值
    branching_factor=50,    # 每个节点的最大 CF 子簇数
    n_clusters=3,           # 最终簇数
    compute_labels=True,
    copy=True
)

model.fit(X)

print(model.labels_)
print(model.root_)          # 内部树的根节点
print(model.subcluster_centers_)  # 子簇中心

# 支持 partial_fit
model.partial_fit(X_batch)

🎲 基于模型的聚类

GaussianMixture — 高斯混合模型(GMM)

from sklearn.mixture import GaussianMixture

model = GaussianMixture(
    n_components=1,           # 混合成分数
    covariance_type='full',   # 'full','tied','diag','spherical'
    tol=1e-3,
    reg_covar=1e-6,          # 协方差对角线上加的正则化
    max_iter=100,
    n_init=1,                # 初始化次数
    init_params='kmeans',    # 'kmeans','k-means++','random','random_from_data'
    weights_init=None,
    means_init=None,
    precisions_init=None,
    random_state=None,
    warm_start=False,
    verbose=0,
    verbose_interval=10
)

model.fit(X)

# 关键属性
print(model.weights_)         # 各成分的混合权重
print(model.means_)           # 各成分的均值
print(model.covariances_)     # 各成分的协方差
print(model.precisions_)      # 各成分的精度矩阵(协方差逆)
print(model.precisions_cholesky_)  # 精度矩阵的 Cholesky 分解
print(model.converged_)       # 是否收敛
print(model.n_iter_)          # 实际迭代数
print(model.lower_bound_)     # 对数似然的下界

# 预测方法
labels = model.predict(X)            # 硬分配
probs = model.predict_proba(X)       # 软分配(后验概率)
log_likelihood = model.score(X)      # 每个样本的对数似然
total_ll = model.score_samples(X)    # 加权对数似然

# 采样
X_sampled, y_sampled = model.sample(n_samples=100)

# AIC / BIC(模型选择)
print(model.aic(X))
print(model.bic(X))

GMM 模型选择:

import numpy as np

n_components = range(1, 11)
models = [GaussianMixture(n, random_state=42).fit(X) for n in n_components]
bics = [m.bic(X) for m in models]
aics = [m.aic(X) for m in models]

best_n = n_components[np.argmin(bics)]
print(f"Best n_components (BIC): {best_n}")

BayesianGaussianMixture — 贝叶斯 GMM

from sklearn.mixture import BayesianGaussianMixture

model = BayesianGaussianMixture(
    n_components=10,            # 设置足够大的初始值
    covariance_type='full',
    tol=1e-3,
    reg_covar=1e-6,
    max_iter=1000,
    n_init=1,
    init_params='kmeans',
    weight_concentration_prior_type='dirichlet_process',
    # 'dirichlet_process' — 自动推断成分数
    # 'dirichlet_distribution' — 固定成分数
    weight_concentration_prior=None,  # Dirichlet 先验浓度
    mean_precision_prior=None,
    mean_prior=None,
    degrees_of_freedom_prior=None,
    covariance_prior=None,
    random_state=None,
    warm_start=False,
    verbose=0
)

model.fit(X)

print(model.weights_)          # 部分权重接近 0(自动选择成分数)
print(model.n_components)      # 原始设定的成分数
# 实际有效的成分数
effective_n = np.sum(model.weights_ > 0.01)
print(f"Effective components: {effective_n}")

📈 其他聚类算法

1. MeanShift — 均值漂移

from sklearn.cluster import MeanShift

model = MeanShift(
    bandwidth=None,         # 带宽(None 用 estimate_bandwidth 估计)
    seeds=None,             # 初始核位置
    bin_seeding=False,      # 使用离散化加速
    min_bin_freq=1,
    cluster_all=True,       # 是否将所有点分配给簇(False 时孤立点为 -1)
    n_jobs=None,
    max_iter=300
)

model.fit(X)

print(model.cluster_centers_)
print(model.labels_)
print(model.n_iter_)

# 带宽估计
from sklearn.cluster import estimate_bandwidth
bandwidth = estimate_bandwidth(X, quantile=0.3, n_samples=500, random_state=42)

2. AffinityPropagation — 近邻传播

from sklearn.cluster import AffinityPropagation

model = AffinityPropagation(
    damping=0.5,              # 阻尼因子 (0.5~1)
    max_iter=200,
    convergence_iter=15,       # 连续迭代无变化判定收敛
    copy=True,
    preference=None,           # 优先度(None=相似度中值)
    affinity='euclidean',      # 或 'precomputed'
    verbose=False,
    random_state=None
)

model.fit(X)

print(model.cluster_centers_indices_)  # 簇中心在原数据中的索引
print(model.labels_)
print(model.affinity_matrix_)          # 相似度矩阵
print(model.n_iter_)

3. SpectralClustering — 谱聚类

from sklearn.cluster import SpectralClustering

model = SpectralClustering(
    n_clusters=8,
    eigen_solver=None,         # None,'arpack','lobpcg','amg'
    n_components=None,         # 谱嵌入维度
    random_state=42,
    n_init=10,                 # k-means 运行次数
    gamma=1.0,                 # RBF 核参数
    affinity='rbf',            # 'rbf','nearest_neighbors','precomputed',callable
    n_neighbors=10,            # nearest_neighbors affinity 的邻居数
    eigen_tol='auto',
    assign_labels='kmeans',    # 'kmeans','discretize','cluster_qr'
    degree=3,                  # 多项式核的次数
    coef0=1                    # 多项式核/ sigmoid 核的独立项
)

model.fit(X)

print(model.labels_)
print(model.affinity_matrix_)  # 亲和矩阵

4. SpectralBiclustering / SpectralCoclustering — 谱双聚类

from sklearn.cluster import SpectralBiclustering, SpectralCoclustering

# 双聚类(同时对行和列聚类)
model = SpectralBiclustering(
    n_clusters=3,
    method='bistochastic',  # 'bistochastic','scale','log'
    n_components=6,
    n_best=3,
    svd_method='randomized',
    n_svd_vecs=None,
    mini_batch=False,
    init='k-means++',
    n_init=10,
    random_state=42
)
model.fit(X)

print(model.row_labels_)     # 行标签
print(model.column_labels_)  # 列标签

# 共聚类(仅用于文档-词矩阵)
model = SpectralCoclustering(n_clusters=3, random_state=42)
model.fit(X)
print(model.row_labels_)
print(model.column_labels_)

🎯 选择簇数 K

肘部法则(Elbow Method)

from sklearn.cluster import KMeans
import matplotlib.pyplot as plt

inertias = []
K_range = range(1, 11)
for k in K_range:
    km = KMeans(n_clusters=k, random_state=42, n_init=10)
    km.fit(X)
    inertias.append(km.inertia_)

plt.plot(K_range, inertias, 'bo-')
plt.xlabel('k')
plt.ylabel('Inertia')
plt.title('Elbow Method')
plt.show()

轮廓系数

from sklearn.metrics import silhouette_score

silhouettes = []
for k in range(2, 11):
    km = KMeans(n_clusters=k, random_state=42, n_init=10)
    labels = km.fit_predict(X)
    sil = silhouette_score(X, labels)
    silhouettes.append(sil)

best_k = K_range[np.argmax(silhouettes)]

📝 算法选择指南

场景推荐
一般用途、快速KMeans
大数据集在线学习MiniBatchKMeans
任意形状簇、含噪音DBSCAN
变密度簇HDBSCAN / OPTICS
层次结构AgglomerativeClustering
软聚类、概率GaussianMixture
自动推断簇数BayesianGaussianMixture
非凸簇SpectralClustering
K 已知、球形簇KMeans

[[sklearn-总览|← 返回总览]]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值