本文目录导读:

我来详细讲解如何使用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提供了多种实现连通分量分析的方法:
- DBSCAN:基于密度的聚类,适合发现任意形状的分量
- k近邻图:通过图论方法找到连接的子图
- 谱聚类:基于图拉普拉斯矩阵的谱分解
- 层次聚类:通过层次化方法发现不同粒度的分量
选择哪种方法取决于你的具体需求:
- 数据量大小
- 分量形状(凸形/非凸形)
- 噪声处理要求
- 计算资源限制
在实际应用中,建议尝试多种方法并进行比较,选择最适合数据特征的方法。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播