sktime聚类与异常检测:发现时间序列模式
本文深入探讨了sktime库在时间序列聚类与异常检测方面的强大功能。文章系统介绍了TimeSeriesKMeans和TimeSeriesDBSCAN等专门针对时间序列设计的聚类算法,详细分析了动态时间规整(DTW)等多种距离度量方法及其适用场景。同时,文章涵盖了基于距离的聚类方法、核函数技术,以及SubLOF、STRAY等异常检测算法和二进制分割、贪婪高斯分割等变点检测技术。最后,文章提供了全面的聚类结果评估指标和可视化方法,帮助读者科学验证聚类质量并深入理解数据模式。
时间序列聚类算法:K-means、DBSCAN变体
时间序列聚类是发现时间序列数据中隐藏模式的重要技术,sktime库提供了多种专门针对时间序列设计的聚类算法。在时间序列分析中,传统的聚类算法需要适应时间序列的特殊性,包括时间依赖性、动态时间规整距离等特性。sktime通过扩展经典的K-means和DBSCAN算法,为时间序列聚类提供了强大的工具集。
TimeSeriesKMeans:时间序列K均值聚类
TimeSeriesKMeans是sktime中专门为时间序列数据设计的K均值聚类实现。与传统的K-means不同,它支持多种时间序列特定的距离度量和平均计算方法。
核心特性
from sktime.clustering.k_means import TimeSeriesKMeans
from sktime.datasets import load_arrow_head
# 加载示例数据
X, y = load_arrow_head()
# 创建TimeSeriesKMeans聚类器
clusterer = TimeSeriesKMeans(
n_clusters=3, # 聚类数量
metric="dtw", # 动态时间规整距离
init_algorithm="kmeans++", # 初始化算法
n_init=10, # 初始化次数
max_iter=300, # 最大迭代次数
averaging_method="dba", # 动态时间规整重心平均
random_state=42
)
# 拟合模型并进行预测
clusterer.fit(X)
labels = clusterer.predict(X)
支持的度量方法
TimeSeriesKMeans支持多种时间序列距离度量:
| 距离度量 | 描述 | 适用场景 |
|---|---|---|
| dtw | 动态时间规整 | 不同长度时间序列 |
| euclidean | 欧几里得距离 | 等长时间序列 |
| ddtw | 导数动态时间规整 | 捕捉形状变化 |
| wdtw | 加权动态时间规整 | 强调特定时间段 |
| lcss | 最长公共子序列 | 噪声数据 |
| edr | 编辑距离 | 序列相似性 |
平均计算方法
TimeSeriesDBSCAN:基于密度的聚类
TimeSeriesDBSCAN扩展了经典的DBSCAN算法,专门处理时间序列数据。它通过支持时间序列特定的距离度量来识别密度相连的簇。
算法实现
from sktime.clustering import TimeSeriesDBSCAN
from sktime.dists_kernels import DtwDist
# 使用自定义距离度量
clusterer = TimeSeriesDBSCAN(
distance="dtw", # 距离度量
eps=0.5, # 邻域半径
min_samples=5, # 核心点最小样本数
algorithm="auto", # 邻域搜索算法
leaf_size=30, # 树结构叶子大小
n_jobs=-1 # 并行计算
)
# 或者使用sktime距离转换器
dtw_distance = DtwDist()
clusterer = TimeSeriesDBSCAN(distance=dtw_distance, eps=1.0, min_samples=3)
距离度量支持
TimeSeriesDBSCAN支持三种类型的距离度量:
- 字符串标识符:内置的硬编码距离度量
- sktime成对转换器:可组合的一等公民
- 可调用函数:自定义距离函数
参数调优指南
| 参数 | 推荐值范围 | 影响 |
|---|---|---|
| eps | 0.1-2.0 | 控制簇的紧密程度 |
| min_samples | 3-10 | 控制噪声点的识别 |
| distance | dtw/euclidean | 影响聚类形状识别 |
算法比较与选择
下表对比了两种算法的主要特性:
| 特性 | TimeSeriesKMeans | TimeSeriesDBSCAN |
|---|---|---|
| 簇形状 | 球形 | 任意形状 |
| 噪声处理 | 无 | 自动识别噪声点 |
| 簇数量 | 需要预先指定 | 自动确定 |
| 距离度量 | 多种时间序列距离 | 多种时间序列距离 |
| 计算复杂度 | O(nki) | O(n²) |
| 内存需求 | 中等 | 较高 |
实际应用示例
心电图信号聚类
import numpy as np
from sktime.clustering.k_means import TimeSeriesKMeans
from sktime.clustering import TimeSeriesDBSCAN
# 生成模拟心电图数据
def generate_ecg_signals(n_samples=100, length=200):
signals = []
for i in range(n_samples):
# 模拟正常心电图
if i < 70:
signal = np.sin(np.linspace(0, 4*np.pi, length))
signal += np.random.normal(0, 0.1, length)
# 模拟异常心电图
else:
signal = np.sin(np.linspace(0, 6*np.pi, length)) * 0.8
signal += np.random.normal(0, 0.15, length)
signals.append(signal)
return np.array(signals)
# 生成数据并聚类
X_ecg = generate_ecg_signals()
X_ecg = X_ecg.reshape(-1, 1, 200) # 转换为3D格式
# 使用K-means聚类
kmeans = TimeSeriesKMeans(n_clusters=2, metric="dtw", averaging_method="dba")
kmeans_labels = kmeans.fit_predict(X_ecg)
# 使用DBSCAN聚类
dbscan = TimeSeriesDBSCAN(distance="dtw", eps=0.8, min_samples=5)
dbscan_labels = dbscan.fit_predict(X_ecg)
性能优化技巧
# 使用缓存距离矩阵加速计算
from sktime.dists_kernels import DtwDist
# 预计算距离矩阵
dtw = DtwDist()
distance_matrix = dtw.transform(X_ecg)
# 对于大型数据集,使用近似算法
clusterer = TimeSeriesKMeans(
n_clusters=3,
metric="dtw",
n_init=3, # 减少初始化次数
max_iter=100, # 减少最大迭代次数
verbose=True # 监控收敛过程
)
算法选择决策流程
通过sktime的TimeSeriesKMeans和TimeSeriesDBSCAN实现,研究人员和工程师可以有效地对时间序列数据进行聚类分析,发现数据中的潜在模式和异常行为。这些算法特别适用于金融时间序列分析、生物信号处理、工业传感器数据分析等领域。
基于距离的聚类方法与核函数
在时间序列分析中,基于距离的聚类方法和核函数技术是发现时间序列模式的重要工具。sktime库提供了丰富的距离度量和核函数实现,使得我们能够有效地对时间序列数据进行聚类分析。
距离度量方法
sktime支持多种距离度量方法,每种方法都针对不同类型的时间序列数据进行了优化:
动态时间规整(DTW)
动态时间规整是最常用的时间序列距离度量方法之一,它能够处理不同长度的时间序列并找到最优的对齐方式:
from sktime.dists_kernels.dtw import DtwDist
from sktime.datasets import load_arrow_head
# 加载示例数据
X, y = load_arrow_head()
# 创建DTW距离计算器
dtw_dist = DtwDist()
# 计算距离矩阵
distance_matrix = dtw_dist(X, X)
print(f"DTW距离矩阵形状: {distance_matrix.shape}")
其他距离度量
sktime还提供了多种其他距离度量方法:
| 距离度量 | 描述 | 适用场景 |
|---|---|---|
| LCSS | 最长公共子序列 | 处理噪声和异常值 |
| Edit Distance | 编辑距离 | 序列相似性比较 |
| GAK | 全局对齐核 | 核方法聚类 |
| Euclidean | 欧几里得距离 | 等长序列 |
核函数方法
核函数将数据映射到高维特征空间,使得在原始空间中线性不可分的数据变得线性可分:
高斯核函数
from sktime.dists_kernels import GaussianKernel
from sktime.clustering.kernel_k_means import KernelKMeans
# 创建高斯核函数
gaussian_kernel = GaussianKernel(sigma=1.0)
# 使用核K均值聚类
kernel_kmeans = KernelKMeans(n_clusters=3, kernel=gaussian_kernel)
labels = kernel_kmeans.fit_predict(X)
核函数组合
sktime支持核函数的代数组合,可以创建复杂的核函数:
from sktime.dists_kernels.algebra import CombinedDistance
from sktime.dists_kernels import GaussianKernel, LinearKernel
# 创建组合核函数
combined_kernel = CombinedDistance(
pw_trafos=[GaussianKernel(sigma=0.5), LinearKernel()],
operation="+"
)
基于距离的聚类算法
K-Medoids聚类
K-Medoids使用实际数据点作为聚类中心,对异常值更加鲁棒:
from sktime.clustering.k_medoids import KMedoids
# 使用DTW距离的K-Medoids聚类
kmedoids = KMedoids(
n_clusters=3,
metric="dtw",
n_init=10,
max_iter=300
)
clusters = kmedoids.fit_predict(X)
层次聚类
from sklearn.cluster import AgglomerativeClustering
from sktime.dists_kernels.dtw import DtwDist
# 计算距离矩阵
dtw = DtwDist()
dist_matrix = dtw(X, X)
# 层次聚类
agg_clustering = AgglomerativeClustering(
n_clusters=3,
affinity='precomputed',
linkage='average'
)
labels = agg_clustering.fit_predict(dist_matrix)
核K均值聚类
核K均值算法在特征空间中进行聚类,能够发现复杂的非线性模式:
from sktime.clustering.kernel_k_means import KernelKMeans
from sktime.dists_kernels import GaussianKernel
# 配置核K均值聚类器
kernel_kmeans = KernelKMeans(
n_clusters=3,
kernel="gak", # 使用全局对齐核
kernel_params={"sigma": 1.0},
n_init=5,
max_iter=100,
verbose=True
)
# 执行聚类
cluster_labels = kernel_kmeans.fit_predict(X)
距离度量的选择策略
选择合适的距离度量对聚类结果至关重要:
性能优化技巧
对于大规模时间序列数据,可以采用以下优化策略:
- 下采样:降低时间序列分辨率
- 边界约束:使用DTW的窗口约束
- 近似算法:使用快速DTW算法
- 并行计算:利用多核处理器
from sktime.dists_kernels.dtw import DtwDist
# 使用带窗口约束的DTW
dtw_fast = DtwDist(window=10) # 设置窗口大小
# 启用多线程计算
dtw_parallel = DtwDist(n_jobs=-1) # 使用所有可用核心
实际应用案例
心电图信号聚类
import numpy as np
from sktime.clustering.k_medoids import KMedoids
from sktime.dists_kernels.dtw import DtwDist
# 模拟心电图数据
n_samples = 100
series_length = 200
X_ecg = np.random.randn(n_samples, 1, series_length)
# 使用DTW距离的K-Medoids聚类
ecg_clusterer = KMedoids(
n_clusters=4,
metric="dtw",
distance_params={"window": 15},
n_init=10
)
ecg_labels = ecg_clusterer.fit_predict(X_ecg)
工业传感器数据分析
from sktime.clustering.kernel_k_means import KernelKMeans
from sktime.dists_kernels import GaussianKernel
# 工业传感器数据聚类
sensor_clusterer = KernelKMeans(
n_clusters=5,
kernel=GaussianKernel(sigma=0.8),
n_init=8,
max_iter=200,
verbose=True
)
sensor_labels = sensor_clusterer.fit_predict(sensor_data)
评估聚类质量
使用内部指标评估聚类结果:
from sklearn.metrics import silhouette_score
from sktime.dists_kernels.dtw import DtwDist
# 计算轮廓系数
dtw = DtwDist()
dist_matrix = dtw(X, X)
silhouette_avg = silhouette_score(dist_matrix, labels, metric="precomputed")
print(f"轮廓系数: {silhouette_avg:.3f}")
基于距离的聚类方法和核函数为时间序列分析提供了强大的工具组合。通过选择合适的距离度量和核函数,结合适当的聚类算法,我们能够有效地发现时间序列数据中的潜在模式和结构。sktime库的丰富实现使得这些高级技术变得易于使用,为时间序列聚类分析提供了完整的解决方案。
异常检测与变点检测技术
在时间序列分析中,异常检测和变点检测是两个核心任务,它们帮助我们发现数据中的异常模式和结构变化。sktime提供了丰富的检测算法,涵盖了从传统的统计方法到现代的机器学习技术。
异常检测算法
基于局部离群因子(LOF)的异常检测
sktime的SubLOF类实现了基于窗口的局部离群因子算法,专门针对时间序列数据进行了优化:
from sktime.detection.lof import SubLOF
import pandas as pd
import numpy as np
# 创建包含异常的时间序列数据
data = pd.Series([1.0, 1.2, 0.9, 1.1, 15.6, 1.3, 0.8, 1.0, 12.4, 1.1, 0.9])
# 初始化LOF检测器
lof_detector = SubLOF(
n_neighbors=5,
window_size=3,
novelty=True,
contamination='auto'
)
# 训练模型并检测异常
lof_detector.fit(data)
anomalies = lof_detector.predict(data)
print("检测到的异常位置:", anomalies['ilocs'].values)
算法特点:
- 基于滑动窗口处理时间序列
- 自动适应不同时间间隔的数据
- 支持多变量时间序列检测
- 可调节的邻域大小和污染率参数
STRAY异常检测算法
STRAY(Search TRace AnomalY)是一种基于极端值理论的鲁棒异常检测方法:
from sktime.detection.stray import STRAY
from sklearn.preprocessing import StandardScaler
# 准备数据
X = np.random.randn(100, 2)
X[25, :] = [10, 10] # 添加异常点
X[75, :] = [-8, -8] # 添加另一个异常点
# 数据标准化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# STRAY异常检测
stray_detector = STRAY(
alpha=0.01, # 显著性水平
k=10, # 近邻数量
p=0.5, # 异常候选比例
size_threshold=50 # 样本大小阈值
)
anomalies = stray_detector.fit_transform(X_scaled)
print("异常检测结果:", np.where(anomalies)[0])
变点检测技术
二进制分割算法
二进制分割(Binary Segmentation)是一种经典的变点检测方法:
from sktime.detection.bs import BinarySegmentation
from sktime.detection.datagen import piecewise_normal
# 生成分段常数时间序列
np.random.seed(42)
data = piecewise_normal(
means=[1, 5, 2, 8],
lengths=[20, 30, 25, 35],
std_dev=0.5
)
# 二进制分割变点检测
bs_detector = BinarySegmentation(
threshold=2.0, # CUMSUM统计量阈值
min_cp_distance=5, # 最小变点间距
max_iter=1000 # 最大迭代次数
)
change_points = bs_detector.fit_predict(pd.Series(data))
print("检测到的变点位置:", change_points['ilocs'].values)
贪婪高斯分割(GGS)
Greedy Gaussian Segmentation是一种基于似然比的变点检测方法:
from sktime.detection.ggs import GreedyGaussianSegmentation
# 使用GGS进行变点检测
ggs_detector = GreedyGaussianSegmentation(
k_max=10, # 最大变点数量
lamb=1.0, # 正则化参数
max_shuffles=250 # 最大重排次数
)
segments = ggs_detector.fit_predict(pd.Series(data))
print("检测到的分段:", segments)
检测器性能评估
sktime提供了统一的评估框架来比较不同检测器的性能:
from sktime.detection.base import BaseDetector
from sktime.performance_metrics.detection import detection_accuracy
class CustomDetector(BaseDetector):
"""自定义检测器示例"""
_tags = {
"task": "anomaly_detection",
"learning_type": "unsupervised"
}
def __init__(self, threshold=3.0):
self.threshold = threshold
super().__init__()
def _fit(self, X, y=None):
self.mean_ = X.mean()
self.std_ = X.std()
return self
def _predict(self, X):
z_scores = np.abs((X - self.mean_) / self.std_)
anomalies = np.where(z_scores > self.threshold)[0]
return pd.DataFrame({'ilocs': anomalies})
# 评估检测器性能
custom_detector = CustomDetector(threshold=3.0)
custom_detector.fit(data)
predictions = custom_detector.predict(data)
# 假设有真实标签
true_anomalies = pd.DataFrame({'ilocs': [20, 50, 75]})
accuracy = detection_accuracy(true_anomalies, predictions)
print(f"检测准确率: {accuracy:.3f}")
多算法比较表格
下表对比了sktime中主要的异常检测和变点检测算法:
| 算法名称 | 类型 | 适用场景 | 参数调节 | 计算复杂度 | 多变量支持 |
|---|---|---|---|---|---|
| SubLOF | 异常检测 | 局部异常点检测 | 窗口大小、近邻数 | O(n²) | 是 |
| STRAY | 异常检测 | 高维数据异常 | 显著性水平、近邻数 | O(n log n) | 是 |
| BinarySegmentation | 变点检测 | 均值变化检测 | 阈值、最小间距 | O(n log n) | 否 |
| GreedyGaussianSegmentation | 变点检测 | 高斯分布变化 | 最大变点数、正则化 | O(kn²) | 否 |
| InformationGainSegmentation | 变点检测 | 信息增益变化 | 最大变点数、步长 | O(kn) | 是 |
实际应用案例
金融时间序列异常检测
import yfinance as yf
from sktime.detection.lof import SubLOF
import matplotlib.pyplot as plt
# 获取股票数据
ticker = yf.Ticker("AAPL")
data = ticker.history(period="1y")['Close']
# 检测价格异常
lof_detector = SubLOF(n_neighbors=20, window_size=20)
lof_detector.fit(data)
anomalies = lof_detector.predict(data)
# 可视化结果
plt.figure(figsize=(12, 6))
plt.plot(data.index, data.values, label='Apple Stock Price')
plt.scatter(data.index[anomalies['ilocs']],
data.iloc[anomalies['ilocs']],
color='red', label='Anomalies')
plt.title('Apple Stock Price Anomaly Detection')
plt.legend()
plt.show()
工业设备监控变点检测
from sktime.detection.bs import BinarySegmentation
from sktime.datasets import load_airline
# 加载航空乘客数据
airline_data = load_airline()
# 检测客流变化点
bs_detector = BinarySegmentation(threshold=50)
change_points = bs_detector.fit_predict(airline_data)
print("检测到的客流变化点:")
for cp in change_points['ilocs']:
print(f"位置 {cp}: 时间 {airline_data.index[cp]}, 值 {airline_data.iloc[cp]}")
算法选择指南
选择合适的检测算法需要考虑多个因素:
最佳实践建议
- 数据预处理:确保时间序列数据经过适当的清洗和标准化处理
- 参数调优:使用交叉验证或网格搜索优化算法参数
- 多算法比较:尝试多种算法并比较它们的性能
- 结果解释:结合领域知识解释检测结果的实际意义
- 实时监测:对于流式数据,考虑使用在线学习版本的检测算法
sktime的异常检测和变点检测模块提供了强大而灵活的工具集,能够满足各种时间序列分析需求。通过合理选择算法和参数配置,可以有效地发现数据中的隐藏模式和异常行为。
聚类结果评估与可视化
在时间序列聚类分析中,仅仅获得聚类标签是不够的,我们还需要对聚类结果进行科学的评估和直观的可视化,以验证聚类质量、理解聚类结构,并为后续决策提供依据。sktime提供了丰富的评估指标和可视化工具,帮助用户深入分析聚类结果。
聚类质量评估指标
sktime支持多种聚类评估指标,从不同角度衡量聚类效果:
1. 内部评估指标
内部评估指标基于聚类数据本身的结构特征,无需外部标签信息:
from sklearn.metrics import davies_bouldin_score, silhouette_score
import numpy as np
# Davies-Bouldin指数:值越小表示聚类效果越好
def evaluate_davies_bouldin(clusterer, X):
labels = clusterer.predict(X)
return davies_bouldin_score(X.reshape(X.shape[0], -1), labels)
# 轮廓系数:值越接近1表示聚类效果越好
def evaluate_silhouette(clusterer, X):
labels = clusterer.predict(X)
return silhouette_score(X.reshape(X.shape[0], -1), labels)
# 惯性(Inertia):聚类内部平方和,值越小越好
def evaluate_inertia(clusterer):
return getattr(clusterer, 'inertia_', None)
2. 外部评估指标(当有真实标签时)
当数据集包含真实类别标签时,可以使用外部评估指标:
from sklearn.metrics import adjusted_rand_score, normalized_mutual_info_score
def evaluate_external_metrics(clusterer, X, true_labels):
pred_labels = clusterer.predict(X)
metrics = {
'adjusted_rand_score': adjusted_rand_score(true_labels, pred_labels),
'normalized_mutual_info': normalized_mutual_info_score(true_labels, pred_labels),
'homogeneity': homogeneity_score(true_labels, pred_labels),
'completeness': completeness_score(true_labels, pred_labels)
}
return metrics
聚类结果可视化
sktime提供了专门的绘图工具来可视化聚类结果:
1. 聚类分区可视化
from sktime.clustering.utils.plotting import plot_cluster_algorithm
import matplotlib.pyplot as plt
# 基本聚类可视化
def visualize_clusters(clusterer, X, n_clusters):
"""
可视化聚类结果,显示每个簇的时间序列和簇中心
"""
plt.figure(figsize=(12, 8))
plot_cluster_algorithm(clusterer, X, n_clusters)
plt.title(f'Clustering Results with {n_clusters} Clusters')
plt.tight_layout()
plt.show()
# 使用示例
kmeans = TimeSeriesKMeans(n_clusters=3, random_state=42)
kmeans.fit(X_train)
visualize_clusters(kmeans, X_test, kmeans.n_clusters)
2. 多维可视化技术
对于高维时间序列数据,可以使用降维技术进行可视化:
from sklearn.manifold import TSNE
from sklearn.decomposition import PCA
def visualize_high_dimensional_clusters(clusterer, X, method='tsne'):
"""
使用降维技术可视化高维聚类结果
"""
labels = clusterer.predict(X)
# 将时间序列数据展平为2D数组
X_flat = X.reshape(X.shape[0], -1)
if method == 'tsne':
reducer = TSNE(n_components=2, random_state=42)
else:
reducer = PCA(n_components=2)
X_reduced = reducer.fit_transform(X_flat)
plt.figure(figsize=(10, 8))
scatter = plt.scatter(X_reduced[:, 0], X_reduced[:, 1],
c=labels, cmap='viridis', alpha=0.7)
plt.colorbar(scatter)
plt.title(f'Cluster Visualization using {method.upper()}')
plt.xlabel('Component 1')
plt.ylabel('Component 2')
plt.show()
3. 簇中心对比分析
def compare_cluster_centers(clusterer):
"""
比较不同簇的中心序列
"""
centers = clusterer.cluster_centers_
n_clusters = centers.shape[0]
fig, axes = plt.subplots(n_clusters, 1, figsize=(12, 3*n_clusters))
for i in range(n_clusters):
axes[i].plot(centers[i][0], label=f'Cluster {i} Center', linewidth=2)
axes[i].set_title(f'Cluster {i} Center')
axes[i].legend()
axes[i].grid(True)
plt.tight_layout()
plt.show()
# 统计每个簇的大小
def cluster_size_distribution(clusterer, X):
labels = clusterer.predict(X)
unique, counts = np.unique(labels, return_counts=True)
plt.figure(figsize=(10, 6))
plt.bar(unique, counts)
plt.title('Cluster Size Distribution')
plt.xlabel('Cluster Label')
plt.ylabel('Number of Instances')
plt.xticks(unique)
plt.show()
return dict(zip(unique, counts))
综合评估报告
创建一个完整的聚类评估报告:
def generate_clustering_report(clusterer, X, true_labels=None):
"""
生成全面的聚类评估报告
"""
report = {}
# 内部评估指标
report['davies_bouldin'] = evaluate_davies_bouldin(clusterer, X)
report['silhouette'] = evaluate_silhouette(clusterer, X)
report['inertia'] = evaluate_inertia(clusterer)
# 外部评估指标(如果有真实标签)
if true_labels is not None:
external_metrics = evaluate_external_metrics(clusterer, X, true_labels)
report.update(external_metrics)
# 簇大小分布
labels = clusterer.predict(X)
unique, counts = np.unique(labels, return_counts=True)
report['cluster_sizes'] = dict(zip(unique, counts))
report['n_clusters'] = len(unique)
return report
def print_report(report):
"""
格式化打印评估报告
"""
print("="*50)
print("CLUSTERING EVALUATION REPORT")
print("="*50)
print(f"\nInternal Metrics:")
print(f" Davies-Bouldin Index: {report.get('davies_bouldin', 'N/A'):.4f}")
print(f" Silhouette Score: {report.get('silhouette', 'N/A'):.4f}")
print(f" Inertia: {report.get('inertia', 'N/A'):.4f}")
if 'adjusted_rand_score' in report:
print(f"\nExternal Metrics:")
for metric, value in [(k,v) for k,v in report.items()
if k in ['adjusted_rand_score', 'normalized_mutual_info']]:
print(f" {metric}: {value:.4f}")
print(f"\nCluster Distribution:")
for cluster, size in report.get('cluster_sizes', {}).items():
print(f" Cluster {cluster}: {size} instances")
print(f"\nTotal clusters: {report.get('n_clusters', 'N/A')}")
高级可视化技术
1. 热图可视化
def cluster_heatmap(clusterer, X):
"""
创建聚类结果的热图可视化
"""
labels = clusterer.predict(X)
# 按簇标签排序
sort_idx = np.argsort(labels)
sorted_X = X[sort_idx]
sorted_labels = labels[sort_idx]
plt.figure(figsize=(15, 10))
plt.imshow(sorted_X[:, 0, :], aspect='auto', cmap='viridis')
plt.colorbar(label='Value')
# 添加簇边界
unique_labels = np.unique(sorted_labels)
for label in unique_labels:
idx = np.where(sorted_labels == label)[0]
if len(idx) > 0:
plt.axhline(y=idx[0]-0.5, color='red', linestyle='--', alpha=0.7)
plt.axhline(y=idx[-1]+0.5, color='red', linestyle='--', alpha=0.7)
plt.title('Cluster Heatmap (Instances Sorted by Cluster)')
plt.xlabel('Time Steps')
plt.ylabel('Instances (Sorted by Cluster)')
plt.show()
2. 时间序列特征可视化
def cluster_feature_analysis(clusterer, X):
"""
分析每个簇的统计特征
"""
labels = clusterer.predict(X)
unique_labels = np.unique(labels)
features = {}
for label in unique_labels:
cluster_data = X[labels == label]
# 计算基本统计特征
features[label] = {
'mean': np.mean(cluster_data, axis=(0, 2)),
'std': np.std(cluster_data, axis=(0, 2)),
'min': np.min(cluster_data, axis=(0, 2)),
'max': np.max(cluster_data, axis=(0, 2)),
'size': len(cluster_data)
}
# 可视化特征对比
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
metrics = ['mean', 'std', 'min', 'max']
titles = ['Mean Values', 'Standard Deviation', 'Minimum Values', 'Maximum Values']
for i, (metric, title) in enumerate(zip(metrics, titles)):
ax = axes[i//2, i%2]
for label in unique_labels:
ax.plot(features[label][metric], label=f'Cluster {label}', marker='o')
ax.set_title(title)
ax.legend()
ax.grid(True)
plt.tight_layout()
plt.show()
return features
评估流程示意图
实际应用示例
# 完整的聚类评估流程示例
def complete_clustering_analysis(X, n_clusters=3, true_labels=None):
"""
执行完整的聚类分析和评估流程
"""
# 1. 聚类
kmeans = TimeSeriesKMeans(n_clusters=n_clusters, random_state=42)
kmeans.fit(X)
# 2. 评估
report = generate_clustering_report(kmeans, X, true_labels)
print_report(report)
# 3. 可视化
visualize_clusters(kmeans, X, n_clusters)
cluster_heatmap(kmeans, X)
cluster_feature_analysis(kmeans, X)
if X.shape[1] > 1: # 如果是多维数据
visualize_high_dimensional_clusters(kmeans, X, 'pca')
visualize_high_dimensional_clusters(kmeans, X, 'tsne')
return kmeans, report
# 使用示例
# kmeans_model, evaluation_report = complete_clustering_analysis(X_data, n_clusters=4, true_labels=y_true)
通过上述评估和可视化技术,我们可以全面了解聚类结果的质量、发现数据中的潜在模式,并为后续的模型优化和业务决策提供有力支持。sktime提供的这些工具使得时间序列聚类分析变得更加直观和科学。
总结
sktime库为时间序列分析提供了完整的聚类与异常检测解决方案。通过专业的TimeSeriesKMeans、TimeSeriesDBSCAN等算法,结合DTW等多种距离度量,能够有效处理时间序列的特殊性。异常检测和变点检测模块涵盖了从传统统计方法到现代机器学习技术,而全面的评估指标和可视化工具则为结果验证提供了科学依据。这些工具的有机结合使得研究人员和工程师能够深入挖掘时间序列数据中的潜在模式,为金融分析、生物信号处理、工业监控等领域的实际应用提供强大支持。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



