Pynote

Python、機械学習、画像処理について

scikit-learn - 特徴量のスケーリング

概要

scikit-learn を使った特徴量のスケーリング方法について


前提

サンプル数を m、特徴量の次元数を n としたとき、データセットm \times n の2次元配列で表される。
以下で紹介するスケーリングは、特徴量の特徴ごと、つまり列ごとに行う。


StandardScaler

StandardScaler は各特徴の平均を0、分散を1となるように変換する。この変換を標準化という。
データセット\boldsymbol{x}_1, \boldsymbol{x}_2, \cdots, \boldsymbol{x}_m \in \mathbb{R}^n としたとき、

\displaystyle
x'_{ij} = \frac{x_{ij} - \mu_j}{\sigma_j}

ただし、\mu_j = \frac{1}{N} \sum_{i=0}^m x_{ij}, \sigma^2 = \frac{1}{N} \sum_{i=0}^m (x_{ij} - \mu_j)^2

コード

  • fit(X): 標準化に必要な情報を計算する。
  • fit_transform(X): fit() 後に変換を同時に行う。
  • transform(X[, y, copy]): 変換する。
from sklearn.preprocessing import StandardScaler

# データセットを作成する。(サンプル数, 特徴量の次元数) の2次元配列で表される。
X = np.array([[4, 1, 2, 2],
              [1, 3, 9, 3],
              [5, 7, 5, 1]],
             dtype=float)

# 変換器を作成する。
transformer = StandardScaler()

# 変換する。
X_scaled = transformer.fit_transform(X)

# 結果を出力する。
print(X_scaled)

for f in X_scaled.T:
    print('feature: {}, mean: {:.2f}, std: {:.2f}'.format(f, f.mean(), f.std()))
[[ 0.39223227 -1.06904497 -1.16247639  0.        ]
 [-1.37281295 -0.26726124  1.27872403  1.22474487]
 [ 0.98058068  1.33630621 -0.11624764 -1.22474487]]
feature: [ 0.39223227 -1.37281295  0.98058068], mean: -0.00, std: 1.00
feature: [-1.06904497 -0.26726124  1.33630621], mean: 0.00, std: 1.00
feature: [-1.16247639  1.27872403 -0.11624764], mean: 0.00, std: 1.00
feature: [ 0.          1.22474487 -1.22474487], mean: 0.00, std: 1.00

特徴ごとに平均が0、分散が1となっていることがわかる。

MinMaxScaler

MinMaxScaler は各特徴の値の範囲が [0, 1] となるようにスケーリングする。
データセット\boldsymbol{x}_1, \boldsymbol{x}_2, \cdots, \boldsymbol{x}_m \in \mathbb{R}^n としたとき、

\displaystyle
x'_{ij} = \frac{x_{ij} - \min_j x_{ij}}{\max_j x_{ij} - \min_j x_{ij}}

コード

from sklearn.preprocessing import MinMaxScaler

# (サンプル数, 特徴量の次元数) の2次元配列で表されるデータセットを作成する。
X = np.array([[4, 1, 2, 2],
              [1, 3, 9, 3],
              [5, 7, 5, 1]],
             dtype=float)

# 変換器を作成する。
transformer = MinMaxScaler()

# 変換する。
X_scaled = transformer.fit_transform(X)

# 結果を出力する。
print(X_scaled)

for f in X_scaled.T:
    print('feature: {}, min: {:.2f}, max: {:.2f}'.format(f, f.min(), f.max()))
[[0.75       0.         0.         0.5       ]
 [0.         0.33333333 1.         1.        ]
 [1.         1.         0.42857143 0.        ]]
feature: [0.75 0.   1.  ], min: 0.00, max: 1.00
feature: [0.         0.33333333 1.        ], min: 0.00, max: 1.00
feature: [0.         1.         0.42857143], min: 0.00, max: 1.00
feature: [0.5 1.  0. ], min: 0.00, max: 1.00

特徴ごとに最小値が0、最大値が1となっていることがわかる。

MaxAbsScaler

MaxAbsScaler は各特徴の最大値が1となるようにスケーリングする。
データセット\boldsymbol{x}_1, \boldsymbol{x}_2, \cdots, \boldsymbol{x}_m \in \mathbb{R}^n としたとき、

\displaystyle
x'_{ij} = \frac{x_{ij}}{|\max_j x_{ij}|}

コード

from sklearn.preprocessing import MaxAbsScaler

# (サンプル数, 特徴量の次元数) の2次元配列で表されるデータセットを作成する。
X = np.array([[4, 1, 2, 2],
              [1, 3, 9, 3],
              [5, 7, 5, 1]],
             dtype=float)

# 変換器を作成する。
transformer = MaxAbsScaler()

# 変換する。
X_scaled = transformer.fit_transform(X)

# 結果を出力する。
print(X_scaled)

for f in X_scaled.T:
    print('feature: {}, max: {:.2f}'.format(f, f.max()))
[[0.8        0.14285714 0.22222222 0.66666667]
 [0.2        0.42857143 1.         1.        ]
 [1.         1.         0.55555556 0.33333333]]
feature: [0.8 0.2 1. ], max: 1.00
feature: [0.14285714 0.42857143 1.        ], max: 1.00
feature: [0.22222222 1.         0.55555556], max: 1.00
feature: [0.66666667 1.         0.33333333], max: 1.00

特徴ごとに最大値が1となっていることがわかる。

RobustScaler

RobustScaler は各特徴の第1分位点 Q_1 と第3分位点 Q_3 の範囲 Q_1, Q_3 が1になるようにスケーリングにする。
データセット\boldsymbol{x}_1, \boldsymbol{x}_2, \cdots, \boldsymbol{x}_m \in \mathbb{R}^n としたとき、

\displaystyle
x'_{ij} = \frac{x_{ij} - Q_1(x_{ij})}{Q_3(x_{ij}) - Q_1(x_{ij})}

となるように変換する。

コード

from sklearn.preprocessing import RobustScaler

# (サンプル数, 特徴量の次元数) の2次元配列で表されるデータセットを作成する。
X = np.array([[4, 1, 2, 2],
              [1, 3, 9, 3],
              [5, 7, 5, 1]],
             dtype=float)

# 変換器を作成する。
transformer = RobustScaler()

# 変換する。
X_scaled = transformer.fit_transform(X)

# 結果を出力する。
print(X_scaled)
[[ 0.         -0.66666667 -0.85714286  0.        ]
 [-1.5         0.          1.14285714  1.        ]
 [ 0.5         1.33333333  0.         -1.        ]]

Normalizer

Normalizer は各サンプルの特徴量のノルムが1になるように変換する。
これまでのものと違い、特徴ごとでなく、サンプルごとであることに注意する。

from sklearn.preprocessing import Normalizer

X = np.array([[4, 1, 2, 2],
              [1, 3, 9, 3],
              [5, 7, 5, 1]], dtype=float)
transformer = Normalizer()
X_normalized = transformer.transform(X)
print(X_normalized)

for feat in X_normalized:
    norm = np.linalg.norm(feat, ord=2)
    print('feature: {}, norm: {}'.format(feat, norm))
[[0.8 0.2 0.4 0.4]
 [0.1 0.3 0.9 0.3]
 [0.5 0.7 0.5 0.1]]
feature: [0.8 0.2 0.4 0.4], norm: 1.0
feature: [0.1 0.3 0.9 0.3], norm: 1.0
feature: [0.5 0.7 0.5 0.1], norm: 1.0

サンプルごとにノルムが1となっていることがわかる。