Python案例如何用Scikit-learn做连通分量

wen python案例 1

本文目录导读:

Python案例如何用Scikit-learn做连通分量

  1. 数据集准备
  2. 基于DBSCAN的连通分量分析
  3. 基于最近邻图的连通分量
  4. 基于谱聚类的连通分量
  5. 高级应用:层次连通分量分析
  6. 实际应用案例:图像分割
  7. 性能评估与优化
  8. 实际应用:社交网络分析

我来详细讲解如何使用Scikit-learn进行连通分量分析,连通分量分析常用于图像处理、图论分析等领域。

数据集准备

1 创建示例数据

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.cluster import DBSCAN
from sklearn.neighbors import kneighbors_graph
from sklearn.manifold import spectral_embedding
from sklearn import datasets
# 生成示例数据集(月亮形状数据)
X, y = datasets.make_moons(n_samples=200, noise=0.05, random_state=42)
# 可视化原始数据
plt.figure(figsize=(8, 6))
plt.scatter(X[:, 0], X[:, 1], c=y, cmap='viridis')'原始数据分布')
plt.xlabel('特征1')
plt.ylabel('特征2')
plt.show()

基于DBSCAN的连通分量分析

1 DBSCAN实现连通分量

# 使用DBSCAN进行聚类,eps控制邻域大小
dbscan = DBSCAN(eps=0.2, min_samples=5)
clusters = dbscan.fit_predict(X)
# 可视化连通分量
plt.figure(figsize=(10, 6))
unique_clusters = np.unique(clusters)
# 为不同分量着色
colors = ['blue', 'red', 'green', 'purple', 'orange', 'brown']
for i, cluster_id in enumerate(unique_clusters):
    mask = clusters == cluster_id
    if cluster_id == -1:  # 噪声点
        plt.scatter(X[mask, 0], X[mask, 1], c='gray', 
                   label='噪声', alpha=0.5, marker='x')
    else:
        plt.scatter(X[mask, 0], X[mask, 1], c=colors[i % len(colors)], 
                   label=f'分量 {cluster_id}')
'DBSCAN连通分量分析')
plt.xlabel('特征1')
plt.ylabel('特征2')
plt.legend()
plt.show()
print(f"找到的连通分量数量(不包括噪声): {len(unique_clusters[unique_clusters != -1])}")

基于最近邻图的连通分量

1 构建k近邻图

from scipy.sparse.csgraph import connected_components
from sklearn.neighbors import NearestNeighbors
# 构建k近邻图
k = 5
nn = NearestNeighbors(n_neighbors=k)
nn.fit(X)
knn_graph = nn.kneighbors_graph(X, mode='distance')
# 计算连通分量
n_components, labels = connected_components(csgraph=knn_graph, directed=False, return_labels=True)
print(f"k近邻图中的连通分量数量: {n_components}")
# 可视化连通分量
plt.figure(figsize=(10, 6))
colors = plt.cm.Set1(np.linspace(0, 1, n_components))
for i in range(n_components):
    mask = labels == i
    plt.scatter(X[mask, 0], X[mask, 1], c=[colors[i]], 
               label=f'分量 {i}', alpha=0.7)
f'基于k近邻图(K={k})的连通分量')
plt.xlabel('特征1')
plt.ylabel('特征2')
plt.legend()
plt.show()

基于谱聚类的连通分量

1 谱聚类实现

from sklearn.cluster import SpectralClustering
# 谱聚类
n_components_spectral = 2
spectral = SpectralClustering(n_clusters=n_components_spectral, 
                              affinity='nearest_neighbors',
                              random_state=42)
spectral_labels = spectral.fit_predict(X)
# 可视化谱聚类结果
plt.figure(figsize=(10, 6))
plt.scatter(X[:, 0], X[:, 1], c=spectral_labels, cmap='viridis')'谱聚类连通分量分析')
plt.xlabel('特征1')
plt.ylabel('特征2')
plt.colorbar(label='分量标签')
plt.show()

高级应用:层次连通分量分析

1 层次聚类实现

from sklearn.cluster import AgglomerativeClustering
from scipy.cluster.hierarchy import dendrogram
# 层次聚类
hierarchical = AgglomerativeClustering(n_clusters=None, 
                                       distance_threshold=0.3,
                                       linkage='ward')
hierarchical_labels = hierarchical.fit_predict(X)
# 可视化层次聚类结果
plt.figure(figsize=(10, 6))
unique_labels = np.unique(hierarchical_labels)
colors = plt.cm.tab20(np.linspace(0, 1, len(unique_labels)))
for i, label in enumerate(unique_labels):
    mask = hierarchical_labels == label
    plt.scatter(X[mask, 0], X[mask, 1], c=[colors[i]], 
               label=f'分量 {label}', alpha=0.7)
'层次聚类连通分量分析')
plt.xlabel('特征1')
plt.ylabel('特征2')
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.tight_layout()
plt.show()

实际应用案例:图像分割

1 图像连通分量分析

from sklearn.feature_extraction import image
from sklearn.cluster import KMeans
# 创建模拟图像数据
np.random.seed(42)
image_shape = (50, 50)
image_data = np.random.rand(*image_shape)
# 添加一些结构化的区域
image_data[10:20, 10:20] = 0.8
image_data[30:40, 30:40] = 0.2
image_data[5:15, 35:45] = 0.6
# 转换为特征矩阵
X_img = image_data.reshape(-1, 1)
# 使用KMeans进行图像分割
kmeans = KMeans(n_clusters=3, random_state=42)
labels_img = kmeans.fit_predict(X_img)
labels_img_2d = labels_img.reshape(image_shape)
# 可视化
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
axes[0].imshow(image_data, cmap='gray')
axes[0].set_title('原始图像')
axes[1].imshow(labels_img_2d, cmap='viridis')
axes[1].set_title('连通分量分割结果')
plt.tight_layout()
plt.show()

性能评估与优化

1 评估不同方法的性能

import time
from sklearn.metrics import silhouette_score
# 定义测试方法
methods = {
    'DBSCAN': {'estimator': DBSCAN(eps=0.2, min_samples=5), 'params': {}},
    'Spectral': {'estimator': SpectralClustering(n_clusters=2, random_state=42), 'params': {}},
    'Hierarchical': {'estimator': AgglomerativeClustering(n_clusters=2), 'params': {}}
}
results = []
for method_name, method_dict in methods.items():
    start_time = time.time()
    # 拟合模型
    labels_pred = method_dict['estimator'].fit_predict(X)
    # 计算时间
    elapsed_time = time.time() - start_time
    # 计算轮廓系数(如果有多个分量)
    if len(np.unique(labels_pred)) > 1:
        silhouette = silhouette_score(X, labels_pred)
    else:
        silhouette = None
    results.append({
        'method': method_name,
        'time': elapsed_time,
        'silhouette_score': silhouette,
        'n_components': len(np.unique(labels_pred))
    })
# 显示结果
results_df = pd.DataFrame(results)
print("性能比较:")
print(results_df)

实际应用:社交网络分析

1 网络图的连通分量

from sklearn.neighbors import radius_neighbors_graph
# 模拟社交网络数据
np.random.seed(42)
n_users = 100
user_features = np.random.randn(n_users, 5)
# 构建基于半径的邻接图
radius = 2.5
adjacency_graph = radius_neighbors_graph(user_features, radius=radius)
# 计算连通分量
n_components_network, component_labels = connected_components(
    csgraph=adjacency_graph, directed=False, return_labels=True
)
# 统计分量大小
component_sizes = pd.Series(component_labels).value_counts().sort_index()
print(f"社交网络中的连通分量数量: {n_components_network}")
print("\n各分量大小:")
print(component_sizes.head(10))
# 可视化分量分布
plt.figure(figsize=(10, 4))
plt.subplot(1, 2, 1)
component_sizes.plot(kind='bar', color='skyblue')'各连通分量大小分布')
plt.xlabel('分量编号')
plt.ylabel('节点数量')
plt.subplot(1, 2, 2)
plt.hist(component_sizes, bins=20, color='lightgreen', edgecolor='black')'分量大小直方图')
plt.xlabel('分量大小')
plt.ylabel('频率')
plt.tight_layout()
plt.show()

Scikit-learn提供了多种实现连通分量分析的方法:

  1. DBSCAN:基于密度的聚类,适合发现任意形状的分量
  2. k近邻图:通过图论方法找到连接的子图
  3. 谱聚类:基于图拉普拉斯矩阵的谱分解
  4. 层次聚类:通过层次化方法发现不同粒度的分量

选择哪种方法取决于你的具体需求:

  • 数据量大小
  • 分量形状(凸形/非凸形)
  • 噪声处理要求
  • 计算资源限制

在实际应用中,建议尝试多种方法并进行比较,选择最适合数据特征的方法。

抱歉,评论功能暂时关闭!