機械学習の前処理とは

AIは生のデータから学習すると思っていたけれども、実施はデータの前処理が必要になるケースが多々あるようです。

Should I standardize the input variables (column vectors)?

上のサイトによると、機械学習への寄与が入力の大きさに影響するようなので、使用する機械学習のアルゴリズムごとに、入力を適切にスケーリング (標準化) することが必要らしいです。 (理解が間違っていなければ、、、)

Scikit learnによる前処理

PythonのライブラリのScikit learnでは、この前処理を一括で行う関数が用意されています。下記のサイトにも、具体例が載っていますが、具体例で使用されている3x3行列では、いまいちイメージが沸かなかったので、どのような前処理が行われているのか、試してみました。

http://scikit-learn.org/stable/modules/preprocessing.html

処理の対象とする行列の作成

10x3行列を使って、Scikit learnの前処理でどのような処理が行われるのか確認します。

test.py
import numpy as np
from sklearn import preprocessing

a = [i**2 - 420 for i in range(30)]
a = np.array(a)
a = a.reshape(10,3)
print(a)
print(a.max(axis=0)) # 各列の最大値 [309 364 421]
print(a.min(axis=0)) # 各列の最小値 [-420 -419 -416]
print(a.mean(axis=0)) # 各列の平均 [-163.5 -135.5 -105.5]
print(a.var(axis=0)) # 各列の分散 [58405.05 66721.05 75631.05]

"""
行列 a:
[[-420 -419 -416]
 [-411 -404 -395]
 [-384 -371 -356]
 [-339 -320 -299]
 [-276 -251 -224]
 [-195 -164 -131]
 [ -96  -59  -20]
 [  21   64  109]
 [ 156  205  256]
 [ 309  364  421]]
"""

Scale関数による前処理

各列は、平均 0 、分散 1に標準化されます。

test2.py
a_scaled = preprocessing.scale(a)

print(a_scaled.max(axis=0)) # [1.95513438 1.93376661 1.91446888]
print(a_scaled.min(axis=0)) # [-1.06135866 -1.09754321 -1.12904575]
print(a_scaled.mean(axis=0)) # [ 2.22044605e-17 -8.88178420e-17  6.66133815e-17]
print(a_scaled.var(axis=0)) # [1. 1. 1.]

MinMaxScaler関数による前処理

各列は、最大値 1 、最小値 0 に標準化されます。

test3.py
min_max_scaler = preprocessing.MinMaxScaler()
a_minmax = min_max_scaler.fit_transform(a)

print(a_minmax.max(axis=0)) # [1. 1. 1.]
print(a_minmax.min(axis=0)) # [0. 0. 0.]
print(a_minmax.mean(axis=0)) # [0.35185185 0.36206897 0.37096774]
print(a_minmax.var(axis=0)) # [0.10989941 0.10882767 0.1079566 ]

MaxAbsScaler関数による前処理

各列は、最大、最小の絶対値が 1 に標準化されます。
各列の要素がすべて正の値の場合は、MaxMinScaler関数と同じ結果を返すようです。

test4.py
max_abs_scaler = preprocessing.MaxAbsScaler()
a_maxabs = max_abs_scaler.fit_transform(a)

print(a_maxabs.max(axis=0)) # [0.73571429 0.86873508 1.        ]
print(a_maxabs.min(axis=0)) # [-1.         -1.         -0.98812352]
print(a_maxabs.mean(axis=0)) # [-0.38928571 -0.32338902 -0.25059382]
print(a_maxabs.var(axis=0)) # [0.33109439 0.38004483 0.42671306]

Pandasに対して前処理を行いたい

上記のScikit-learnの前処理は、前処理結果がndarrayに変換されてしまいます。
このため、元DataがPandasである場合、前処理結果がPandasでなくなってしまうことが面倒です。
その面倒を回避するには、下記のライブラリを使用すると良さそうです。作ってくれた人、ありがとうございます。

StatsFragments Python, R, Rust, 統計, 機械学習とか
Github sinhrks/pandas-ml

どの前処理を用いるか?

前回行った試行によると、LSTMで予測を行う場合は、平均値0のデータの場合が予測精度が高かった。その場合、Scale関数を使って前処理を行うと良いかもしれない (未検証)。

LSTMの予測精度に対するサンプルデータ絶対値の影響

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.