データ分析の前処理などで行う標準化と正規化の違いや, Pythonで標準化する際のいくつかの方法について調べたのでメモります。
標準化と正規化
正規化 (normalization) または最大最小スケーリング (min-max scaling) は [0,1] となるように下記のような変換をする。min/maxに強く影響される。
一方で, 標準化 (standardization)は N(0, 1) となるように下記のような変換する。外れ値に対して正規化よりロバスト。
数式は Standardization vs. normalization [1] から引用。
機械学習の様々なアルゴリズムは良いパフォーマンスを実現するためにスケーリングが必要となるが, 正規化も標準化もスケーリングの一種として考えて良さそう。
注意点として訓練データのみならず, 評価データや予測時のデータに対しても同じスケーリングパラメータを適用して変換する必要がある。
(過去に訓練データと評価データで別々に標準化し失敗してしまったことがあった…)
Pythonでデータの標準化
標準化自体が簡単に実装できるとは思うが, ライブラリを使う方法も幾つかある。
- NumPy
- SciPy
- scikit-learn
環境はOSX 10.11.5, Python 2.7.9。
NumPy
NumPyの mean と std を使う方法。
In [1]: import numpy as np
In [2]: x = [1,2,3,4,5,6,7,8,9]
In [3]: x_copy = np.copy(x)
In [4]: x_std = (x_copy - x_copy.mean()) / x_copy.std()
In [5]: x_std
Out[5]:
array([-1.54919334, -1.161895 , -0.77459667, -0.38729833, 0. ,
0.38729833, 0.77459667, 1.161895 , 1.54919334])
In [6]: np.mean(x_std)
Out[6]: 0.0
In [7]: np.std(x_std)
Out[7]: 1.0
mean, std を使った方法は Pandas でもできる。[2]
SciPy
scipy.stats.zscore を使う方法。axisに None, 0, 1 を指定でき下記のような違いがある。
- axis=None: 行列全体で標準化
- axis=0: 列方向で標準化
- axis=1: 行方向で標準化
また, ddof で std 計算時の自由度 (df) を調整できる。 例えば, ddof=1 の時に n-1 で計算。Defaultは0。
In [8]: import scipy.stats as sp
In [9]: x_std = sp.stats.zscore(x, axis=0)
In [10]: x_std
Out[10]:
array([-1.54919334, -1.161895 , -0.77459667, -0.38729833, 0. ,
0.38729833, 0.77459667, 1.161895 , 1.54919334])
In [11]: np.mean(x_std)
Out[11]: 0.0
In [12]: np.std(x_std)
Out[12]: 1.0
In [13]: x_matrix = np.array([[1,2,3],[4,5,6],[7,8,9]])
In [14]: x_matrix
Out[14]:
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
In [15]: x_std = sp.stats.zscore(x_matrix, axis=0)
In [16]: x_std
Out[16]:
array([[-1.22474487, -1.22474487, -1.22474487],
[ 0. , 0. , 0. ],
[ 1.22474487, 1.22474487, 1.22474487]])
In [17]: x_std = sp.stats.zscore(x_matrix, axis=None)
In [18]: x_std
Out[18]:
array([[-1.54919334, -1.161895 , -0.77459667],
[-0.38729833, 0. , 0.38729833],
[ 0.77459667, 1.161895 , 1.54919334]])
In [19]: x_std = sp.stats.zscore(x_matrix, axis=1)
In [20]: x_std
Out[20]:
array([[-1.22474487, 0. , 1.22474487],
[-1.22474487, 0. , 1.22474487],
[-1.22474487, 0. , 1.22474487]])
In [21]: x_std = sp.stats.zscore(x_matrix, axis=1, ddof=1)
In [22]: x_std
Out[22]:
array([[-1., 0., 1.],
[-1., 0., 1.],
[-1., 0., 1.]])
scikit-learn
sklearn.preprocessing を使う方法。StandardScaler は標準化, MinMaxScaler は正規化。
fit でスケーリングパラメータを保持しておき, transform で標準化された値を返すのでアプリケーションへの実装に適している。
In [27]: from sklearn.preprocessing import StandardScaler
In [28]: x = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
In [29]: ss = StandardScaler()
In [30]: ss.fit(x)
Out[30]: StandardScaler(copy=True, with_mean=True, with_std=True)
In [31]: x_std = ss.transform(x)
In [32]: x_std
Out[32]:
array([-1.54919334, -1.161895 , -0.77459667, -0.38729833, 0. ,
0.38729833, 0.77459667, 1.161895 , 1.54919334])
In [33]: x_std = ss.transform([4.5])
In [34]: x_std
Out[34]: array([-0.19364917])
In [35]: from sklearn.preprocessing import MinMaxScaler
In [36]: mms = MinMaxScaler()
In [37]: x_norm = mms.fit_transform(x)
In [38]: x_norm
Out[38]: array([ 0. , 0.125, 0.25 , 0.375, 0.5 , 0.625, 0.75 , 0.875, 1. ])
今回, 参考にさせて頂いた本は『Python機械学習プログラミング 達人データサイエンティストによる理論と実践』です。
[1] Standardization vs. normalization
[2] Essential Basic Functionality