機械学習でなぜ正規化が必要なのか

## 初めに

機会学習をする際には学習モデルを構築する前に前処理としてデータを正規化する必要がある
ということを聞いたことありますでしょうか？
機械学習の勉強を始めたばかりですが、機械学習はデータの前処理が命ともいうので
なぜ必要なのか、どのようにすればいいのかを調べてまとめてみたいと思います。

## 1.正規化？標準化？

正規化について調べていると「標準化」という言葉も出てきました。
まず「正規化」と「標準化」の違いについてみていきたいと思います。
※調べた結果、サイトによって少し異なる説明になっていることがありました。(ライブラリやフレームワークによって定義が異なる？)
　この記事では正規化、標準化はこういう定義で進めていきます！って意味でまとめてます。

* 正規化とは  
データに対して何らかの計算を行い、全てのデータが0～1の間の大きさにすること  
例えば、全てのデータを「100で割る」、「2乗する」という操作によって値を0から1の間にすることが正規化と言えるわけです。
* 標準化とは  
データに対して平均値が0、標準偏差が1になるように計算すること
理由は数学の世界になるので省きますが、全ての値から平均値を引いて標準偏差で割れば平均値=0、標準偏差=1になります。
これをZスコアというそうです。

「正規化」と「標準化」のどちらを使えばいいのかについてはなぜ正規化や標準化が必要なのかを考えてから考察したいと思います。

## なぜ正規化や標準化が必要なのか

本題です。特徴量によって異なるデータスケールを統一するためって説明しかないことも多いのですが、
自分はこれだけでは全然理解できなかったのでもう少し掘り下げます。

機械学習やディープラーニングの勉強をしていると下記のニューラルネットワークの図を見たことがあると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162114/bc9ed15e-2159-2aa9-9f01-b3c36f246b3c.png)
Wは入力値に掛ける重みを表しています。
この図では入力される特徴量は2つでその特徴量に重みを掛けて計算して3つの中間層を作成しています。
例えば、入力される特徴量が「年齢」と「身長」で、これらの特徴量から何かを学習しようとしているとします。
5人分の年齢・身長のセットを持っているとしてこれらに重みを掛けて計算していきます。
ここでも説明とは無関係なので中間層は単純に入力に重みを掛けたものを足し合わせて作成するとします。
年齢 =｛"10", "15", "20", "25", "30"｝
身長 = {"130", "165", "170", "173", "170"}

* W1とW2が1の場合(年齢と身長の重要度は同じ)  
10 × 1 + 130 × 1 = 140  
15 × 1 + 165 × 1 = 180  
20 × 1 + 170 × 1 = 190  
25 × 1 + 173 × 1 = 198  
30 × 1 + 170 × 1 = 200
* W1=1、W2=2の場合(年齢よりも身長を重要視する)  
10 × 1 + 130 × 2 = 270  
15 × 1 + 165 × 2 = 345  
20 × 1 + 170 × 2 = 360  
25 × 1 + 173 × 2 = 371  
30 × 1 + 170 × 1 = 370
* W1=2、W2=1の場合(身長よりも年齢を重要視する)  
10 × 2 + 130 × 1 = 150  
15 × 2 + 165 × 1 = 195  
20 × 2 + 170 × 1 = 210  
25 × 2 + 173 × 1 = 223  
30 × 2 + 170 × 1 = 230

この結果を見てどうでしょうか？
身長を重要視した結果と年齢を重要視した結果を比べると身長を重要視した結果のほうが数値が大きくなっています。
年齢を重要視した結果は値が大きくはなっていますが、年齢と身長を同じ重要度にした結果とそんなに変わらないです。

つまり、手持ちのデータをそのまま使用して計算してしまうと重みに関係なく身長のほうが計算結果に与える影響が大きい(=重要視されている)という結果になっているわけです。
推測したい結果が身長に大きく依存するものであればうまく学習できるのかもしれませんが、
年齢に大きく依存するものならば結果が身長に引きずられてうまく学習できない可能性があります。
これは身長の取りえる値が大体0～100としても身長が盗りえる値は50～200くらいあり、最大値、最小値が異なることが原因です。
なので、年齢と身長を同じレベルで扱うために正規化や標準化が必要なのです。

### 正規化や標準化の計算をしても悪影響は出ない？

ここまで学習して気になったのが元のデータから変換したことによって学習結果に悪影響はないのか？ということです。
これについては問題ないようで、機械学習の入力は"特徴量"と呼ばれるようにデータの値そのものではなく、
特徴をとらえて学習するものだそうです。なので正規化・標準化後もデータの特徴が変わっていなければ問題なしということです。

上記の年齢・身長を正規化、標準化するとそれぞれ下記のようになります。

* 正規化(年齢は100、身長は200で各データを割って算出)  
年齢 = {0.1, 0.15, 0.2, 0.25, 0.3}  
身長 = {0.65, 0.825, 0.85, 0.865, 0.85}
* 標準化  
年齢 = {-1.264911064, -0.632455532, 0, 0.632455532, 1.264911064}  
身長 = {-1.76566624, 0.189976747, 0.469354317, 0.636980859, 0.469354317}  

正規化・標準化することで年齢と身長の大きさの差が縮まって平等に扱えるようになりました。

計算前の年齢、身長をブラフにするとこのようになります。

* 元データ  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162114/3dccffa8-8aba-c845-db7d-7d7a0a821a0c.png)
* 正規化  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162114/97b586ce-b154-1958-7adc-a863cbffa2ca.png)
* 標準化  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162114/9221a600-20f9-2c7e-ab2e-0261882234e0.png)

正規化や標準化したブラフを見るとどちらもグラフの"形"は元データの形からほとんど変わっていないことが分かります。
(標準化のグラフは少し形が変わっていますが、値の変化の特徴がよりはっきり分かるようになったと考えます。)
グラフの形が変わらないということはデータの持つ特徴は失われていないということなので正規化や標準化をしても問題なく学習できる
ということです。

## 正規化と標準化のどっちを使うべき？

明確な回答はなく、ケースバイケースになりますが、標準化を使用することのほうが多いようです。
理由は正規化は異常値による影響を受けやすいからだそうです。
今回の例では身長は最大値を200として200で正規化しましたが、異常値として1000という値が紛れ込んだらどうなるでしょうか？
その異常値のために他の値すべてを1000で割ることになるので値が極端に小さくなり、特徴がうまく現れなくなります。
しかし、画像処理ではピクセルのRGB値(0~255)が特徴量となりますが、これは1000などの異常値をとることはないのでこのような最小値と最大値が明確に決まっている場合は計算が簡単な正規化を用いるようです。

なので、基本的には標準化を行うが、値の範囲が明確ならば正規化を行う。
というような使い分けになるのかなと思います。

## 参考にさせていただいたサイト様

最後に今回学習するにあたって参考にさせていただいたサイト様を紹介します。
大変参考になりました。ありがとうございます。

* [正規化 標準化(機械学習)の理由,必要性,メリットと元に戻す(逆変換)方法をPythonで解説【ディープラーニング,ニューラルネットワーク】](https://nine-num-98.blogspot.com/2019/12/ai-normalization.html) 
* [Feature Scalingはなぜ必要?](https://qiita.com/ttskng/items/2a33c1ca925e4501e609)
* [【Python】数量データの正規化 ( 標準化 ) について](https://www.st-hakky-blog.com/entry/2017/12/11/200046)