【sklearn】K-means、密度聚类、层次聚类、GMM、谱聚类
文章目录
- 一、什么是聚类?
- 二、聚类方法(综述)
- 1、经典聚类方法(优缺点 + 适用场景)
- 2、两种改进方向
- (1)降维+聚类(先降维再聚类)
- (2)子空间聚类(自动找低维结构)
- 3、深度聚类(Deep Clustering)
- 三、项目实战
- 1、K-means(K均值聚类):一种常见的无监督学习方法
- (1)定义 + 原理(详解)
- (2)函数详解:sklearn.cluster.KMeans()
- (3)sklearn.cluster.KMeans()(点数据集)
- (2)sklearn.cluster.KMeans()(图像集)
- 2、DBSCAN(密度聚类):一种基于密度的聚类方法
- (1)定义 + 原理(详解)
- (2)函数详解:sklearn.cluster.DBSCAN()
- (3)sklearn.cluster.DBSCAN()(点数据集)
- (4)sklearn.cluster.DBSCAN()(图像集)
- 3、Agglomerative Clustering(层次聚类):一种自底向上的聚类方法
- (1)定义 + 原理(详解)
- (2)函数详解:sklearn.cluster.AgglomerativeClustering()
- (3)sklearn.cluster.AgglomerativeClustering(点数据集)
- (4)sklearn.cluster.AgglomerativeClustering(图像集)
- 4、Gaussian Mixture Model(高斯混合):一种基于概率模型的聚类方法
- (1)定义 + 原理(详解)
- (2)函数详解:sklearn.cluster.GaussianMixture()
- (3)sklearn.cluster.GaussianMixture()(点数据集)
- (4)sklearn.cluster.GaussianMixture()(图像集)
- 5、Spectral Clustering(谱聚类):一种基于图论的聚类方法
- (1)定义 + 原理(详解)
- (2)函数详解:sklearn.cluster.SpectralClustering()
- (3)sklearn.cluster.SpectralClustering()(点数据集)
- (4)sklearn.cluster.SpectralClustering()(图像集)
一、什么是聚类?
聚类(Clustering)是一种无监督学习任务,其目标是将数据集划分为若干个内部相似、相互区别的子集(簇,Cluster)。在图像处理领域中,聚类常用于图像分类、相似性搜索、结构分组与图像去重等任务。
- 原理解析:https://github.com/HuStanding/ml/tree/master/cluster
- 机器学习:聚类(层次聚类,密度聚类,K-means,谱聚类)
聚类(Clustering)与分类(Classification)对比
对比维度 | 聚类(Clustering) | 分类(Classification) |
---|---|---|
学习方式 | 无监督学习(Unsupervised Learning) | 有监督学习(Supervised Learning) |
是否有标签 | 没有标签(无需事先知道类别) | 有标签(每个样本都有预先定义的类别) |
样本目标 | 发现数据的内部结构或模式 | 学习输入与类别之间的映射关系 |
输出形式 | 每个样本的簇标签(类别未知) | 每个样本的类别标签(来自预定义类别集) |
常见算法 | KMeans、DBSCAN、谱聚类、GMM、层次聚类等 | 决策树、SVM、KNN、神经网络、朴素贝叶斯等 |
结果评估标准 | 轮廓系数、Calinski-Harabasz指数等 | 准确率、精确率、召回率、F1分数等 |
典型应用 | 客户分群、图像聚类、异常检测 | 垃圾邮件识别、图像分类、疾病预测等 |
对新样本处理 | 需重新聚类或扩展已有聚类 | 可直接用已有模型进行预测 |
对类别数依赖 | 一般需要指定簇数(如KMeans) | 训练阶段由数据提供类别 |
可解释性 | 通常较弱,类别含义需后续分析 | 类别语义明确,易解释 |
二、聚类方法(综述)
深度聚类算法研究综述
1、经典聚类方法(优缺点 + 适用场景)
类别 | 核心思想 | 代表算法 | 优点 | 缺点 | 适用场景 |
---|---|---|---|---|---|
1. 划分聚类 | 将数据划分为k个簇,使簇内相似度最大、簇间差异最大 | K-Means、K-Medoids、K-Modes | 简单高效,计算速度快,适用于大数据 | 需提前指定k值,对异常值和非球形簇敏感 | 簇结构较明显、各类分布较均匀、无噪声点,适合连续型低维数据 |
2. 密度聚类 | 基于数据点的密度连接构建簇,高密度区域为簇核心 | DBSCAN、OPTICS、HDBSCAN | 可发现任意形状簇,自动识别噪声 | 对参数敏感(如eps、min_samples),在高维数据中表现较差 | 簇密度不均、含噪声、复杂形状簇(如环状、月牙等),适合空间数据或地理聚类 |
3. 层次聚类 | 基于数据点之间的距离构建聚类树(树状结构) | Agglomerative、Divisive、Chameleon、BIRCH | 无需预设簇数,结果具有可解释的层次结构 | 计算复杂度高,不适合大规模数据 | 样本量中小型、需要展示“合并过程”或层级结构的场景,如生物系统分类、文档层级聚类 |
4. 模型聚类 | 假设数据由多个概率分布生成,使用统计建模 | GMM(高斯混合模型)、Bayesian GMM、Hidden Markov Model(HMM) | 支持软聚类,有概率解释,拟合能力强 | 对分布假设(如高斯)敏感,易陷入局部最优 | 数据呈混合分布、需对每个样本给出概率归属的场景,如图像背景建模、语音建模 |
5. 图聚类 | 将样本转为图结构,用图划分(最小割)方法分簇 | 谱聚类(Spectral Clustering)、RatioCut、NormalizedCut | 能处理任意形状簇,适合非凸分布,理论基础好 | 构图与特征分解开销大,不适合大数据 | 样本间相似性明确、数据分布复杂非凸形状,常用于图像分割、社交网络分析 |
虽然经典方法使用广泛,但当面对
高维、大规模或复杂结构数据
时,会遇到三大挑战:
高维稀疏性
:高维空间中点之间距离趋于相等,传统距离度量失效。复杂结构识别难
:例如同一类可能有多个形态(多模态),传统方法不容易识别。大规模数据耗时
:经典聚类多为O(n²)时间复杂度,难以处理百万级样本。
2、两种改进方向
为了解决上述问题,研究者提出了两条优化路线:
(1)降维+聚类(先降维再聚类)
- 思路:先用降维方法把数据从高维压缩成低维,再用传统聚类方法。
- 常用降维方法:
PCA(主成分分析)
:线性降维t-SNE、LLE、Isomap
:非线性降维- 优点:可视化效果好,计算量降低
- 局限:降维与聚类是分开的,可能失去原本的簇结构
(2)子空间聚类(自动找低维结构)
- 思路:认为数据不是整体分布在高维空间,而是隐藏在多个低维子空间中。
- 代表方法:
SSC(稀疏子空间聚类)
:找稀疏表示LRSC(低秩子空间聚类)
:找低秩结构- 优点:可发现更复杂的类结构
- 缺点:计算量大,理解门槛高
3、深度聚类(Deep Clustering)
- 背景与动机
- 传统聚类方法(如K-Means、DBSCAN、GMM)依赖于浅层特征(如颜色直方图、灰度均值、边缘强度等)以及固定的距离度量(如欧式距离)。这些方法在处理结构简单、低维度的数据时表现良好,但当数据呈现出非线性、高维度、复杂结构时,性能大幅下降。
- 随着深度学习的发展,研究者逐渐认识到,深度神经网络具备强大的特征抽象能力,能够从原始数据中自动学习更具判别性的表达,进而提升聚类效果。这便催生了**深度聚类(Deep Clustering)**这一研究方向。
- 基本思想:深度聚类本质上是将神经网络的特征学习与聚类的结构发现结合起来,以实现端到端的聚类建模。其目标是通过联合优化的方式,使学习到的表示空间更有利于聚类。
- 基本结构 —— 典型的深度聚类框架包括以下三个组成部分:
编码器网络(Encoder)
:
- 用于将原始数据(如图像)映射到一个潜在的低维特征空间。
- 常用结构:卷积自编码器(CNN-AE)、变分自编码器(VAE)、残差网络(ResNet)等。
聚类模块(Clustering Layer)
:
- 在潜在空间中引入KMeans中心、GMM概率模型或自注意力机制,对样本进行分组。
- 聚类目标常用KL散度、交叉熵、样本一致性损失等度量方式。
联合训练机制(Joint Optimization)
:
- 同时优化重构损失和聚类损失,使得所学特征不仅能还原数据,还具有良好的类内紧凑性和类间可分性。
- 代表性方法
方法 | 核心思想 | 特点 |
---|---|---|
DEC(2016) Deep Embedded Clustering | 用自编码器提取特征,聚类时最小化KL散度 | 开创性工作,不支持重构 |
IDEC(2017) Improved DEC | 在DEC基础上加入重构损失,提升稳定性 | 保持结构信息 |
DeepCluster(2018, Facebook) | 用CNN提取特征后KMeans聚类,迭代优化 | 支持ImageNet级别数据 |
DAC(2017) Deep Adaptive Clustering | 将聚类视为伪监督学习,引入样本对关系 | 不依赖中心初始化 |
SCAN(2020) Semantic Clustering by Adopting Nearest neighbors | 使用一致性学习方式实现语义聚类 | 无需先验类别数 |
DCCM(2020) Deep Comprehensive Correlation Mining | 同时优化标签、结构、距离 | 综合性框架 |
- 优势:
- 能自动学习复杂特征(特别是图像、语音、文本等非结构化数据)。
- 可以联合优化聚类结构和表示学习,端到端训练。
- 灵活扩展:可结合对比学习、图网络、自监督机制等模块。
- 挑战:
- 聚类目标容易陷入局部最优,需要精心设计初始化策略。
- 网络训练不稳定,聚类标签缺乏监督信号。
- 聚类数量k的选择依然是问题(部分方法支持自动估计)。
三、项目实战
1、K-means(K均值聚类):一种常见的无监督学习方法
K-means聚类详解
(1)定义 + 原理(详解)
一、算法简介
K均值聚类(K-Means Clustering)是一种常见的无监督学习方法,通过将数据自动分为K个簇,通过迭代方式最小化簇内样本到簇中心点的距离总和,从而获得高内聚、低外离的聚类效果。
- 簇(Cluster):一个簇是数据点的集合,这些点在某种意义上彼此相似。
- 簇中心(Centroid):是簇中所有点的平均值,表示簇的中心位置。
二、基本原理
K-means通过迭代方式优化以下目标函数:
arg min C ∑ i = 1 K ∑ x ∈ C i ∥ x − μ i ∥ 2 \underset{C}{\arg\min} \sum_{i=1}^{K} \sum_{x \in C_i} \|x - \mu_i\|^2 Cargmini=1∑Kx∈Ci∑∥x−μi∥2
其中:
- 𝐶𝑖:第i个簇;
- 𝜇𝑖 :第i簇的中心(均值);
- 𝑥:属于第i簇的样本;
- ∥𝑥−𝜇𝑖∥2 :样本与其簇中心的欧式距离平方。
- 目标:最小化簇内平方误差(SSE)。
三、算法流程
输入:样本数据集 X = x 1 , x 2 , … , x n X = {x_1, x_2, \dots, x_n} X=x1,x2,…,xn,预设簇数 K K K
输出:每个样本所属的簇标签 l 1 , l 2 , … , l n {l_1, l_2, \dots, l_n} l1,l2,…,ln,以及 K K K个簇中心点 μ 1 , μ 2 , … , μ K {\mu_1, \mu_2, \dots, \mu_K} μ1,μ2,…,μK
算法步骤:
- 初始中心:随机从样本中选取 K K K个数据点作为初始聚类中心 μ 1 , μ 2 , … , μ K {\mu_1, \mu_2, \dots, \mu_K} μ1,μ2,…,μK。
- 样本分配:对每个样本点 x i x_i xi,计算其与所有聚类中心的欧式距离: d ( x i , μ k ) = ∣ x i − μ k ∣ 2 d(x_i, \mu_k) = |x_i - \mu_k|_2 d(xi,μk)=∣xi−μk∣2,并将 x i x_i xi分配给距离最近的簇中心所代表的簇。
- 中心更新:对每个簇 C k C_k Ck,重新计算其所有成员的均值作为新簇中心: μ k = 1 ∣ C k ∣ ∑ x i ∈ C k x i \mu_k = \frac{1}{|C_k|} \sum_{x_i \in C_k} x_i μk=∣Ck∣1∑xi∈Ckxi
- 迭代优化:重复执行步骤2和3,直到满足以下任一停止条件:聚类中心不再发生变化(收敛)或达到预设最大迭代次数。
四、算法特点
✅ 优点:
- 算法简单,易于实现;
- 对中等规模数据具有良好效率;
- 结果具有可解释性,中心即代表簇的“原型”。
❌ 缺点:
- K值需预设,实际中往往难以确定;
- 对初始中心点敏感,可能陷入局部最优;
- 仅适用于凸状簇、球形分布,不适合非球形或密度不均数据;如月牙型数据。
- 对离群点敏感,极端值可能扰乱中心更新。
(2)函数详解:sklearn.cluster.KMeans()
"""#############################################################################################
# 模块功能:KMeans 是一种基于划分的无监督聚类算法,将数据划分为 k 个簇,使得簇内的样本相似度最大。
# 类说明:sklearn.cluster.KMeans(n_clusters=8, init='k-means++', n_init=10, max_iter=300, random_state=None, ...)
# 参数说明:
# n_clusters:要形成的簇的数量,即k值。
# init:初始化方法,默认是 'k-means++',可选 'random' 或指定初始中心。
# n_init:算法运行次数,每次运行重新初始化中心点。最终选取最优解(默认10次)。
# max_iter:单次运行最大迭代次数。
# tol:容差,当中心变化小于该值时停止迭代(默认1e-4)。
# random_state:随机数种子,确保结果可重复。
# algorithm:可选 'auto'、'full'(经典EM)、'elkan'(加速版本,适用于欧式距离)。
# 属性说明:
# labels_:每个样本的聚类标签。
# cluster_centers_:每个簇的中心点。
# inertia_:聚类结果的总误差平方和(越小越好)。
# n_iter_:实际运行迭代次数。
# 方法说明:
# fit(X):对数据 X 进行聚类建模。
# fit_predict(X):建模并返回每个样本的聚类标签。
# predict(X):对新数据预测其属于哪个簇。
#############################################################################################"""
(3)sklearn.cluster.KMeans()(点数据集)
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.cluster import KMeansk = 4 # 聚类类别
np.random.seed(42) # 固定随机种子,确保结果可复现# 1. 生成二维聚类数据
X, _ = make_blobs(n_samples=300, centers=k, cluster_std=0.8, random_state=42)
#############################################################################
# 2. 使用 sklearn 的 KMeans 进行聚类
kmeans = KMeans(n_clusters=k, random_state=42, n_init='auto')
kmeans.fit(X)# 3. 获取聚类标签与中心点
labels = kmeans.labels_
centers = kmeans.cluster_centers_
inertia = kmeans.inertia_# 4. 可视化聚类结果
plt.figure(figsize=(8, 6))
colors = plt.colormaps["Set1"].resampled(k)
for i in range(k):cluster_data = X[labels == i]plt.scatter(cluster_data[:, 0], cluster_data[:, 1], s=40, color=colors(i), label=f'Cluster {i}')
plt.scatter(centers[:, 0], centers[:, 1], c='black', marker='x', s=150, label='Centroids')
plt.title("sklearn KMeans")
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()# 5. 输出聚类信息
print("聚类标签:\n", labels)
print("质心坐标:\n", centers)
print(f"总平方误差SSE:{inertia:.2f}")"""
聚类标签:[3 3 0 1 3 1 2 1 0 2 0 2 0 0 3 0 3 2 0 0 2 0 1 3 0 3 3 1 1 2 0 2 3 2 3 0 31 3 1 2 0 3 1 0 0 3 2 3 2 1 3 1 0 1 2 3 2 2 0 3 2 2 3 1 1 1 1 1 0 1 1 3 20 3 1 1 0 1 0 0 3 0 1 3 3 2 2 2 3 0 3 0 0 3 1 0 3 3 2 2 2 0 0 0 0 0 1 3 20 0 0 0 2 3 1 3 1 1 1 0 3 1 3 3 0 3 1 2 0 0 0 0 2 2 3 0 1 0 2 1 0 2 2 2 21 0 0 3 2 1 0 2 1 3 3 2 0 3 1 3 2 3 1 0 0 0 0 0 1 2 2 1 1 2 2 1 3 0 3 2 23 1 0 2 2 1 1 1 3 2 1 1 2 2 3 0 0 1 2 0 1 1 3 1 0 0 1 1 2 3 1 3 3 0 3 3 13 1 2 2 3 3 2 2 2 3 0 1 2 1 3 2 3 3 3 1 1 2 3 1 1 1 3 1 3 1 3 2 1 3 2 0 30 2 0 3 0 1 2 1 2 2 0 0 1 2 2 3 3 1 0 0 2 2 2 2 1 3 2 1 2 2 1 0 1 2 0 3 02 0 3 3]
质心坐标:[[-2.63715917 8.98563949][-6.84180708 -6.84038791][ 4.70253968 2.02807134][-8.83330596 7.21790214]]
总平方误差SSE:362.47
"""
(2)sklearn.cluster.KMeans()(图像集)
# tif_clustering_kmeans.py
import os
import glob
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
import tifffile
import cv2# 1. 设置路径与读取图像
def load_tif_images(folder_path):"""读取指定文件夹下所有.tif图像,返回图像数组列表和文件名列表"""tif_paths = sorted(glob.glob(os.path.join(folder_path, "*.tif")))images = []filenames = []for path in tif_paths:img = tifffile.imread(path)if img.ndim == 3: # 如果是RGB或多通道,转换为灰度img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)images.append(img)filenames.append(os.path.basename(path))return images, filenames# 2. 提取图像特征(默认使用灰度统计特征)
def extract_features(images):"""提取每张图像的灰度特征向量:[均值, 标准差]"""features = []for img in images:mean = np.mean(img)std = np.std(img)features.append([mean, std])return np.array(features)# 3. KMeans 聚类并输出结果
def run_kmeans(features, n_clusters=3):"""使用 sklearn KMeans 进行聚类"""kmeans = KMeans(n_clusters=n_clusters, random_state=42, n_init='auto')kmeans.fit(features)return kmeans.labels_, kmeans.cluster_centers_, kmeans.inertia_# 4. 可视化聚类结果(按2维特征散点图)
def plot_clusters(features, labels, centers, filenames):"""Plot clustering results based on 2D features"""plt.figure(figsize=(8, 6))k = centers.shape[0]colors = plt.colormaps["Set1"].resampled(k)for i in range(k):cluster_points = features[labels == i]plt.scatter(cluster_points[:, 0], cluster_points[:, 1], s=100, label=f"Cluster {i}", color=colors(i))plt.scatter(centers[:, 0], centers[:, 1], marker='x', c='black', s=150, label='Centroids')for i, name in enumerate(filenames):plt.text(features[i, 0], features[i, 1], name, fontsize=8)plt.title("KMeans Clustering Result")plt.xlabel("Mean Intensity")plt.ylabel("Standard Deviation")plt.legend()plt.grid(True)plt.tight_layout()plt.show()# 5. 主函数
def main():folder_path = r"D:\py\cluster\data" # 修改为.tif图像所在目录images, filenames = load_tif_images(folder_path)features = extract_features(images)labels, centers, sse = run_kmeans(features, n_clusters=4)for name, label in zip(filenames, labels):print(f"{name}: labels {label}")# print("聚类标签:\n", labels) # 第i个元素表示第i张图像属于哪个簇(类别)print("聚类中心点坐标:\n", centers) # 每个聚类的“中心位置” ———— 在特征空间中,该类所有图像特征的平均值print(f"总平方误差SSE: {sse:.2f}") # 聚类总误差平方和,每个样本到其所属中心的欧式距离的平方之和。值越小说明类内样本越集中。plot_clusters(features, labels, centers, filenames)if __name__ == "__main__":main()
"""
09_1-01.tif: labels 2 21-01.tif: labels 0 32-01.tif: labels 3 92_1-01.tif: labels 1
09_1-02.tif: labels 2 21-02.tif: labels 0 32-02.tif: labels 1 92_1-02.tif: labels 3
09_1-03.tif: labels 2 21-03.tif: labels 0 32-03.tif: labels 1 92_1-03.tif: labels 3
09_1-04.tif: labels 1 21-04.tif: labels 1 32-04.tif: labels 1 92_1-04.tif: labels 1
09_1-05.tif: labels 2 21-05.tif: labels 0 32-05.tif: labels 1 92_1-05.tif: labels 3
聚类中心:[[ 92.39133279 73.30541406][114.03790788 60.16781074][127.41909154 66.28763555][ 94.74319609 59.01898048]]
总平方误差SSE: 991.23
"""
2、DBSCAN(密度聚类):一种基于密度的聚类方法
聚类分析算法——DBSCAN(密度聚类)算法详解
(1)定义 + 原理(详解)
一、基本思想
DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一种基于密度的聚类方法,不需要预先指定聚类数量,能够自动识别任意形状的簇,将其分为核心点(core point)、边界点(border point)和噪声点(noise point),并具备良好的噪声识别能力。其核心思想为:
在样本密集区域形成簇,稀疏区域被视为噪声。
一、核心概念
ε(Eps)
:某个点周围距离不超过ε的区域,称为该点的ε邻域。MinPts(最小点数)
:形成一个“高密度区域”所需的最小点数阈值。
根据这两个参数,每个样本点被分类为:
点类型 | 条件 |
---|---|
核心点 | ε邻域内包含至少MinPts个点(含自身) |
边界点 | 自身ε邻域内点数不足MinPts,但落在某个核心点的ε邻域中 |
噪声点 | 既不是核心点,也不在任何核心点的ε邻域中 |
二、聚类定义
- 直接密度可达:若点 p p p在点 q q q的ε邻域内,且 q q q是核心点,则称 p p p直接密度可达于 q q q;
- 密度可达:若存在点序列 p 1 , p 2 , . . . , p n p_1, p_2, ..., p_n p1,p2,...,pn,使得 p i + 1 p_{i+1} pi+1直接密度可达于 p i p_i pi,则 p n p_n pn密度可达于 p 1 p_1 p1;
- 密度相连:若存在点 o o o,使得 p p p和 q q q都密度可达于 o o o,则 p p p与 q q q密度相连。
三、聚类过程
输入:样本集 D D D,半径参数 ε ε ε,最小点数 M i n P t s MinPts MinPts
输出:簇划分结果,含噪声点标识
算法步骤:
- 初始化:所有样本标记为“未访问”;
- 从一个未访问的点 p p p出发:
- 若 p p p的ε邻域内点数≥MinPts,则以 p p p为种子生成新簇;
- 将ε邻域内所有密度可达点加入该簇;
- 若 p p p不满足核心点条件,则标记为“噪声点”;
- 重复步骤2~3,直到所有点被处理完毕。
四、算法特点
优点 | 缺点 |
---|---|
可识别任意形状簇 | 对参数ε和MinPts敏感 |
无需预设簇数 | 不适用于高维稀疏数据 |
能识别噪声点 | 在密度差异大的数据上效果不理想 |
(2)函数详解:sklearn.cluster.DBSCAN()
"""#############################################################################################
# 模块功能:DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是基于密度的聚类算法,
# 能有效识别任意形状的簇,并自动处理离群点(噪声)。
# 类说明:sklearn.cluster.DBSCAN(eps=0.5, min_samples=5, metric='euclidean', ...)
# 参数说明:
# eps:两个样本被认为是邻居的最大距离,越小越严格。即“半径”参数。
# min_samples:构成核心点的最小邻居数(包括点本身)。
# metric:距离度量方法(默认是欧几里得距离'euclidean'),也支持'manhattan'、'cosine'等。
# algorithm:近邻搜索算法,可选{'auto', 'ball_tree', 'kd_tree', 'brute'}。
# leaf_size:构造树结构时的叶子节点大小,默认为30(影响搜索效率)。
# n_jobs:指定并行计算的线程数,-1表示使用所有CPU核心。
# 属性说明:
# labels_:每个点的聚类标签。-1表示噪声点。
# core_sample_indices_:核心点在数据集中的索引。
# components_:核心点的坐标集合。
# 方法说明:
# fit(X):对数据 X 进行聚类建模。
# fit_predict(X):直接对数据进行聚类并返回标签结果。
#############################################################################################"""
(3)sklearn.cluster.DBSCAN()(点数据集)
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.cluster import DBSCAN# 设置聚类数量和随机种子
k = 4
np.random.seed(42)# 1. 生成二维聚类数据
X, _ = make_blobs(n_samples=300, centers=k, cluster_std=0.8, random_state=42)
#############################################################################
# 2. 使用 DBSCAN 进行聚类
db = DBSCAN(eps=0.9, min_samples=5) # 根据数据稠密程度调整 eps
db.fit(X)
labels = db.labels_ # 每个样本的聚类标签,-1 表示噪声点
n_clusters = len(set(labels)) - (1 if -1 in labels else 0)# 3. 可视化聚类结果
plt.figure(figsize=(8, 6))
colors = plt.colormaps["Set1"].resampled(n_clusters)for cluster_id in set(labels):cluster_mask = (labels == cluster_id)cluster_data = X[cluster_mask]if cluster_id == -1:# 噪声点用灰色表示plt.scatter(cluster_data[:, 0], cluster_data[:, 1], s=40, color='black', label="Noise")else:plt.scatter(cluster_data[:, 0], cluster_data[:, 1], s=40, color=colors(cluster_id), label=f"Cluster {cluster_id}")plt.title("DBSCAN Clustering Result")
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()# 4. 输出结果
print("聚类标签:\n", labels)
print(f"聚类簇数量(不含噪声):{n_clusters}")
"""
聚类标签:[ 0 0 1 2 0 2 3 2 1 3 1 3 1 1 0 1 0 3 1 1 3 1 2 01 0 0 2 2 3 1 3 0 3 0 1 0 2 0 2 3 1 0 2 1 1 0 30 3 2 0 2 1 2 -1 0 3 3 1 0 3 3 -1 2 2 2 2 2 1 2 20 3 1 0 2 2 1 2 1 1 0 1 2 0 0 3 3 3 0 1 0 1 1 02 1 0 0 3 3 3 1 1 1 1 1 2 0 3 1 1 1 1 3 0 2 0 22 2 1 0 2 0 0 1 0 2 3 1 1 1 1 3 3 0 1 2 1 3 2 13 3 3 3 2 1 1 0 3 2 1 3 2 0 0 3 1 0 2 0 3 0 2 11 1 1 1 2 3 3 2 2 -1 3 2 0 1 0 3 3 0 2 1 -1 3 2 22 0 3 2 2 3 3 0 1 1 2 3 1 2 2 0 2 1 1 2 2 3 0 20 0 1 0 0 2 0 2 3 3 0 0 3 3 3 0 1 2 3 2 0 3 0 00 2 2 3 0 2 2 2 0 2 0 2 0 3 2 0 3 1 0 1 3 1 0 12 3 2 3 3 1 1 2 3 3 0 0 2 1 1 3 3 3 3 2 0 3 2 33 2 1 2 3 1 0 1 3 1 0 0]
聚类簇数量(不含噪声):4
"""
(4)sklearn.cluster.DBSCAN()(图像集)
# tif_clustering_dbscan.py
import os
import glob
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import DBSCAN
import tifffile
import cv2# 1. 设置路径与读取图像
def load_tif_images(folder_path):"""读取指定文件夹下所有.tif图像,返回图像数组列表和文件名列表"""tif_paths = sorted(glob.glob(os.path.join(folder_path, "*.tif")))images = []filenames = []for path in tif_paths:img = tifffile.imread(path)if img.ndim == 3:img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)images.append(img)filenames.append(os.path.basename(path))return images, filenames# 2. 提取图像特征(默认使用灰度统计特征)
def extract_features(images):"""提取每张图像的灰度特征向量:[均值, 标准差]"""features = []for img in images:mean = np.mean(img)std = np.std(img)features.append([mean, std])return np.array(features)# 3. DBSCAN 聚类并输出结果
def run_dbscan(features, eps=5.0, min_samples=2):"""使用 sklearn DBSCAN 进行聚类"""dbscan = DBSCAN(eps=eps, min_samples=min_samples)dbscan.fit(features)return dbscan.labels_# 4. 可视化聚类结果
def plot_clusters(features, labels, filenames):"""绘制 DBSCAN 聚类结果,包括噪声点"""plt.figure(figsize=(8, 6))unique_labels = sorted(set(labels))n_clusters = len([l for l in unique_labels if l != -1])colors = plt.colormaps["Set1"].resampled(max(n_clusters, 1))for i, label in enumerate(unique_labels):mask = (labels == label)cluster_points = features[mask]if label == -1:plt.scatter(cluster_points[:, 0], cluster_points[:, 1], s=100, color='black', label="Noise")else:plt.scatter(cluster_points[:, 0], cluster_points[:, 1], s=100, color=colors(label), label=f"Cluster {label}")for i, name in enumerate(filenames):plt.text(features[i, 0], features[i, 1], name, fontsize=8)plt.title("DBSCAN Clustering Result")plt.xlabel("Mean Intensity")plt.ylabel("Standard Deviation")plt.legend()plt.grid(True)plt.tight_layout()plt.show()# 5. 主函数
def main():folder_path = r"D:\py\cluster\data" # 修改为实际图像目录images, filenames = load_tif_images(folder_path)features = extract_features(images)labels = run_dbscan(features, eps=5.0, min_samples=2)for name, label in zip(filenames, labels):print(f"{name}: labels {label}")print("聚类标签集合(含噪声):", sorted(set(labels)))plot_clusters(features, labels, filenames)if __name__ == "__main__":main()
"""
09_1-01.tif: labels 0 21-01.tif: labels 2 32-01.tif: labels 3 92_1-01.tif: labels 4
09_1-02.tif: labels 0 21-02.tif: labels -1 32-02.tif: labels 4 92_1-02.tif: labels -1
09_1-03.tif: labels 1 21-03.tif: labels 2 32-03.tif: labels 4 92_1-03.tif: labels 3
09_1-04.tif: labels 1 21-04.tif: labels -1 32-04.tif: labels 4 92_1-04.tif: labels 4
09_1-05.tif: labels 1 21-05.tif: labels -1 32-05.tif: labels 4 92_1-05.tif: labels -1
聚类标签集合(含噪声): [np.int64(-1), np.int64(0), np.int64(1), np.int64(2), np.int64(3), np.int64(4)]
"""
3、Agglomerative Clustering(层次聚类):一种自底向上的聚类方法
层次聚类算法的实现
(1)定义 + 原理(详解)
Agglomerative Clustering(凝聚型层次聚类)是一种自底向上的聚类方法,最初将每个样本视为一个独立簇,然后不断将最相似的簇合并,直到满足停止条件(如簇数达到预设值)。
- 它属于层次聚类(Hierarchical Clustering)的一类。
一、基本思想
层次聚类:构造的是一个聚类树(Dendrogram),用来描述聚类过程中的合并或分裂历史。
- Agglomerative 是其“凝聚型”实现方式,对应“自底向上”策略。
Dendrogram 可直观展示样本聚类过程。截断树状图的高度,即可得到不同的簇划分。
_______| || ____|_____| | | |A B C D
二、聚类过程
输入:样本集 X X X,聚类目标数 K K K(或距离阈值)
输出:每个样本所属簇的标签
算法步骤如下:
- 初始化:将每个样本作为一个独立簇,共有 n n n个簇;
- 计算距离矩阵:计算所有簇两两之间的距离;
- 合并最近簇对:选择距离最近的两个簇进行合并;
- 更新距离矩阵:根据链接策略(见下文)更新新簇与其他簇的距离;
- 重复步骤2~4,直到剩下 K K K个簇或距离大于设定阈值。
三、距离定义(Linkage Methods)
Agglomerative Clustering 的聚类效果依赖于簇间距离的定义方式,常见策略包括:
方法 | 定义 | 特点 |
---|---|---|
单链接(single linkage) | 两簇中最近点之间的距离 | 易形成链状簇 |
全链接(complete linkage) | 两簇中最远点之间的距离 | 对离群值敏感 |
平均链接(average linkage) | 两簇中所有点对之间平均距离 | 折中方案 |
中心链接(centroid linkage) | 两簇中心点之间的距离 | 可导致非嵌套聚类 |
Ward 方法 | 使合并后簇内平方误差最小 | 常用于数值型特征,效果稳定 |
四、算法特点
优点 | 缺点 |
---|---|
无需预设簇数(可视化后决定) | 计算复杂度高,O(n2) |
适合层次结构分析 | 对噪声敏感,难扩展到大数据集 |
可选择多种距离与合并策略 | 不支持“样本移动”,无法回溯 |
(2)函数详解:sklearn.cluster.AgglomerativeClustering()
"""#############################################################################################
# 模块功能:AgglomerativeClustering 是一种基于层次的聚类算法(自底向上),每次将最近的两个簇合并,直到达到预定的聚类数。
# 类说明:sklearn.cluster.AgglomerativeClustering(n_clusters=2, affinity='euclidean', linkage='ward', ...)
# 参数说明:
# n_clusters:期望的聚类数量。
# affinity:距离度量方法(也叫“相似度”),可选:
# - 'euclidean'(默认):欧氏距离
# - 'manhattan'、'cosine' 等
# - 如果 linkage='ward',只能使用 'euclidean'
# linkage:链接方式,定义簇之间的距离,可选:
# - 'ward':最小化簇内方差(只支持欧式距离)
# - 'complete':最大距离
# - 'average':平均距离
# - 'single':最小距离
# distance_threshold:可选。如果设定该参数,聚类过程会基于阈值自动停止,忽略 n_clusters。
# compute_full_tree:默认 'auto',控制是否构建完整的层次树(适用于可视化等高级分析)。
# 属性说明:
# labels_:每个样本的聚类标签。
# 方法说明:
# fit(X):对数据 X 建模。
# fit_predict(X):建模并返回聚类标签。
#############################################################################################"""
(3)sklearn.cluster.AgglomerativeClustering(点数据集)
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.cluster import AgglomerativeClustering# 设置聚类数量和随机种子
k = 4
np.random.seed(42)# 1. 生成二维聚类数据
X, _ = make_blobs(n_samples=300, centers=k, cluster_std=0.8, random_state=42)# 2. 使用 Agglomerative Clustering 进行聚类
model = AgglomerativeClustering(n_clusters=k, linkage='ward') # linkage 可选: 'ward', 'average', 'complete', 'single'
labels = model.fit_predict(X)# 3. 可视化聚类结果
plt.figure(figsize=(8, 6))
colors = plt.colormaps["Set1"].resampled(k)for cluster_id in range(k):cluster_mask = (labels == cluster_id)cluster_data = X[cluster_mask]plt.scatter(cluster_data[:, 0], cluster_data[:, 1], s=40, color=colors(cluster_id), label=f"Cluster {cluster_id}")plt.title("Agglomerative Clustering Result")
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()# 4. 输出结果
print("聚类标签:\n", labels)
print(f"聚类簇数量:{k}")
"""
聚类标签:[0 0 3 1 0 1 2 1 3 2 3 2 3 3 0 3 0 2 3 3 2 3 1 0 3 0 0 1 1 2 3 2 0 2 0 3 01 0 1 2 3 0 1 3 3 0 2 0 2 1 0 1 3 1 2 0 2 2 3 0 2 2 0 1 1 1 1 1 3 1 1 0 23 0 1 1 3 1 3 3 0 3 1 0 0 2 2 2 0 3 0 3 3 0 1 3 0 0 2 2 2 3 3 3 3 3 1 0 23 3 3 3 2 0 1 0 1 1 1 3 0 1 0 0 3 0 1 2 3 3 3 3 2 2 0 3 1 3 2 1 3 2 2 2 21 3 3 0 2 1 3 2 1 0 0 2 3 0 1 0 2 0 1 3 3 3 3 3 1 2 2 1 1 2 2 1 0 3 0 2 20 1 3 2 2 1 1 1 0 2 1 1 2 2 0 3 3 1 2 3 1 1 0 1 3 3 1 1 2 0 1 0 0 3 0 0 10 1 2 2 0 0 2 2 2 0 3 1 2 1 0 2 0 0 0 1 1 2 0 1 1 1 0 1 0 1 0 2 1 0 2 3 03 2 3 0 3 1 2 1 2 2 3 3 1 2 2 0 0 1 3 3 2 2 2 2 1 0 2 1 2 2 1 3 1 2 3 0 32 3 0 0]
聚类簇数量:4
"""
(4)sklearn.cluster.AgglomerativeClustering(图像集)
# tif_clustering_dbscan.py
import os
import glob
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import DBSCAN
import tifffile
import cv2# 1. 设置路径与读取图像
def load_tif_images(folder_path):"""读取指定文件夹下所有.tif图像,返回图像数组列表和文件名列表"""tif_paths = sorted(glob.glob(os.path.join(folder_path, "*.tif")))images = []filenames = []for path in tif_paths:img = tifffile.imread(path)if img.ndim == 3:img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)images.append(img)filenames.append(os.path.basename(path))return images, filenames# 2. 提取图像特征(默认使用灰度统计特征)
def extract_features(images):"""提取每张图像的灰度特征向量:[均值, 标准差]"""features = []for img in images:mean = np.mean(img)std = np.std(img)features.append([mean, std])return np.array(features)# 3. DBSCAN 聚类并输出结果
def run_dbscan(features, eps=5.0, min_samples=2):"""使用 sklearn DBSCAN 进行聚类"""dbscan = DBSCAN(eps=eps, min_samples=min_samples)dbscan.fit(features)return dbscan.labels_# 4. 可视化聚类结果
def plot_clusters(features, labels, filenames):"""绘制 DBSCAN 聚类结果,包括噪声点"""plt.figure(figsize=(8, 6))unique_labels = sorted(set(labels))n_clusters = len([l for l in unique_labels if l != -1])colors = plt.colormaps["Set1"].resampled(max(n_clusters, 1))for i, label in enumerate(unique_labels):mask = (labels == label)cluster_points = features[mask]if label == -1:plt.scatter(cluster_points[:, 0], cluster_points[:, 1], s=100, color='black', label="Noise")else:plt.scatter(cluster_points[:, 0], cluster_points[:, 1], s=100, color=colors(label), label=f"Cluster {label}")for i, name in enumerate(filenames):plt.text(features[i, 0], features[i, 1], name, fontsize=8)plt.title("DBSCAN Clustering Result")plt.xlabel("Mean Intensity")plt.ylabel("Standard Deviation")plt.legend()plt.grid(True)plt.tight_layout()plt.show()# 5. 主函数
def main():folder_path = r"D:\py\cluster\data" # 修改为实际图像目录images, filenames = load_tif_images(folder_path)features = extract_features(images)labels = run_dbscan(features, eps=5.0, min_samples=2)for name, label in zip(filenames, labels):print(f"{name}: labels {label}")print("聚类标签集合(含噪声):", sorted(set(labels)))plot_clusters(features, labels, filenames)if __name__ == "__main__":main()
"""
09_1-01.tif: labels 0 21-01.tif: labels 1 32-01.tif: labels 3 92_1-01.tif: labels 2
09_1-02.tif: labels 0 21-02.tif: labels 1 32-02.tif: labels 2 92_1-02.tif: labels 3
09_1-03.tif: labels 0 21-03.tif: labels 1 32-03.tif: labels 2 92_1-03.tif: labels 3
09_1-04.tif: labels 0 21-04.tif: labels 0 32-04.tif: labels 2 92_1-04.tif: labels 2
09_1-05.tif: labels 0 21-05.tif: labels 1 32-05.tif: labels 2 92_1-05.tif: labels 3
聚类标签集合: [np.int64(0), np.int64(1), np.int64(2), np.int64(3)]
"""
4、Gaussian Mixture Model(高斯混合):一种基于概率模型的聚类方法
高斯混合模型聚类算法
(1)定义 + 原理(详解)
高斯混合模型(Gaussian Mixture Model,GMM)是一种基于概率模型的聚类方法,它假设数据是由多个不同的高斯分布(即正态分布)混合而成的,每个高斯分布对应一个簇(类别),数据点属于某个簇的概率由该簇对应的高斯分布决定。
- 与KMeans只考虑“点到中心的距离”不同,GMM认为每个样本属于某个簇的概率是可以计算的,因此支持软聚类,即一个样本可以属于多个簇,但属于某一簇的概率更高。
一、基本思想
GMM认为:整个数据集是由 K K K个高斯分布“叠加”而成,每个簇对应一个高斯组件(分布)。每个簇具有:
- 均值(即该簇的中心)
- 协方差(控制形状/方向/离散度)
- 混合系数(表示该簇在整体中占比)
二、聚类过程
GMM采用一种迭代优化策略称为EM算法(期望最大化)
,用于不断拟合最优。
步骤 | 内容 |
---|---|
初始化 | 随机生成若干高斯分布参数(均值、方差、权重) |
E步(Expectation) | 计算每个样本属于每个簇的概率(软分配) |
M步(Maximization) | 基于上述概率,重新估计每个簇的均值、方差、权重 |
重复E-M过程 | 直到模型收敛或达到最大迭代次数 |
最终,每个样本将被分配到概率最大的簇中,也可根据“属于每个簇的概率”进行进一步分析。
四、算法特点
优点 | 缺点 |
---|---|
支持软聚类,提供更丰富的信息 | 需要预设簇数 |
可表示椭圆形簇,更贴合实际分布 | 对初始参数敏感,易陷入局部最优 |
能输出概率,有统计解释能力 | 不适合离群点多或簇非高斯的数据 |
(2)函数详解:sklearn.cluster.GaussianMixture()
"""#############################################################################################
# 模块功能:GaussianMixture 是一种基于概率模型的聚类算法,使用高斯混合模型(GMM)表示数据分布。
# 它假设数据由多个高斯分布成分组成,可用于软聚类与密度估计。
# 类说明:sklearn.mixture.GaussianMixture(n_components=1, covariance_type='full', max_iter=100, random_state=None, ...)
# 参数说明:
# n_components:高斯分布的个数(即聚类数量)。
# covariance_type:协方差矩阵的类型,常用取值包括:
# - 'full'(默认):每个成分有自己的完整协方差矩阵
# - 'tied':所有成分共享一个协方差矩阵
# - 'diag':对角协方差矩阵(仅保留方差)
# - 'spherical':所有成分共享一个单一方差(球形分布)
# max_iter:最大迭代次数(EM算法迭代上限)。
# tol:收敛阈值,默认为1e-3。
# random_state:设置随机种子,保证可重复性。
# init_params:初始化方式,'kmeans'(默认)或 'random'。
# 属性说明:
# weights_:各个高斯成分的权重。
# means_:每个高斯成分的均值向量。
# covariances_:各个高斯成分的协方差矩阵。
# converged_:布尔值,指示算法是否收敛。
# 方法说明:
# fit(X):拟合模型。
# predict(X):返回每个样本的聚类标签(对应最大概率)。
# predict_proba(X):返回每个样本属于每个簇的概率。
# score_samples(X):返回每个样本的对数概率密度。
#############################################################################################"""
(3)sklearn.cluster.GaussianMixture()(点数据集)
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.mixture import GaussianMixture# 设置聚类数量和随机种子
k = 4
np.random.seed(42)# 1. 生成二维聚类数据
X, _ = make_blobs(n_samples=300, centers=k, cluster_std=0.8, random_state=42)# 2. 使用 GMM 高斯混合模型进行聚类
gmm = GaussianMixture(n_components=k, random_state=42)
gmm.fit(X)
labels = gmm.predict(X) # 每个样本的聚类标签
probs = gmm.predict_proba(X) # 每个样本属于每一类的概率
centers = gmm.means_ # 聚类中心# 3. 可视化聚类结果
plt.figure(figsize=(8, 6))
colors = plt.colormaps["Set1"].resampled(k)for cluster_id in range(k):cluster_data = X[labels == cluster_id]plt.scatter(cluster_data[:, 0], cluster_data[:, 1], s=40, color=colors(cluster_id), label=f"Cluster {cluster_id}")# 标记 GMM 中心
plt.scatter(centers[:, 0], centers[:, 1], marker='x', c='black', s=150, label='GMM Centers')plt.title("Gaussian Mixture Clustering Result")
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()# 4. 输出结果
print("聚类标签:\n", labels)
print("GMM 聚类中心坐标:\n", centers)
"""
聚类标签:[3 3 0 1 3 1 2 1 0 2 0 2 0 0 3 0 3 2 0 0 2 0 1 3 0 3 3 1 1 2 0 2 3 2 3 0 31 3 1 2 0 3 1 0 0 3 2 3 2 1 3 1 0 1 2 3 2 2 0 3 2 2 3 1 1 1 1 1 0 1 1 3 20 3 1 1 0 1 0 0 3 0 1 3 3 2 2 2 3 0 3 0 0 3 1 0 3 3 2 2 2 0 0 0 0 0 1 3 20 0 0 0 2 3 1 3 1 1 1 0 3 1 3 3 0 3 1 2 0 0 0 0 2 2 3 0 1 0 2 1 0 2 2 2 21 0 0 3 2 1 0 2 1 3 3 2 0 3 1 3 2 3 1 0 0 0 0 0 1 2 2 1 1 2 2 1 3 0 3 2 23 1 0 2 2 1 1 1 3 2 1 1 2 2 3 0 0 1 2 0 1 1 3 1 0 0 1 1 2 3 1 3 3 0 3 3 13 1 2 2 3 3 2 2 2 3 0 1 2 1 3 2 3 3 3 1 1 2 3 1 1 1 3 1 3 1 3 2 1 3 2 0 30 2 0 3 0 1 2 1 2 2 0 0 1 2 2 3 3 1 0 0 2 2 2 2 1 3 2 1 2 2 1 0 1 2 0 3 02 0 3 3]
GMM 聚类中心坐标:[[-2.6371644 8.98563839][-6.84180708 -6.84038791][ 4.70253968 2.02807134][-8.83330932 7.21790079]]
"""
(4)sklearn.cluster.GaussianMixture()(图像集)
# tif_clustering_gmm.py
import os
import glob
import numpy as np
import matplotlib.pyplot as plt
from sklearn.mixture import GaussianMixture
import tifffile
import cv2# 1. 读取.tif图像
def load_tif_images(folder_path):tif_paths = sorted(glob.glob(os.path.join(folder_path, "*.tif")))images = []filenames = []for path in tif_paths:img = tifffile.imread(path)if img.ndim == 3:img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)images.append(img)filenames.append(os.path.basename(path))return images, filenames# 2. 提取图像特征
def extract_features(images):features = []for img in images:mean = np.mean(img)std = np.std(img)features.append([mean, std])return np.array(features)# 3. GMM 聚类
def run_gmm(features, n_components=4):gmm = GaussianMixture(n_components=n_components, random_state=42)gmm.fit(features)labels = gmm.predict(features)centers = gmm.means_return labels, centers# 4. 可视化聚类结果
def plot_clusters(features, labels, centers, filenames):plt.figure(figsize=(8, 6))k = centers.shape[0]colors = plt.colormaps["Set1"].resampled(k)for i in range(k):cluster_points = features[labels == i]plt.scatter(cluster_points[:, 0], cluster_points[:, 1], s=100, color=colors(i), label=f"Cluster {i}")plt.scatter(centers[:, 0], centers[:, 1], marker='x', c='black', s=150, label='GMM Centers')for i, name in enumerate(filenames):plt.text(features[i, 0], features[i, 1], name, fontsize=8)plt.title("GMM Clustering Result")plt.xlabel("Mean Intensity")plt.ylabel("Standard Deviation")plt.legend()plt.grid(True)plt.tight_layout()plt.show()# 5. 主函数
def main():folder_path = r"D:\py\cluster\data" # 修改为.tif图像目录images, filenames = load_tif_images(folder_path)features = extract_features(images)labels, centers = run_gmm(features, n_components=4)for name, label in zip(filenames, labels):print(f"{name}: label {label}")print("GMM 聚类中心:\n", centers)plot_clusters(features, labels, centers, filenames)if __name__ == "__main__":main()
"""
09_1-01.tif: label 2 21-01.tif: label 0 32-01.tif: label 3 92_1-01.tif: label 1
09_1-02.tif: label 2 21-02.tif: label 0 32-02.tif: label 1 92_1-02.tif: label 3
09_1-03.tif: label 2 21-03.tif: label 0 32-03.tif: label 1 92_1-03.tif: label 3
09_1-04.tif: label 1 21-04.tif: label 1 32-04.tif: label 1 92_1-04.tif: label 1
09_1-05.tif: label 2 21-05.tif: label 0 32-05.tif: label 1 92_1-05.tif: label 3
GMM 聚类中心:[[ 92.39272065 73.30510563][114.03417607 60.11274762][127.19113991 66.29119459][ 94.74032195 59.01709723]]
"""
5、Spectral Clustering(谱聚类):一种基于图论的聚类方法
谱聚类(spectral clustering)基本原理及python实现
(1)定义 + 原理(详解)
Spectral Clustering(谱聚类)是一种基于图论的聚类方法,将数据点视为图中的节点,利用它们之间的相似度构建图结构,并借助图的拉普拉斯矩阵(Laplacian Matrix)的特征向量对数据进行聚类。
一、基本思想
谱聚类不直接使用样本的原始特征,而是先计算样本间的相似度矩阵,将数据表示成一个无向加权图:
- 节点:数据点
- 边权重:两个点之间的相似度(通常使用高斯核函数)
通过图的拉普拉斯矩阵的特征分解,将高维复杂结构映射到低维空间,再利用传统聚类方法(如KMeans)完成最终分组。
二、聚类过程
- 构建相似度矩阵:计算样本间相似度,得到一个对称的权重矩阵。
- 计算图拉普拉斯矩阵:基于相似度矩阵计算拉普拉斯矩阵(如:标准拉普拉斯、归一化拉普拉斯等)。
- 特征分解:求解拉普拉斯矩阵的前K个特征向量,形成低维嵌入空间。
- 聚类划:在低维空间上用KMeans等方法对特征向量进行聚类。
三、算法特点
优点 | 缺点 |
---|---|
能识别任意形状的簇 | 对相似度矩阵构建敏感,需合理选参数 |
理论基础坚实,效果稳定 | 计算拉普拉斯矩阵特征向量代价较高 |
不依赖数据分布的假设 | 对大规模数据计算资源要求高 |
(2)函数详解:sklearn.cluster.SpectralClustering()
"""#############################################################################################
# 模块功能:SpectralClustering(谱聚类)是一种基于图论的聚类算法,利用样本之间的相似度构建图,
# 通过计算图的拉普拉斯矩阵的特征向量进行降维,再使用KMeans等方法完成聚类。
# 类说明:sklearn.cluster.SpectralClustering(n_clusters=8, affinity='rbf', assign_labels='kmeans', ...)
# 参数说明:
# n_clusters:聚类簇的数量。
# affinity:相似度计算方式(构造邻接图的方法),常见取值:
# - 'rbf':使用高斯核函数(默认方式),即欧氏距离的指数衰减形式。
# - 'nearest_neighbors':基于k近邻图。
# - 'precomputed':使用预先计算好的相似度矩阵。
# gamma:当 affinity='rbf' 时,控制核函数的带宽(即影响距离的缩放)。
# n_neighbors:当 affinity='nearest_neighbors' 时使用的近邻数。
# assign_labels:在谱空间中如何将数据分组,可选:
# - 'kmeans'(默认):用KMeans在特征空间中分组。
# - 'discretize':使用离散化方法(更稳定但更慢)。
# random_state:控制随机性(保证可重复性)。
# eigen_solver:求解特征向量的算法,可选 'arpack'、'lobpcg' 或 'amg'。
# n_init:内部KMeans的初始化次数。
# 属性说明:
# labels_:每个样本对应的聚类标签。
# 方法说明:
# fit(X):对数据拟合。
# fit_predict(X):拟合后返回标签(推荐使用)。
#############################################################################################"""
(3)sklearn.cluster.SpectralClustering()(点数据集)
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.cluster import SpectralClustering# 设置聚类数量和随机种子
k = 4
np.random.seed(42)# 1. 生成二维聚类数据
X, _ = make_blobs(n_samples=300, centers=k, cluster_std=0.8, random_state=42)# 2. 使用 Spectral Clustering 进行聚类
sc = SpectralClustering(n_clusters=k,affinity='nearest_neighbors', # 可选: 'rbf', 'nearest_neighbors'n_neighbors=10, # 邻接数,affinity='nearest_neighbors' 时使用assign_labels='kmeans',random_state=42
)
labels = sc.fit_predict(X)# 3. 可视化聚类结果
plt.figure(figsize=(8, 6))
colors = plt.colormaps["Set1"].resampled(k)for cluster_id in range(k):cluster_data = X[labels == cluster_id]plt.scatter(cluster_data[:, 0], cluster_data[:, 1], s=40, color=colors(cluster_id), label=f"Cluster {cluster_id}")plt.title("Spectral Clustering Result")
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()# 4. 输出结果
print("聚类标签:\n", labels)
print(f"类别数量:{len(set(labels))}")
"""
聚类标签:[2 2 1 1 2 1 3 1 1 3 1 0 1 1 2 1 2 3 1 1 0 1 1 2 1 2 2 1 1 0 1 3 2 0 2 1 21 2 1 0 1 2 1 1 1 2 3 2 0 1 2 1 1 1 3 2 3 3 1 2 0 3 2 1 1 1 1 1 1 1 1 2 31 2 1 1 1 1 1 1 2 1 1 2 2 3 3 0 2 1 2 1 1 2 1 1 2 2 0 3 0 1 1 1 1 1 1 2 01 1 1 1 0 2 1 2 1 1 1 1 2 1 2 2 1 2 1 3 1 1 1 1 3 0 2 1 1 1 0 1 1 0 3 3 31 1 1 2 0 1 1 0 1 2 2 3 1 2 1 2 0 2 1 1 1 1 1 1 1 3 3 1 1 3 3 1 2 1 2 0 32 1 1 0 3 1 1 1 2 3 1 1 3 3 2 1 1 1 3 1 1 1 2 1 1 1 1 1 3 2 1 2 2 1 2 2 12 1 3 3 2 2 3 3 3 2 1 1 0 1 2 3 2 2 2 1 1 0 2 1 1 1 2 1 2 1 2 0 1 2 3 1 21 3 1 2 1 1 3 1 0 3 1 1 1 3 3 2 2 1 1 1 0 0 3 0 1 2 0 1 3 3 1 1 1 3 1 2 10 1 2 2]
类别数量:4
"""
(4)sklearn.cluster.SpectralClustering()(图像集)
# tif_clustering_spectral.py
import os
import glob
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import SpectralClustering
import tifffile
import cv2# 1. 读取.tif图像
def load_tif_images(folder_path):tif_paths = sorted(glob.glob(os.path.join(folder_path, "*.tif")))images = []filenames = []for path in tif_paths:img = tifffile.imread(path)if img.ndim == 3:img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)images.append(img)filenames.append(os.path.basename(path))return images, filenames# 2. 提取图像特征
def extract_features(images):features = []for img in images:mean = np.mean(img)std = np.std(img)features.append([mean, std])return np.array(features)# 3. Spectral 聚类
def run_spectral_clustering(features, n_clusters=4):sc = SpectralClustering(n_clusters=n_clusters,affinity='nearest_neighbors',n_neighbors=5,assign_labels='kmeans',random_state=42)labels = sc.fit_predict(features)return labels# 4. 可视化聚类结果
def plot_clusters(features, labels, filenames):plt.figure(figsize=(8, 6))k = len(np.unique(labels))colors = plt.colormaps["Set1"].resampled(k)for i in range(k):cluster_points = features[labels == i]plt.scatter(cluster_points[:, 0], cluster_points[:, 1], s=100, color=colors(i), label=f"Cluster {i}")for i, name in enumerate(filenames):plt.text(features[i, 0], features[i, 1], name, fontsize=8)plt.title("Spectral Clustering Result")plt.xlabel("Mean Intensity")plt.ylabel("Standard Deviation")plt.legend()plt.grid(True)plt.tight_layout()plt.show()# 5. 主函数
def main():folder_path = r"D:\py\cluster\data" # 修改为.tif图像目录images, filenames = load_tif_images(folder_path)features = extract_features(images)labels = run_spectral_clustering(features, n_clusters=4)for name, label in zip(filenames, labels):print(f"{name}: label {label}")print(f"类别数量:{len(set(labels))}")plot_clusters(features, labels, filenames)if __name__ == "__main__":main()
"""
09_1-01.tif: label 1 21-01.tif: label 2 32-01.tif: label 3 92_1-01.tif: label 0
09_1-02.tif: label 1 21-02.tif: label 2 32-02.tif: label 0 92_1-02.tif: label 3
09_1-03.tif: label 1 21-03.tif: label 2 32-03.tif: label 0 92_1-03.tif: label 3
09_1-04.tif: label 1 21-04.tif: label 1 32-04.tif: label 0 92_1-04.tif: label 0
09_1-05.tif: label 1 21-05.tif: label 2 32-05.tif: label 0 92_1-05.tif: label 3
类别数量:4
"""