使用tslearn实现DTW分类遇错及多维分类等技术问询
使用tslearn实现DTW分类时的问题
我在用tslearn库做Dynamic Time Warping(DTW)分类时,训练阶段报错ValueError: setting an array element with a sequence.。我的数据是多组长度可变、维度多样的时间序列,先导入成DataFrame列表用于可视化,筛选列转成numpy数组,划分训练测试集后用DTW作为距离度量训练模型,试过展平数组、重塑为(-1,1)、修改dtype为float都没用。
代码片段:
from tslearn.neighbors import KNeighborsTimeSeriesClassifier from tslearn.metrics import dtw import pandas as pd import numpy as np from sklearn.model_selection import cross_val_score from sklearn.model_selection import KFold from sklearn.pipeline import Pipeline from sklearn.model_selection import train_test_split # timeseries()返回多个不同长度的DataFrame print(timeseries()) # 输出示例:两个不同行数的DataFrame,各包含10列 ts = timeseries() # 只保留TC列 [i.drop(columns=['time','IRtime','value','value.1','value.2','value.3','IR','TS','p'],inplace = True) for i in ts] X = [] for i in ts: i = i.values X.append(i.flatten()) y = labels()['target'].values X = np.array(X) y = np.array(y) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # 初始化模型并训练 knn = KNeighborsTimeSeriesClassifier(n_neighbors=2,metric =dtw) knn.fit(X_train, y_train) # 报错: # TypeError: only size-1 arrays can be converted to Python scalars # ValueError: setting an array element with a sequence.
问题
Q1. 如何修复该错误?
Q2. 有没有其他可计算距离矩阵并完成分类的库?(试过dtai库计算距离矩阵,但不知如何用于分类,且遇到同样的错误)
Q3. 我想基于IR、TC、TS多特征实现多维DTW分类,有哪些可行方法?
解答
Q1:修复错误的方法
核心问题是tslearn的KNeighborsTimeSeriesClassifier要求输入格式为三维结构:每个样本是(时间步长, 特征数)的二维数组,整体以列表形式传入(支持变长序列),而你当前的X_train是一维数组的集合,不符合要求。
修复步骤:
- 保留时间序列的二维结构,不要展平:
ts = timeseries() # 处理数据时保留二维结构,不要用inplace修改原列表 ts_processed = [i.drop(columns=['time','IRtime','value','value.1','value.2','value.3','IR','TS','p']) for i in ts] # 转成(时间步长, 1)的二维数组,组成列表 X = [df.values.reshape(-1, 1) for df in ts_processed] y = labels()['target'].values X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) - 使用tslearn内置的DTW度量标识:
不需要直接传入dtw函数,用字符串'dtw'即可,避免函数调用格式不匹配:knn = KNeighborsTimeSeriesClassifier(n_neighbors=2, metric='dtw') knn.fit(X_train, y_train)
tslearn原生支持变长时间序列,只要每个样本是符合维度要求的二维数组,列表形式传入即可。
Q2:其他可用于DTW分类的库
- scikit-learn + 预计算距离矩阵:
用sklearn的KNeighborsClassifier结合预计算的DTW距离矩阵,适合自定义距离逻辑:from sklearn.neighbors import KNeighborsClassifier from tslearn.metrics import dtw # 预计算训练集的距离矩阵 def build_dtw_matrix(X): n_samples = len(X) dist_matrix = np.zeros((n_samples, n_samples)) for i in range(n_samples): for j in range(i+1, n_samples): dist = dtw(X[i], X[j]) dist_matrix[i,j] = dist dist_matrix[j,i] = dist return dist_matrix # 训练阶段 train_dist = build_dtw_matrix(X_train) knn = KNeighborsClassifier(n_neighbors=2, metric='precomputed') knn.fit(train_dist, y_train) # 测试阶段:计算测试样本到训练样本的距离 test_dist = np.array([[dtw(x_test, x_train) for x_train in X_train] for x_test in X_test]) y_pred = knn.predict(test_dist) - fastdtw:比原生DTW更快的实现,适合大数据量,用法和上述逻辑一致,替换
dtw函数为fastdtw即可。 - pyDTW:轻量级DTW库,专注于距离计算,同样可配合sklearn分类器使用。
Q3:多维DTW分类的可行方法
多维DTW用于处理多特征时间序列,有以下几种实用方案:
- tslearn原生多维支持:
tslearn的DTW和分类器原生支持多维时间序列,只要每个样本是(时间步长, 特征数)的二维数组即可。比如保留IR、TC、TS三列:
tslearn会自动对每个特征维度计算DTW距离后求和,也可通过ts_processed = [i[['IR', 'TC', 'TS']] for i in ts] X = [df.values for df in ts_processed] # 每个样本是(时间步长, 3)的二维数组 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) knn = KNeighborsTimeSeriesClassifier(n_neighbors=2, metric='dtw') knn.fit(X_train, y_train)metric_params设置权重。 - 加权多维DTW:
如果不同特征重要性不同,可自定义加权距离函数:def weighted_mdtw(x, y, weights=[0.3, 0.5, 0.2]): # x、y为(时间步长, 3)的数组 total_dist = 0 for idx in range(3): total_dist += weights[idx] * dtw(x[:, idx].reshape(-1,1), y[:, idx].reshape(-1,1)) return total_dist knn = KNeighborsTimeSeriesClassifier(n_neighbors=2, metric=weighted_mdtw) knn.fit(X_train, y_train) - 特征对齐后做DTW:
先对多特征时间序列做时序对齐(比如用插值统一长度),再用多维DTW,但会丢失原始时序的变长特性,仅适合对长度一致性有要求的场景。
内容的提问来源于stack exchange,提问作者memonj12
相关产品推荐
相关产品推荐

