本文目录导读:

我来为你详细介绍如何使用脚本实现谱聚类算法,这里以Python为例,展示完整的实现过程:
谱聚类算法实现
import numpy as np
from sklearn.cluster import KMeans
from scipy.sparse.csgraph import connected_components
from scipy.spatial.distance import pdist, squareform
class SpectralClustering:
def __init__(self, n_clusters=2, gamma=1.0, affinity='rbf'):
"""
n_clusters: 聚类数量
gamma: RBF核参数
affinity: 相似度度量方式 ('rbf' 或 'nearest_neighbors')
"""
self.n_clusters = n_clusters
self.gamma = gamma
self.affinity = affinity
def _compute_similarity_matrix(self, X):
"""计算相似度矩阵"""
n_samples = X.shape[0]
if self.affinity == 'rbf':
# 计算欧氏距离
pairwise_dists = squareform(pdist(X, 'euclidean'))
# RBF核相似度
similarity_matrix = np.exp(-self.gamma * pairwise_dists ** 2)
else:
# 使用最近邻方法
similarity_matrix = np.zeros((n_samples, n_samples))
from sklearn.neighbors import kneighbors_graph
knn_graph = kneighbors_graph(X, n_neighbors=10, mode='distance')
similarity_matrix = knn_graph.toarray()
return similarity_matrix
def _compute_laplacian(self, similarity_matrix):
"""计算拉普拉斯矩阵"""
# 度矩阵
degree_matrix = np.diag(np.sum(similarity_matrix, axis=1))
# 归一化拉普拉斯矩阵
# L = D^(-1/2) * (D - W) * D^(-1/2)
degree_inv_sqrt = np.linalg.inv(np.sqrt(degree_matrix))
laplacian = degree_inv_sqrt @ (degree_matrix - similarity_matrix) @ degree_inv_sqrt
return laplacian
def fit_predict(self, X):
"""执行谱聚类"""
# 1. 计算相似度矩阵
similarity_matrix = self._compute_similarity_matrix(X)
# 2. 计算拉普拉斯矩阵
laplacian = self._compute_laplacian(similarity_matrix)
# 3. 计算特征值和特征向量
eigenvalues, eigenvectors = np.linalg.eigh(laplacian)
# 4. 选择最小的k个特征值对应的特征向量
idx = np.argsort(eigenvalues)[:self.n_clusters]
selected_eigenvectors = eigenvectors[:, idx]
# 5. 归一化特征向量(行归一化)
row_norms = np.linalg.norm(selected_eigenvectors, axis=1, keepdims=True)
normalized_vectors = selected_eigenvectors / (row_norms + 1e-10)
# 6. 使用K-means进行聚类
kmeans = KMeans(n_clusters=self.n_clusters, random_state=42)
labels = kmeans.fit_predict(normalized_vectors)
return labels
# 简化版谱聚类
def spectral_clustering_simple(X, n_clusters=2, gamma=1.0):
"""
简化的谱聚类实现
"""
# 计算相似度矩阵
pairwise_dists = squareform(pdist(X, 'euclidean'))
W = np.exp(-gamma * pairwise_dists ** 2)
# 计算度矩阵
D = np.diag(np.sum(W, axis=1))
# 计算拉普拉斯矩阵
D_inv_sqrt = np.linalg.inv(np.sqrt(D))
L = D_inv_sqrt @ (D - W) @ D_inv_sqrt
# 计算特征值和特征向量
eigenvalues, eigenvectors = np.linalg.eigh(L)
# 选择特征向量
idx = np.argsort(eigenvalues)[:n_clusters]
selected = eigenvectors[:, idx]
# K-means聚类
kmeans = KMeans(n_clusters=n_clusters, random_state=42)
labels = kmeans.fit_predict(selected)
return labels
测试脚本
import matplotlib.pyplot as plt
from sklearn.datasets import make_moons, make_circles
def test_spectral_clustering():
"""测试谱聚类算法"""
# 生成测试数据
X_moons, y_moons = make_moons(n_samples=200, noise=0.05, random_state=42)
X_circles, y_circles = make_circles(n_samples=200, noise=0.05, factor=0.5, random_state=42)
# 创建谱聚类实例
sc = SpectralClustering(n_clusters=2, gamma=10.0)
# 对moon数据进行聚类
labels_moons = sc.fit_predict(X_moons)
# 对circle数据进行聚类
labels_circles = sc.fit_predict(X_circles)
# 可视化结果
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
# moon数据原始标签
axes[0, 0].scatter(X_moons[:, 0], X_moons[:, 1], c=y_moons, cmap='viridis')
axes[0, 0].set_title('Moon Data - True Labels')
# moon数据聚类结果
axes[0, 1].scatter(X_moons[:, 0], X_moons[:, 1], c=labels_moons, cmap='viridis')
axes[0, 1].set_title('Moon Data - Spectral Clustering')
# circle数据原始标签
axes[1, 0].scatter(X_circles[:, 0], X_circles[:, 1], c=y_circles, cmap='viridis')
axes[1, 0].set_title('Circle Data - True Labels')
# circle数据聚类结果
axes[1, 1].scatter(X_circles[:, 0], X_circles[:, 1], c=labels_circles, cmap='viridis')
axes[1, 1].set_title('Circle Data - Spectral Clustering')
plt.tight_layout()
plt.show()
if __name__ == "__main__":
test_spectral_clustering()
使用scikit-learn的实现
from sklearn.cluster import SpectralClustering
from sklearn.preprocessing import StandardScaler
def sklearn_spectral_clustering(X, n_clusters=2):
"""
使用scikit-learn的谱聚类实现
"""
# 数据标准化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 创建谱聚类模型
spectral = SpectralClustering(
n_clusters=n_clusters,
affinity='rbf',
gamma=1.0,
random_state=42
)
# 执行聚类
labels = spectral.fit_predict(X_scaled)
return labels
参数优化脚本
def tune_parameters(X, n_clusters_range=[2, 3, 4, 5], gamma_range=[0.1, 1, 10]):
"""参数调优"""
from sklearn.metrics import silhouette_score
best_score = -1
best_params = {}
for n_clusters in n_clusters_range:
for gamma in gamma_range:
sc = SpectralClustering(n_clusters=n_clusters, gamma=gamma)
labels = sc.fit_predict(X)
# 计算轮廓系数
if len(np.unique(labels)) > 1:
score = silhouette_score(X, labels)
if score > best_score:
best_score = score
best_params = {
'n_clusters': n_clusters,
'gamma': gamma
}
return best_params, best_score
完整使用示例
import numpy as np
from sklearn.datasets import make_blobs
# 生成测试数据
X, y = make_blobs(n_samples=300, centers=3, n_features=2, random_state=42)
# 方法1:使用自定义实现
sc_custom = SpectralClustering(n_clusters=3, gamma=1.0)
labels_custom = sc_custom.fit_predict(X)
# 方法2:使用scikit-learn
labels_sklearn = sklearn_spectral_clustering(X, n_clusters=3)
# 方法3:使用简化版
labels_simple = spectral_clustering_simple(X, n_clusters=3, gamma=1.0)
# 比较结果
print(f"自定义实现聚类结果:{np.unique(labels_custom)}")
print(f"Sklearn实现聚类结果:{np.unique(labels_sklearn)}")
print(f"简化版聚类结果:{np.unique(labels_simple)}")
关键点说明
- 相似度矩阵构建:使用RBF核或KNN
- 拉普拉斯矩阵:归一化版本更稳定
- 特征分解:选择最小的k个特征值
- 后处理:使用K-means对特征向量聚类
这个实现包含了谱聚类的核心步骤,可以直接用于实际数据聚类任务。