概要
時系列データを処理する機会があり、便利そうなものを発見したので、使い方のメモ。
以下の公式を参照。
tsfresh
tsfresh is a python package. It automatically calculates a large number of time series characteristics, the so called features. Further the package contains methods to evaluate the explaining power and importance of such characteristics for regression or classification tasks.
使い方
以下はJupyter Notebook上で実行しています。
ライブラリのインポート
!pip install tsfresh
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
時系列データの作成
適当なダミーデータを作成。
timeline = np.arange(10000)
data = np.sin(timeline/100) + np.cos((timeline/100) * 3) + (np.random.rand(len(timeline)))*0.2
plt.plot(timeline[:1000], data[:1000])
plt.xlabel('time')
plt.ylabel('data')
plt.show()
feature_extractionで特徴量を計算
feature_calculatorsという関数があるので、これを使うと様々な特徴量を計算できる。
feature_extraction
import tsfresh.feature_extraction.feature_calculators as feature_calculators
range_data = data[:600]
mean_abs_change = feature_calculators.mean_abs_change(data)
# 前後のポイント間での差分の平均値
# np.mean(np.abs(np.diff(x))) と等しい
first_location_of_maximum = feature_calculators.first_location_of_maximum(data)
# 最大値が観測される位置
fft_aggregated = feature_calculators.fft_aggregated(data, [{'aggtype': 'skew'}])
# フーリエ変換
number_peaks = feature_calculators.number_peaks(data[:1000], 50)
# ピークの数
index_mass_quantile = feature_calculators.index_mass_quantile(data[:1000], [{'q': 0.5},{'q': 0.1}])
# パーセンタイル処理
linear_trend = feature_calculators.linear_trend(range_data, [{'attr': "slope"},{'attr': 'intercept'},{'attr': 'rvalue'}])
# 単純なトレンド分析。attrに関しては下記を参照
# https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.linregress.html
autocorrelation = feature_calculators.autocorrelation(data, 100)
# 自己相関の計算
この中のlinear_trendを使って、時系列データのトレンドを計算してみる。
trend = linear_trend[0][1] * timeline + linear_trend[1][1]
plt.plot(timeline[:600], data[:600])
plt.plot(timeline[:600], trend[:600])
plt.xlabel('time')
plt.ylabel('data')
plt.show()
当たり前だが、正しく計算できていそう。
まとめて特徴量を計算
個別にではなくて、とりあえずたくさん特徴量を計算したい場合は、extract_featuresを使えばよさそう。
from tsfresh import extract_features
# こちらはDataFrameではないといけないようなので変換する。
# 1つのデータフレーム内に複数の時系列データがある形を想定しているらしく、どのデータが時系列としてひとまとまりなのか識別するカラムが必要(column_idで指定)
# 今回は1種類しか入っていないので、すべて1にした
temp = pd.DataFrame(data, columns=['value'], dtype='float')
temp['id'] = 1
temp.head()
extracted_features = extract_features(temp, column_id='id')
display(extracted_features.columns)
Index(['value__abs_energy', 'value__absolute_sum_of_changes',
'value__agg_autocorrelation__f_agg_"mean"__maxlag_40',
'value__agg_autocorrelation__f_agg_"median"__maxlag_40',
'value__agg_autocorrelation__f_agg_"var"__maxlag_40',
'value__agg_linear_trend__f_agg_"max"__chunk_len_10__attr_"intercept"',
'value__agg_linear_trend__f_agg_"max"__chunk_len_10__attr_"rvalue"',
'value__agg_linear_trend__f_agg_"max"__chunk_len_10__attr_"slope"',
'value__agg_linear_trend__f_agg_"max"__chunk_len_10__attr_"stderr"',
'value__agg_linear_trend__f_agg_"max"__chunk_len_50__attr_"intercept"',
...
'value__symmetry_looking__r_0.9',
'value__symmetry_looking__r_0.9500000000000001',
'value__time_reversal_asymmetry_statistic__lag_1',
'value__time_reversal_asymmetry_statistic__lag_2',
'value__time_reversal_asymmetry_statistic__lag_3',
'value__value_count__value_-1', 'value__value_count__value_0',
'value__value_count__value_1', 'value__variance',
'value__variance_larger_than_standard_deviation'],
dtype='object', name='variable', length=794)
これだけで794個も特徴量が計算できたらしい。
まとめ
numpy1行で終わるようなものも多いが、まとめて特徴量計算したいときには便利かもしれない。特にextract_features。
時間を見つけてもう少し使ってみたい。