<jupyter_start><jupyter_text>Ch8 特徴量の生成と選択<jupyter_code>import numpy as np
import pandas as pd

%matplotlib inline
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(font_scale = 1.5)
c_list = sns.color_palette().as_hex()
color_num = len(c_list)<jupyter_output><empty_output><jupyter_text>8.1 簡単な例 ここでは、toy sampleを使って、系列データの「特徴量」への変換例を紹介。<jupyter_code>df_temp = pd.DataFrame(
    {
        "week":[
            "Mon", "Mon", "Mon", "Tue", "Tue", "Tue", 
            "Wed", "Wed", "Wed", "Thu", "Thu", "Thu", 
            "Fri", "Fri", "Fri", "Sat", "Sat", "Sat", 
            "Sun", "Sun", "Sun", 
        ], 
        "t":[
            "m", "l", "n", "m", "l", "n", 
            "m", "l", "n", "m", "l", "n", 
            "m", "l", "n", "m", "l", "n", 
            "m", "l", "n", 
        ], 
        "temp":[
            35, 52, 15, 37, 52, 15, 37, 54, 16, 39, 51, 12, 
            41, 55, 20, 43, 58, 22, 46, 61, 35
        ]
    }
)
df_temp.set_index(["week", "t"], inplace=True)
display(df_temp)
fig = plt.figure(figsize=(10, 4))
ax = fig.subplots(1, 1)
df_temp.plot(y="temp", marker="o", ax=ax);<jupyter_output><empty_output><jupyter_text>このような日次の周期と上昇トレンドを持った系列データ。このデータを要約する特徴量がいくつか考えられる。- 周期- 全体平均（定常過程）、上昇トレンドの傾き（非定常）- 朝、昼、夜の平均、トレンド  8.4 特徴量の自動生成と自動選択<jupyter_code>#!pip install tsfresh
from tsfresh.examples.robot_execution_failures import (
    download_robot_execution_failures, 
    load_robot_execution_failures
)
from tsfresh import extract_features
import tsfresh<jupyter_output><empty_output><jupyter_text>ここで扱うtoyデータをダウンロードする。<jupyter_code>download_robot_execution_failures()
timeseries, y = load_robot_execution_failures()

display(type(timeseries)) # time series data
display(type(y)) # target vector<jupyter_output><empty_output><jupyter_text>robot_execution_failuresデータの確認このデータが何なのか確認する。<jupyter_code>help(tsfresh.examples.robot_execution_failures)<jupyter_output>Help on module tsfresh.examples.robot_execution_failures in tsfresh.examples:

NAME
    tsfresh.examples.robot_execution_failures

DESCRIPTION
    This module implements functions to download the Robot Execution Failures LP1 Data Set [1]_, [2]_, [3]_ and load it as
    as DataFrame.
    
    *Important:* You need to download the data set yourself, either manually or via the function
    :func:`~tsfresh.examples.robot_execution_failures.download_robot_execution_failures`
    
    References
    ----------
    .. [1] https://archive.ics.uci.edu/ml/datasets/Robot+Execution+Failures
    .. [2] <NAME>. (2013).
        UCI Machine Learning Repository [https://archive.ics.uci.edu/ml].
        Irvine, CA: University of California, School of Information and Computer Science.
    .. [3] <NAME>., <NAME>, and <NAME> (1996).
        Integration and Learning in Supervision of Flexible Assembly Systems.
        "IEEE Transactions on Robotics and Automation", 12 (2), 202-[...]<jupyter_text>`LP1 dataset`というのは[ダウンロード元](https://archive.ics.uci.edu/ml/datasets/Robot+Execution+Failures)を確認すると、 `LP1: failures in approach to grasp position` と書かれている。> each failure instance is characterized in terms of 15 force/torque samples collected at regular time intervals starting immediately after failure detectionということなので、障害検出後のForceとTorqueの計測結果ということ。`target vector`って何？？`target vector`については、[tsfreshのDocument](https://tsfresh.readthedocs.io/en/v0.3.0/text/quick_start.htmlquick-start-label)に書かれてた。ロボットが把持を成功させたケース（y=True）と失敗したケース(y=False)でのForceとTorqueの計測結果ということ。<jupyter_code>display(timeseries.shape)
display(y.shape)
timeseries.head()
timeseries.groupby("id").count()
y.head()
y[~y]<jupyter_output><empty_output><jupyter_text>失敗事例（y=False）は67なので、成功（y=True）は21。そこそこ偏ってる。<jupyter_code>grp = timeseries.groupby("id")
# 成功事例
grp_idx = 2
df_tmp = grp.get_group(grp_idx)

display(df_tmp)

fig = plt.figure(figsize=(15, 3*3))
ax = fig.subplots(3, 2)
ax[0, 0].plot(df_tmp.time, df_tmp.F_x);
ax[0, 1].plot(df_tmp.time, df_tmp.T_x);
ax[1, 0].plot(df_tmp.time, df_tmp.F_y);
ax[1, 1].plot(df_tmp.time, df_tmp.T_y);
ax[2, 0].plot(df_tmp.time, df_tmp.F_z);
ax[2, 1].plot(df_tmp.time, df_tmp.T_z);
# 失敗事例
grp_idx = 20
df_tmp = grp.get_group(grp_idx)

display(df_tmp)

fig = plt.figure(figsize=(15, 3*3))
ax = fig.subplots(3, 2)
ax[0, 0].plot(df_tmp.time, df_tmp.F_x);
ax[0, 1].plot(df_tmp.time, df_tmp.T_x);
ax[1, 0].plot(df_tmp.time, df_tmp.F_y);
ax[1, 1].plot(df_tmp.time, df_tmp.T_y);
ax[2, 0].plot(df_tmp.time, df_tmp.F_z);
ax[2, 1].plot(df_tmp.time, df_tmp.T_z);<jupyter_output><empty_output><jupyter_text>特徴量の自動生成(tsfresh.extract_feature)<jupyter_code>extracted_features = extract_features(
    timeseries, column_id="id", column_sort="time"
)
display(type(extracted_features))
display(extracted_features.columns)
display(extracted_features.shape)<jupyter_output><empty_output><jupyter_text>特徴量の自動選択(FRESHアルゴリズム)<jupyter_code>from tsfresh import select_features
from tsfresh.utilities.dataframe_functions import impute<jupyter_output><empty_output><jupyter_text>`impute`: 列毎に`NaN`と`Inf`を以下の値に置き換える。- `-inf` -> `min`- `+inf` -> `max`- `NaN` -> `median`documentは[こちら](https://tsfresh.readthedocs.io/en/latest/api/tsfresh.utilities.htmltsfresh.utilities.dataframe_functions.impute)<jupyter_code>impute(extracted_features)
features_filtered = select_features(extracted_features, y)

display(type(features_filtered))
display(features_filtered.columns)
display(features_filtered.shape)<jupyter_output>/opt/conda/lib/python3.9/site-packages/tsfresh/utilities/dataframe_functions.py:171: RuntimeWarning: The columns ['F_x__partial_autocorrelation__lag_7'
 'F_x__partial_autocorrelation__lag_8'
 'F_x__partial_autocorrelation__lag_9' ...
 'T_z__matrix_profile__feature_"median"__threshold_0.98'
 'T_z__matrix_profile__feature_"25"__threshold_0.98'
 'T_z__matrix_profile__feature_"75"__threshold_0.98'] did not have any finite values. Filling with zeros.
  warnings.warn("The columns {} did not have any finite values. Filling with zeros.".format(<jupyter_text>4,722の特徴量が676個にまで削減された。 なお、ここの内容まで[tsfreshのチュートリアル](https://tsfresh.readthedocs.io/en/v0.3.0/text/quick_start.htmlquick-start-label)。  特徴量の自動選択(sklearn.feature_selection.RFE)特徴量選択アルゴリズムにRFEを利用した場合の、FRESHアルゴリズムとの比較をする。RFEでが特徴量の重要順が計算できるので、FRESHアルゴリズムで選択されたものと削除されたものをRFEで順位付けしてみたらどうなるのか傾向を確認する。 RFEの紹介はしてるのに、実装についての情報が何もない。うんこうんこ。[sklearnのドキュメント](https://scikit-learn.org/stable/modules/generated/sklearn.feature_selection.RFE.html)にほぼほぼ同じ例が載ってる。インターフェースが固定されてるから同じような実装になるのは仕方がないが、書籍よりも公式のドキュメントを探した方が情報が多いってのはどういうことなんだ？？<jupyter_code>import random<jupyter_output><empty_output><jupyter_text>FRESHアルゴリズムで選択した特徴量と削除した特徴量の中からランダムに10個抽出。これらの特徴量の順位を計算してみる。<jupyter_code>x_idx = random.sample(range(len(features_filtered.columns)), 10)
selX = features_filtered.iloc[:, x_idx].values
unselected_features = list(
    set(extracted_features.columns).difference(set(features_filtered.columns))
)
unselected_features = random.sample(unselected_features, 10)
unsel_x_idx = [
    idx for idx, val in enumerate(extracted_features.columns) if val in unselected_features
]
unselX = extracted_features.iloc[:, unsel_x_idx].values
mixed_X = np.hstack([selX, unselX])
display(x_idx)
display(unsel_x_idx)
display(type(mixed_X))
mixed_X.shape
from sklearn.feature_selection import RFE
from sklearn.svm import SVC<jupyter_output><empty_output><jupyter_text>SVC(Support Vector Classifire)を推定器として特徴量の重要度を計算。<jupyter_code>svc = SVC(kernel="linear", C=1)
rfe = RFE(estimator=svc, n_features_to_select=1, step=1)
rfe.fit(mixed_X, y)
rfe.ranking_
feature_names = []
for i, r in enumerate(rfe.ranking_):
    if i < 10:
        idx = x_idx[i]
        name = features_filtered.columns[idx]
    else:
        idx = unsel_x_idx[i - 10]
        name = extracted_features.columns[idx]
    feature_names.append(name)
df_mixed_feature_rank =  pd.DataFrame(
    {
        "feature_ranking":rfe.ranking_, 
        "feature_name":feature_names, 
        "is_FRESH_selected":list(np.repeat(True, 10)) + list(np.repeat(False, 10)), 
    }
)
df_mixed_feature_rank.sort_values("feature_ranking")<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.13715212779233746, 'fraction_numerical': 0.021589916385872956, 'mean_word_length': 5.896729776247849, 'pattern_counts': {'":': 6, '<': 56, '<?xml version=': 0, '>': 59, 'https://': 7, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '13', 'dir': 'jupyter-structured-clean-dedup', 'id': '344082', 'license': 'MIT', 'n_tokens_mistral': 3730, 'n_tokens_neox': 3494, 'n_words': 466, 'path': 'notebooks/Ch08/ch8_feature_for_timeseriese.ipynb', 'repo_name': 'tok41/note_oreilly_time_seriese_analysis', 'size': '8043'}