单时间序列数组的DBSCAN与层次聚类实现及可视化问题
问题解答
1. 单数组数据能否聚类?
完全可以。聚类算法支持一维数据,只是Scikit-learn的聚类API要求输入为二维数组格式(形状为(样本数量, 特征数量)),你的一维数组x需要转换成(10000, 1)的二维结构才能被算法正确识别。
2. 修正DBSCAN代码并实现层次聚类
以下是完整的可运行代码,包含数据预处理、DBSCAN聚类、层次聚类,以及结果可视化:
import numpy as np import matplotlib.pyplot as plt from sklearn.cluster import DBSCAN from sklearn.preprocessing import StandardScaler import scipy.cluster.hierarchy as hac # 生成数据 x = np.linspace(0, 500, 10000) x = 1.5 * np.sin(x) # 将一维数组转为二维格式 (样本数, 特征数) X = x.reshape(-1, 1) # 标准化数据(对DBSCAN这类基于距离的算法很重要) scaler = StandardScaler() X_scaled = scaler.fit_transform(X) # ---------------------- DBSCAN聚类 ---------------------- # 调整eps参数,因为数据已标准化,eps值要对应缩放后的数据 dbscan = DBSCAN(eps=0.3, min_samples=5) db_labels = dbscan.fit_predict(X_scaled) # ---------------------- 层次聚类 ---------------------- # 构建层次聚类模型,使用ward方法(最小化类内方差) linkage_matrix = hac.linkage(X_scaled, method='ward') # 生成聚类标签(这里设定聚成3类,可根据需求调整) hier_labels = hac.fcluster(linkage_matrix, t=3, criterion='maxclust') # ---------------------- 可视化结果 ---------------------- plt.figure(figsize=(16, 8)) # 子图1:原始数据+DBSCAN聚类结果 plt.subplot(1, 2, 1) # 绘制原始数据散点,用不同颜色区分聚类标签(-1代表噪声点) unique_db_labels = np.unique(db_labels) colors = plt.cm.get_cmap('viridis', len(unique_db_labels)) for label in unique_db_labels: mask = db_labels == label plt.scatter(x[mask], np.zeros_like(x[mask]), c=[colors(label)], label=f'Cluster {label}', s=5) plt.title('DBSCAN Clustering Results on Original Data') plt.xlabel('x value') plt.legend() # 子图2:原始数据+层次聚类结果 plt.subplot(1, 2, 2) unique_hier_labels = np.unique(hier_labels) colors_hier = plt.cm.get_cmap('plasma', len(unique_hier_labels)) for label in unique_hier_labels: mask = hier_labels == label plt.scatter(x[mask], np.zeros_like(x[mask]), c=[colors_hier(label)], label=f'Cluster {label}', s=5) plt.title('Hierarchical Clustering Results on Original Data') plt.xlabel('x value') plt.legend() # 绘制层次聚类树状图(可选,单独展示) plt.figure(figsize=(12, 6)) hac.dendrogram(linkage_matrix, truncate_mode='lastp', p=10, show_leaf_counts=True) plt.title('Hierarchical Clustering Dendrogram') plt.xlabel('Sample Index') plt.ylabel('Distance') plt.tight_layout() plt.show()
关键说明
- 输入格式转换:用
x.reshape(-1, 1)将一维数组转为二维,这是解决你DBSCAN报错的核心原因——Scikit-learn不接受一维输入。 - 数据标准化:DBSCAN基于距离计算,标准化后数据的距离尺度更合理,避免因特征范围过大导致聚类结果偏差。
- 参数调整:
- DBSCAN的
eps和min_samples需要根据数据分布调整,标准化后eps通常取0.1-1之间的值; - 层次聚类的
t参数(聚类数)可根据业务需求或树状图的距离阈值调整。
- DBSCAN的
- 噪声点识别:DBSCAN中标签为
-1的点是被识别的噪声点,层次聚类默认不会标记噪声,所有样本都会被分配到某个聚类中。
内容的提问来源于stack exchange,提问作者pro
相关产品推荐
相关产品推荐

