Python

Pythonで機械学習を学ぶ スケーリングで予測精度を向上させる

説明変数の標準化を実施し、変数間の単位、大きさの異なりを消し、数値の大小と意味するところを合致させる。

以前に紹介したロジスティック回帰に、StandardScaler() を使い、標準化してみます。

サンプルコード

import pandas as pd
import requests
import io
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

# 読み込み
url = 'https://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv'
res = requests.get(url).content

data = pd.read_csv(io.StringIO(res.decode('utf-8')), header=None, skiprows=1, delimiter=";")

data.columns =['fixedacidity','volatileacidity','citricacid','residualsugar','chlorides','freesulfurdioxide','totalsulfurdioxide','density','pH','sulphates','alcohol','quality']

import pandas as pd
import requests
import io
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

# 読み込み
url = 'https://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv'
res = requests.get(url).content

data = pd.read_csv(io.StringIO(res.decode('utf-8')),
                   header=None, skiprows=1, delimiter=";")

data.columns = ['fixedacidity', 'volatileacidity', 'citricacid', 'residualsugar', 'chlorides',
                'freesulfurdioxide', 'totalsulfurdioxide', 'density', 'pH', 'sulphates', 'alcohol', 'quality']

# 確認
print('データ形式:{}'.format(data.shape))
print(data.head())
# print(data.dtypes)

# flg カラムを追加、qualityが5.5以上なら1、そうでないなら0をセット
data['flg'] = data['quality'].map(lambda x: 1 if x >= 5.5 else 0)
print(data.groupby('flg').size())


# 目的変数、説明変数
X = data[['fixedacidity', 'volatileacidity', 'citricacid', 'residualsugar', 'chlorides',
          'freesulfurdioxide', 'totalsulfurdioxide', 'density', 'pH', 'sulphates', 'alcohol']]
y = data['flg']

# 訓練データとテストデータに分ける
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.5, random_state=0)

# 標準化
sc = StandardScaler()
sc.fit(X_train)
X_train_std = sc.transform(X_train)
X_test_std = sc.transform(X_test)

# 学習
model = LogisticRegression(max_iter=10000)
model.fit(X_train_std, y_train)

# 結果
print('train:{:.3f}'.format(model.score(X_train_std, y_train)))
print('test:{:.3f}'.format(model.score(X_test_std, y_test)))

結果

# 適用前
train:0.756
test:0.734

# 適用後
train:0.758
test:0.738

わずかですが精度が向上したようです。もともとの説明変数間の単位、大きさがそれほど大きく異ならないことが原因と考えられます。