機械学習モデルにデータを入力するとき、前処理としてデータを標準化(Standardization)や正規化(Normalization)をすることで、モデルの精度を向上させることができます。
また近年流行りの深層学習においては、データを0~1の範囲に変換してからモデルに入力することで、モデルの精度を上げることができることから、正規化や標準化のスケーリングは非常に重要な操作になってきます。
標準化は、データの平均が0、分散(標準偏差)が1となるように、データ列をそのデータ列の平均で引いた後に、標準偏差で割る変換をします。一方、正規化では、データ列が全て0~1の範囲に収まるように(最小値が0、最大値が1)、データ列を変換する処理のことを指します。
一方で、標準化と正規化ってどっちがどっちだっけと思うことも何度かあったので、今回は機械学習で毎回のように行うことになる、標準化と正規化について、その違いがわかるようにまとめていきます。
また、Pythonでこれらの処理を行うときは、標準化や正規化の関数を実装することはあまりなく、通常はscikit-learnのsklearn.preprocessingモジュールを利用すると便利です。
この記事では、Pythonを用いて標準化と正規化を行う方法として、sklearn.preprocessingのStandardScalerとMinMaxScalerとついてまとめていきます。また、標準化や正規化したデータを元のスケールに戻す方法についてもまとめます。
- 標準化と正規化の定義と操作
- Pythonで標準化をStandardScalerで行う方法
- Pythonで正規化をMinMaxScalerで行う方法
標準化と正規化
まず最初に、標準化と正規化のやり方について提示します。
標準化は、データ列を、データ列の平均で引いた後に、標準偏差で割る操作のことを言います。式で提示すると次のようになります。
データの平均を$\bar{x}$、標準偏差を$\sigma$とすると、データを次のように変換することを標準化という。
\frac{x - \bar{x} }{ \sigma }
続いて、正規化の定義と処理内容は次のようになっています。
データ列における最小値を$x_{min}$、最大値を$x_{max}$とするとき、正規化では次のような変換(スケーリング)を行う。
x' = \frac{x - x_{min}}{x_{max} - x_{min}}
式で見ても、中々ピンときませんが、標準化はデータの平均が0になるような変換、正規化はデータが0~1の間に収まるような変換、というふうに覚えておくと良いでしょう。
続いて、Pythonを用いてこれらの標準化と正規化を行う方法について解説します。
StandardScalerで標準化する
Pythonで標準化を行う場合には、scikit-learnのStandardScalerを用います。
今回は、時系列データセットAirPassengersのデータを用いて、データの標準化を行います。
今回用意するデータセットは次のようなコードで準備できます。
import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler
df = pd.read_csv("https://raw.githubusercontent.com/jbrownlee/Datasets/master/airline-passengers.csv", index_col='Month', parse_dates=True)
values = df.values.flatten()
values
# array([112, 118, 132, 129, 121, 135, 148, 148, 136, 119, 104, 118, 115,
126, 141, 135, 125, 149, 170, 170, 158, 133, 114, 140, 145, 150,
178, 163, 172, 178, 199, 199, 184, 162, 146, 166, 171, 180, 193,
181, 183, 218, 230, 242, 209, 191, 172, 194, 196, 196, 236, 235,
229, 243, 264, 272, 237, 211, 180, 201, 204, 188, 235, 227, 234,
264, 302, 293, 259, 229, 203, 229, 242, 233, 267, 269, 270, 315,
364, 347, 312, 274, 237, 278, 284, 277, 317, 313, 318, 374, 413,
405, 355, 306, 271, 306, 315, 301, 356, 348, 355, 422, 465, 467,
404, 347, 305, 336, 340, 318, 362, 348, 363, 435, 491, 505, 404,
359, 310, 337, 360, 342, 406, 396, 420, 472, 548, 559, 463, 407,
362, 405, 417, 391, 419, 461, 472, 535, 622, 606, 508, 461, 390,
432])
続いて、標準化を行なっていきます。
コードは次のようになります。
scikit-learnのStandardScalerは、引数にnp.array形式でデータを与える必要性があるため、1行目でreshapeを行っています。
x = np.array(values, dtype="float64").reshape([-1, 1])
scaler = StandardScaler()
scaled_x = scaler.fit_transform(x)
標準化した配列がscaled_xで得ることができました。
標準化したデータを元のスケールに戻す
標準化を行ったデータを元のスケールに戻したいときは、次のようにinverser_transform関数を実行します。
original_x = scaler.inverse_transform(scaled_x)
original_x
一度作った、StandardScalerのオブジェクトのinversr_transformを利用することで、元のスケールに戻すことができます。
MinMaxScalerで正規化する
Pythonで正規化するには、scikit-learnの前処理モジュールsklearn.preprocessingに含まれている、MinMaxScalerを利用します。
方法は標準化とほとんど同じです。データとして、標準化と同様に、AirPassengersのデータを用いて、正規化を行います。
from sklearn.preprocessing import MinMaxScaler
x = np.array(values, dtype="float64").reshape([-1, 1])
scaler = MinMaxScaler(feature_range=(0, 1))
scaled_x = scaler.fit_transform(x)
scaled_x
正規化したデータセットを元のスケールに戻す
標準化の場合と同じように、元のスケールに戻す場合は、次のようにinverse_transform()関数を実行します。
original_x = scaler.inverse_transform(scaled_x)
original_x
無事スケールを元に戻すことができました。
scikit-learnのMinMaxScalerクラスは、正規化の場合だけでなく、初期化時のfeature_rangeオプション引数に、とりうる値の範囲を渡すことで、任意のスケーリングができます。とても便利ですね。