形状距离 Shapelet:基于判别性子序列的时序分类
形状距离 Shapelet 教程
什么是 Shapelet?
Shapelet 是时间序列中最具有判别性的局部形状模式,它能够最大程度地区分不同类别的时间序列。与依赖全局特征的传统方法不同,Shapelet 通过捕捉关键局部特征,实现高精度且可解释的时间序列分类。该概念由 Ye 和 Keogh 在 2009 年正式提出,已成为时序数据挖掘中的一项基础技术。
一个典型的例子是区分“行走”与“跑步”的加速度信号:两者的整体轮廓相似,但“跑步”信号中存在更尖锐的峰值和更短的步态周期。Shapelet 能够自动定位到这类判别性的短片段,而非依赖整个序列的长度。
Shapelet 的核心概念
判别性子序列
假设有一个时间序列数据集,每个样本属于某个类别。Shapelet 就是一个子序列(连续的一段),使得不同类别的序列与该子序列的距离分布存在显著差异。这种差异通常用信息增益或F统计量来量化。子序列本身是一个时间序列片段,其长度远小于原始序列。
形状距离定义
给定一个 Shapelet S(长度为 L)和一条时间序列 T(长度大于 L),我们通过子序列距离来度量它们之间的相似性:将 S 在 T 上滑动,计算 S 与每一个等长子序列的欧氏距离(通常需做 Z-归一化),取最小值作为 S 到 T 的距离。
Subsequence_Dist(S, T) = min_{窗口j} Euclidean_Distance(S, T[j:j+L])
这个最小值反映出 T 中是否存在与 S 最匹配的片段。具有高判别性的 S 应使类内距离小、类间距离大。
如何发现 Shapelet?
暴力搜索法
最初的 Shapelet 发现算法采用暴力搜索:
- 生成数据集中所有时间序列的所有可能长度(通常从最小长度到序列长度的一半)的子序列。
- 对每一个候选子序列,计算它与数据集中每一条时间序列的子序列距离,得到一个距离值。
- 将距离值作为特征,根据类别标签计算该候选的信息增益。
- 保留信息增益最高的一个或多个候选作为 Shapelet。
该方法的时间复杂度极高(O(n²m⁴),n为序列数,m为序列长度),仅适用于较短序列。
加速与剪枝技术
为使其可行,后来发展出多种加速策略:
- 早期放弃(Early Abandon):在计算候选与某序列的最小距离时,若已超过当前最优距离,则不需精确计算,可直接跳过。
- 熵剪枝(Entropy Pruning):利用信息增益的上界进行剪枝,当候选的形状即使在未来计算中也不可能超越当前最优时,提前终止。
- 哈希加速:将子序列映射到符号化表示,快速过滤不相似的对,减少精确距离计算。
Shapelet 变换
为了解决原生 Shapelet 对分类器选择的限制,Shapelet 变换方法不再将 Shapelet 嵌入决策树,而是将其作为一种特征提取器:
- 从训练集中提取 k 个最优 Shapelet。
- 对于每一条时间序列,计算其到这 k 个 Shapelet 的子序列距离,形成一个 k 维的特征向量。
- 使用任意分类器(如 SVM、随机森林)在这个新特征空间上训练。
这种变换极大地提升了灵活性和泛化能力。
使用 Shapelet 进行分类
距离度量选择
实际应用中常使用Z-归一化欧氏距离,以消除偏移和尺度影响。此外,也可采用动态时间规整(DTW)距离,但会增加计算成本。对于周期性信号,有时会引入相位约束。
训练分类器
基于 Shapelet 的分类有两种主流方式:
- 形状树(Shape Tree):将 Shapelet 作为决策节点的分裂规则,分裂阈值由 Shapelet 距离的最优分割点确定。决策树的结构可直接解释分类逻辑。
- Shapelet 变换 + 通用分类器:如前所述,先做特征变换,再训练线性模型或集成模型。该方法往往能取得更高的准确率,且可以利用成熟机器学习库。
优点与局限
优点
- 可解释性强:Shapelet 本身是一个可绘制的子序列,直接展示出类间差异的关键形态,适合医学、金融等需要解释性的领域。
- 局部特征聚焦:能忽略无关的全局噪声,对时间序列的平移、局部缩放(需配合归一化)有一定鲁棒性。
- 无需精确对齐:子序列滑动匹配机制天然处理时间轴上的偏移。
- 高精度:在许多基准数据集上,Shapelet 方法的分类准确率可与深度学习模型媲美,而模型复杂度更低。
局限
- 计算复杂度高:Shapelet 搜索过程仍然耗时,尽管有大量加速算法,在处理超长序列或海量数据时仍面临挑战。
- 长度选择敏感:Shapelet 的最优长度需要预先设定范围或通过交叉验证选择,不合适的长度会降低判别力。
- 可扩展性有限:多变量时间序列和极大规模的发现仍是研究热点,传统 Shapelet 主要针对单变量。
代码示例:使用 Python 学习 Shapelet
以下示例使用 sktime 中的 ShapeletTransformClassifier,它结合了 Shapelet 变换与随机森林分类器。
from sktime.classification.shapelet_based import ShapeletTransformClassifier
from sktime.datasets import load_gunpoint
from sklearn.metrics import accuracy_score
# 加载示例数据(枪支动作分类)
X_train, y_train = load_gunpoint(split="train")
X_test, y_test = load_gunpoint(split="test")
# 初始化分类器:搜索200个Shapelet,每个序列使用的最优Shapelet数量为150
stc = ShapeletTransformClassifier(
n_shapelet_samples=200,
max_shapelets=150,
estimator=None # 默认使用随机森林
)
# 训练
stc.fit(X_train, y_train)
# 预测并评估
y_pred = stc.predict(X_test)
print(f"准确率: {accuracy_score(y_test, y_pred):.2f}")
# 查看某个Shapelet
if hasattr(stc, 'shapelets_'):
best_shapelet = stc.shapelets_[0] # 第一个Shapelet
print(f"最优Shapelet长度: {len(best_shapelet)}")
拓展学习与方向
- 学习 Shapelet(Learning Shapelet):不同于从数据中搜索,通过学习方式直接优化 Shapelet 的形状和决策阈值,如 Grabocka 等人提出的 LTS 算法。
- 多变量 Shapelet:将判别性子序列的概念扩展到多维时间序列,联合考虑多通道上的局部形态。
- 深度 Shapelet:使用神经网络自动提取潜在的 Shapelet 表示,兼具端到端学习的优势。
- 在线与流式 Shapelet:用于实时数据流的增量学习和分类,保持 Shapelet 集合的持续更新。
Shapelet 作为时间序列分类的里程碑式方法,在保留物理可解释性的同时实现了高性能,是进入时序数据挖掘领域的必修知识。