Pythonで特徴量を作る際に気を付けておくこと:rollingについて
rollingを使って特徴量を作る際に気を付けておくことを書いておきます。
正直に申しますとかなりアホな間違えをしてしまったので、戒めのために備忘録として残しておきます。
・rollingの扱い
基本的なrollingの扱いは以下の通り
import pandas as pd s = pd.Series(range(10)) ######################### 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 #########################
df = pd.DataFrame({ 'num' : s, 'rolling': s.rolling(3).sum() })
index | num | rolling |
0 | 0 | NaN |
1 | 1 | NaN |
2 | 2 | 3.0 |
3 | 3 | 6.0 |
4 | 4 | 9.0 |
5 | 5 | 12.0 |
6 | 6 | 15.0 |
7 | 7 | 18.0 |
8 | 8 | 21.0 |
9 | 9 | 24.0 |
rolling(window=3)の場合は
index[0]+[1]+[2] = 3
index[1]+[2]+[3] = 6
index[2]+[3]+[4] = 9
index[3]+[4]+[5] = 12
index[4]+[5]+[6] = 15
index[5]+[6]+[7] = 18
index[6]+[7]+[8] = 21
index[7]+[8]+[9] = 24
3の場合は2つズレたうえで3つずつを足し算する動きを取る。
但し、min_periodsという引数を入れるとその値の個数のデータが含まれていれば結果が算出される。
さて本題ですが
私はテストデータと訓練データをくっつける際に使用上出てこない数字(python初学者が競馬予測をしてみたをもとにすると[result, 3ftime, rank3, rank4などの指数])
これに関しては欠損値が出てしまうので999の値を入れていたのですが、実際に入れてみるとこんな感じ
s['10'] = 999 ######################### 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 999 #########################
これをrollingすると(結果はわかるかもしれませんが。。。)
index | num | rolling |
0 | 0 | NaN |
1 | 1 | NaN |
2 | 2 | 3.0 |
3 | 3 | 6.0 |
4 | 4 | 9.0 |
5 | 5 | 12.0 |
6 | 6 | 15.0 |
7 | 7 | 18.0 |
8 | 8 | 21.0 |
9 | 9 | 24.0 |
10 | 999 | 1016.0 |
そうです。index10の所が異常値になって返ってきます。
解決策として
df = pd.DataFrame({ 'num' : s, 'rolling': s.rolling(3).sum().shift(1) })
index | num | rolling |
0 | 0 | NaN |
1 | 1 | NaN |
2 | 2 | NaN |
3 | 3 | 3.0 |
4 | 4 | 6.0 |
5 | 5 | 9.0 |
6 | 6 | 12.0 |
7 | 7 | 15.0 |
8 | 8 | 18.0 |
9 | 9 | 21.0 |
10 | 999 | 24.0 |
案の一つかもしれませんがこんな感じでかけたりします。
shiftを使う際はmin_periodsという引数を入れた方がいいのかもしれません。
df = pd.DataFrame({ 'num' : s, 'rolling': s.rolling(3, min_periods=2).sum().shift(1) })
index | num | rolling |
0 | 0 | NaN |
1 | 1 | NaN |
2 | 2 | 1.0 |
3 | 3 | 3.0 |
4 | 4 | 6.0 |
5 | 5 | 9.0 |
6 | 6 | 12.0 |
7 | 7 | 15.0 |
8 | 8 | 18.0 |
9 | 9 | 21.0 |
10 | 999 | 24.0 |
いい感じに加工できたと思います。
明らかに間違いをした場合は機械学習した際に予測値がおかしくなり正常に予想ができなくなります。
そうなった場合は前処理の部分を中心に探してみるのもいいかもしれません。
ではまた。