3
3

特徴量を標準化しないとどうなるか分かりやすくしてみた

Last updated at Posted at 2024-06-10

よく機械学習を使う前に特徴量を標準化ないし正規化をして単位を統一しろと言われると思います。
それについて実際に単位を統一しないとどうなるか、今回は機械学習ではなくユークリッド距離(多次元の三平方の定理だと思っていただければ)を用いた1近傍法を使って説明してみようと思います。

標準化をしない場合

from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
import pandas as pd
import numpy as np

df = pd.read_csv("wine.csv")
y = df["Wine"].values
x = df.drop("Wine", axis=1).values

x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=1)

y_pred = []
for i in range(len(x_test)):
    tmp = []
    for j in range(len(x_train)):
        tmp.append(np.linalg.norm(x_train[j]-x_test[i]))
    y_pred.append(y_train[np.argmin(tmp)])
print(classification_report(y_test, y_pred))
              precision    recall  f1-score   support

           1       0.95      0.91      0.93        22
           2       0.80      0.80      0.80        20
           3       0.54      0.58      0.56        12

    accuracy                           0.80        54
   macro avg       0.76      0.76      0.76        54
weighted avg       0.80      0.80      0.80        54

となります。Wineデータにしては非常に精度が悪い事が分かります。

標準化した場合

from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
import pandas as pd
import numpy as np

df = pd.read_csv("wine.csv")
y = df["Wine"].values
x = df.drop("Wine", axis=1)

# 標準化
for col in x.columns:
    x[col] = (x[col] - x[col].mean()) / x[col].std()
x = x.values

x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=1)

y_pred = []
for i in range(len(x_test)):
    tmp = []
    for j in range(len(x_train)):
        tmp.append(np.linalg.norm(x_train[j]-x_test[i]))
    y_pred.append(y_train[np.argmin(tmp)])
print(classification_report(y_test, y_pred))
              precision    recall  f1-score   support

           1       0.96      1.00      0.98        22
           2       1.00      0.80      0.89        20
           3       0.80      1.00      0.89        12

    accuracy                           0.93        54
   macro avg       0.92      0.93      0.92        54
weighted avg       0.94      0.93      0.93        54

精度が13%上がりました。
コードを見れば分かりますが最初に言いました通り機械学習ではなくユークリッド距離によるルールベースの予測です。

なぜこうなったか

ちょっとデータを実際に見てみましょう

標準化していない

そのままのデータを出します。

df = pd.read_csv("wine.csv")
df.head()
x = df.drop("Wine", axis=1)
x.head()

image.png

x.describe()

image.png

変数によって数値がバラバラです

標準化をする

標準化は平均値を0として標準偏差を1にします。

for col in x.columns:
    x[col] = (x[col] - x[col].mean()) / x[col].std()
x.head()

image.png

x.describe()

image.png

多少四分位と最大最小値に違いはありますがそれでも数値が似ています。

結論

単位が違うと当然変数の取り得る値も異なる訳で、そうなると大きな値に影響されやすくなります。なので、今回だと単位を揃えなかったらProlineに大きく影響を受けてしまう事が考えられます。
しかし単位を標準化して揃える事でどの変数も平等に扱うことができます。

まとめ

単位はちゃんと揃えましょう。
でないと大きな数値に影響されやすくなります。
ただし決定木系アルゴリズムでは揃えなくても大丈夫です。

標準化

Norm(x_i) = \frac{x_i - mean(x_i)}{std(x_i)}

正規化

Scale(x_i) = \frac{x_i - min(x_i)}{max(x_i) - min(x_i)}
3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3