时间序列分类任务---tsfresh库
如何对多条时间序列进行分类,分析哪些是正常,哪些是异常等问题。
思路:首先,分析时间序列,提取可用的特征,一般指序列的统计特征(最小值,最大值,方差,平均值,变化频率等);然后,利用特征数据进行分类任务。在特征提取中tsfresh库帮助实现时间序列特征自动提取。
一、tsfresh介绍
tsfresh 用于从时间序列和其他顺序数据中进行系统化特征工程。这些数据的共同点是由一个独立变量排序。最常见的独立变量是时间(时间序列)。其他顺序数据的例子包括反射和吸收光谱,它们以波长作为排序维度。
您想要计算不同的特征,例如最高或最低温度、平均温度或暂时温度峰值的数量。
如果没有 tsfresh,您将必须手动计算所有这些特征;tsfresh 可以自动计算并返回所有这些特征。
1.1、我们可以利用这些功能做什么?
提取的特征可用于描述时间序列,也就是说,这些特征通常能为时间序列及其动态提供新的见解。它们还可用于聚类时间序列并训练对时间序列执行分类或回归任务的机器学习模型。
tsfresh 包已成功用于以下项目:
(1)连铸过程中钢坯质量的预测
(2)通过同步传感器进行活动识别
(3)火山爆发预报
(4)根据书面文本样本进行作者归属鉴定
(5)根据缺失数据的时间序列描述太阳系外行星系统的特征
(6)传感器异常检测
…
1.2、我们不能用 tsfresh 做什么?
目前,tsfresh 不适合:
(1)流数据(流数据通常用于在线操作,而时间序列数据通常用于离线操作)
(2)在提取的特征上训练模型
(3)用于高度不规则的时间序列
二、案例
2.1、加载数据
pip install tsfresh
pip install tsfresh[dask] #如果需要处理可能无法放入内存的大型时间序列数据,请使用 Dask安装 tsfresh
%matplotlib inline
import matplotlib.pylab as plt
from tsfresh import extract_features, extract_relevant_features, select_features #extract_features 用于从时间序列数据中提取特征。extract_relevant_features 用于提取与目标变量相关的特征。select_features 用于选择特征。
from tsfresh.utilities.dataframe_functions import impute #用于处理缺失值。
from tsfresh.feature_extraction import ComprehensiveFCParameters #提供了特征提取的参数配置。
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from tsfresh.examples import robot_execution_failures #提供一个示例数据集。
robot_execution_failures.download_robot_execution_failures() #下载与机器人执行失败相关的示例数据。
df, y = robot_execution_failures.load_robot_execution_failures()
df.head()
案例使用机器人执行失败数据,展示如何使用 tsfresh 从多个时间序列中提取有用的特征并使用它们来提高分类性能。不同的传感器有六个不同的时间序列( F_x、F_y、F_z、T_x、T_y、T_z )。不同的机器人由 id 列表示。
df[df.id == 3][['time', 'F_x', 'F_y', 'F_z', 'T_x', 'T_y', 'T_z']].plot(x='time', title='Success example (id 3)', figsize=(12, 6));
df[df.id == 20][['time', 'F_x', 'F_y', 'F_z', 'T_x', 'T_y', 'T_z']].plot(x='time', title='Failure example (id 20)', figsize=(12, 6));
2.2、提取特征
X包含每个机器人执行的单行,其中所有特征 tsfresh 都是根据该 id 的测量时间序列值计算。
extraction_settings = ComprehensiveFCParameters() #提供了特征提取的参数配置。
X = extract_features(df, column_id='id', column_sort='time',
default_fc_parameters=extraction_settings, #提取特征
impute_function=impute)
X
2.3、特征选择
使用 tsfresh 实现假设检验,从这个大型数据集中仅选择相关特征。 tsfresh 将对每个功能进行假设检验,以检查它是否与您给定的目标相关。为了不泄漏训练集和测试集之间的信息,我们将仅在训练集上执行选择。
X_full_train, X_full_test, y_train, y_test = train_test_split(X, y, test_size=.4, random_state=42)
X_filtered_train = select_features(X_full_train, y_train)
X_filtered_train.head()
2.4、模型训练和评估
X_filtered_train, X_filtered_test = X_full_train[X_filtered_train.columns], X_full_test[X_filtered_train.columns]
classifier_full = DecisionTreeClassifier()
classifier_full.fit(X_full_train, y_train)
print(classification_report(y_test, classifier_full.predict(X_full_test)))
与使用所有特征(classifier full)相比,仅使用相关特征(classifier filtered)可以用更少的数据实现相似或更好的分类性能。
classifier_filtered = DecisionTreeClassifier()
classifier_filtered.fit(X_filtered_train, y_train)
print(classification_report(y_test, classifier_filtered.predict(X_filtered_test)))
提取相关特征
extract_relevant_features(df, y, column_id='id', column_sort='time',
default_fc_parameters=extraction_settings)
三、sklearn Pipeline
3.1、sklearn Pipeline 选择特征
import pandas as pd
from sklearn.pipeline import Pipeline
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report
from tsfresh.examples import load_robot_execution_failures
from tsfresh.transformers import RelevantFeatureAugmenter #是一个变换器类,用于增强特征。在时间序列分析中,它通过提取与目标变量相关的特征来扩展原始数据集。 这个类通常用于在模型训练前自动选择对目标变量有显著影响的特征,从而帮助提高模型的性能。
from tsfresh.utilities.dataframe_functions import impute
加载数据
from tsfresh.examples.robot_execution_failures import download_robot_execution_failures
download_robot_execution_failures()
df_ts, y = load_robot_execution_failures()
X = pd.DataFrame(index=y.index)
# Split data into train and test set
X_train, X_test, y_train, y_test = train_test_split(X, y)
构建pipeline
ppl = Pipeline([
('augmenter', RelevantFeatureAugmenter(column_id='id', column_sort='time')),
('classifier', RandomForestClassifier())
])
ppl.set_params(augmenter__timeseries_container=df_ts)
ppl.fit(X_train, y_train)
预测
y_pred = ppl.predict(X_test)
print(classification_report(y_test, y_pred))
查看模型选择哪些特征
ppl.named_steps["augmenter"].feature_selector.relevant_features
四、多分类任务
使用人类活动识别的示例数据集,展示如何使用 tsfresh 从多分类示例中的时间序列中提取和选择有用的特征。该数据集由 7352 个加速度计读数的时间序列组成。每个读数代表 50hz下 2.56 秒的加速度计读数(每个读数总共 128 个样本),此外,每次阅读都对应六种活动之一(行走、上楼,下楼、坐着、站立和躺下)。
4.1、加载数据及预处理
%matplotlib inline
import matplotlib.pylab as plt
from tsfresh import extract_features, extract_relevant_features, select_features
from tsfresh.utilities.dataframe_functions import impute
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
import pandas as pd
import numpy as np
from tsfresh.examples.har_dataset import download_har_dataset, load_har_dataset, load_har_classes
download_har_dataset()
df = load_har_dataset()
df.head()
y = load_har_classes()
y
df["id"] = df.index
df = df.melt(id_vars="id", var_name="time").sort_values(["id", "time"]).reset_index(drop=True)
df.head() #7352*128
数据并不是典型的时间序列格式:列是时间步长,而每行是不同人的测量。因此,我们将其采用一种格式,其中不同人的时间序列由 id 标识,并按时间垂直排序。
plt.title('accelerometer reading')
plt.plot(df[df["id"] == 0].set_index("time").value)
plt.show()
4.2、提取特征
X = extract_features(df[df["id"] < 500], column_id="id", column_sort="time", impute_function=impute)
X.head() #只取前500个分析
4.3、加载和评估模型
X_train, X_test, y_train, y_test = train_test_split(X, y[:500], test_size=.2)
classifier_full = DecisionTreeClassifier()
classifier_full.fit(X_train, y_train)
print(classification_report(y_test, classifier_full.predict(X_test)))
4.4、多特征选择
我们现在将使用 tsfresh 的特征选择方法来选择一组相关特征。然而,该方法仅适用于二分类或回归任务。
对于六类多分类问题,我们因此将特征选择问题拆分为六个二分类的“一个对所有”的分类问题。对于每个分类问题,我们可以进行二分类特征选择。
relevant_features = set()
for label in y.unique():
y_train_binary = y_train == label
X_train_filtered = select_features(X_train, y_train_binary)
print("Number of relevant features for class {}: {}/{}".format(label, X_train_filtered.shape[1], X_train.shape[1]))
relevant_features = relevant_features.union(set(X_train_filtered.columns))
len(relevant_features) #313
对于训练集和测试集,我们只保留上面选择的那些特征。通过去除不相关的特征来提高精度
X_train_filtered = X_train[list(relevant_features)]
X_test_filtered = X_test[list(relevant_features)]
classifier_selected = DecisionTreeClassifier()
classifier_selected.fit(X_train_filtered, y_train)
print(classification_report(y_test, classifier_selected.predict(X_test_filtered)))
更多细节可以参考:https://github.com/blue-yonder/tsfresh/tree/main/notebooks