さまざまなスケール変換
Overview
データセットに対するさまざまなスケール変換と前処理結果
https://gyazo.com/ff5294bcf5f29bb83098216251396fc9
上図は2特徴量の2クラス分類合成データセットです。その隣の4つのプロットは、scikit-learnを使ってそのデータを標準的なレンジに変換する4つの方法を示しています。下記はそれぞれのスケール変換の特徴です。
StandardScaler: 個々の特徴量の平均が0で分散が1になるように変換します。しかし、この方法は特徴量の最大値や最小値がある範囲に入ることは保証しません。
RobustScaler: 個々の特徴量の中央値と四位分数を用いて、一定の範囲に入るように変換します。このため、極端に他の値と異なるような値(外れ値)を無視します。
MinMaxScaler: データがちょうど0から1の間に入るように変換します。
Normalizer: 個々のデータポイントを、特徴量ベクトルがユークリッド長1になるように変換します。この変換は、特徴ベクトルの長さだけでなく、方向(もしくが角度)だけが問題になる場合に用いられます。
Coding
cancerデータセットの前処理にMinMaxScalerを用いてスケール変換前後のデータポイントを確認する
code: Python
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
cancer = load_breast_cancer()
X_train, X_test, y_train, y_test = train_test_split(cancer.data, cancer.target, random_state=1)
print('Shape of X_train: {}'.format(X_train.shape))
print('Shape of X_test: {}'.format(X_test.shape))
# スケール変換器のfitメソッドにはデータ(X_train)のみを与える
# 訓練データ中の各特徴量の最小値と最大値を計算する
scaler = MinMaxScaler()
scaler.fit(X_train)
# 実際に訓練データをスケール変換する
X_train_scaled = scaler.transform(X_train)
# 下のようにも書ける
# scaler.fit(X_train).transform(X_train)
# scaler.fit_transform(X_train)
print()
# スケール変換の前後のデータ特性をプリントする
print('transformed shape: {}'.format(X_train_scaled.shape))
print('pre-feature minimum before scaling:\n {}'.format(X_train.min(axis=0)))
print('pre-feature maximum before scaling:\n {}'.format(X_train.max(axis=0)))
print('pre-feature minimum after scaling:\n {}'.format(X_train_scaled.min(axis=0)))
print('pre-feature maximum after scaling:\n {}'.format(X_train_scaled.max(axis=0)))
--------------------------------------------------------------------------
Shape of X_train: (426, 30)
Shape of X_test: (143, 30)
MinMaxScaler(copy=True, feature_range=(0, 1))
transformed shape: (426, 30)
pre-feature minimum before scaling:
[6.981e+00 9.710e+00 4.379e+01 1.435e+02 5.263e-02 1.938e-02 0.000e+00
0.000e+00 1.060e-01 5.024e-02 1.153e-01 3.602e-01 7.570e-01 6.802e+00
1.713e-03 2.252e-03 0.000e+00 0.000e+00 9.539e-03 8.948e-04 7.930e+00
1.202e+01 5.041e+01 1.852e+02 7.117e-02 2.729e-02 0.000e+00 0.000e+00
1.566e-01 5.521e-02]
pre-feature maximum before scaling:
[2.811e+01 3.928e+01 1.885e+02 2.501e+03 1.634e-01 2.867e-01 4.268e-01
2.012e-01 3.040e-01 9.575e-02 2.873e+00 4.885e+00 2.198e+01 5.422e+02
3.113e-02 1.354e-01 3.960e-01 5.279e-02 6.146e-02 2.984e-02 3.604e+01
4.954e+01 2.512e+02 4.254e+03 2.226e-01 9.379e-01 1.170e+00 2.910e-01
5.774e-01 1.486e-01]
pre-feature minimum after scaling:
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0.]
pre-feature maximum after scaling:
[1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.
1. 1. 1. 1. 1. 1.]
--------------------------------------------------------------------------
このように、MinMaxScalerはデータがちょうど0から1の間に入るように変換します。また、同様にテストセットの方も変換する必要があります。
code: Python
X_test_scaled = scaler.transform(X_test)
print('pre-feature minimum after scaling:\n {}'.format(X_test_scaled.min(axis=0)))
print('pre-feature maximum after scaling:\n {}'.format(X_test_scaled.max(axis=0)))
--------------------------------------------------------------------------
pre-feature minimum after scaling:
[ 0.0336031 0.0226581 0.03144219 0.01141039 0.14128374 0.04406704
0. 0. 0.1540404 -0.00615249 -0.00137796 0.00594501
0.00430665 0.00079567 0.03919502 0.0112206 0. 0.
-0.03191387 0.00664013 0.02660975 0.05810235 0.02031974 0.00943767
0.1094235 0.02637792 0. 0. -0.00023764 -0.00182032]
pre-feature maximum after scaling:
[0.9578778 0.81501522 0.95577362 0.89353128 0.81132075 1.21958701
0.87956888 0.9333996 0.93232323 1.0371347 0.42669616 0.49765736
0.44117231 0.28371044 0.48703131 0.73863671 0.76717172 0.62928585
1.33685792 0.39057253 0.89612238 0.79317697 0.84859804 0.74488793
0.9154725 1.13188961 1.07008547 0.92371134 1.20532319 1.63068851]
--------------------------------------------------------------------------
テストセットの場合には、スケール変換後の最小値と最大値が0と1の間になっていません。これは、訓練セットの場合と全く同じ計算をしているからですが、これで問題ありません。
cancerデータセットに前処理をしSVCモデルを構築・学習・スケール変換前後の精度を確認する
前処理をしない場合
code: Python
from sklearn.svm import SVC
X_train, X_test, y_train, y_test = train_test_split(cancer.data, cancer.target, random_state=0)
svm = SVC(C=100).fit(X_train, y_train)
print('Test set accuracy: {:.2f}'.format(svm.score(X_test, y_test)))
--------------------------------------------------------------------------
Test set accuracy: 0.63
--------------------------------------------------------------------------
MinMaxScalerで前処理する場合
code: Python
from sklearn.svm import SVC
X_train, X_test, y_train, y_test = train_test_split(cancer.data, cancer.target, random_state=0)
# 0-1 スケール変換で前処理
scaler = MinMaxScaler().fit(X_train)
X_train_scaled = scaler.transform(X_train)
X_test_scaled = scaler.transform(X_test)
# 変換された訓練データで学習
svm.fit(X_train_scaled, y_train)
# 変換されたテストセットでスコア計算
print('Scaled test set accuracy: {:.2f}'.format(svm.score(X_test_scaled, y_test)))
--------------------------------------------------------------------------
Scaled test set accuracy: 0.97
--------------------------------------------------------------------------
StandardScalerで前処理する場合
code: Python
from sklearn.svm import SVC
X_train, X_test, y_train, y_test = train_test_split(cancer.data, cancer.target, random_state=0)
# 個々の特徴量の平均が0で分散が1になるように変換
scaler = StandardScaler().fit(X_train)
X_train_scaled = scaler.transform(X_train)
X_test_scaled = scaler.transform(X_test)
# 変換された訓練データで学習
svm.fit(X_train_scaled, y_train)
# 変換されたテストセットでスコア計算
print('Scaled test set accuracy: {:.2f}'.format(svm.score(X_test_scaled, y_test)))
--------------------------------------------------------------------------
Scaled test set accuracy: 0.96
--------------------------------------------------------------------------