Python

Pythonで機械学習を学ぶ ロジスティック回帰

重回帰は目的変数が数値変数であった。ロジスティック回帰は、目的変数がカテゴリ変数であり、classification(カテゴリに属すかどうかの確率を計算するタスク分類)を行う。目的関数(交差エントロピー誤差関数)が最小になるように学習する。正確なほど値が小さくなる。

サンプルコードでは、以下のモデルを構築します。
目的変数:品質が5.5以上か分類
説明変数:固定酸度、揮発性の酸度、クエン酸、残糖、塩化物など11の入力

以下のワインのデータセットで実験します。

ポルトガルワイン「Vinho Verde」の赤と白の変数に関するもの。プライバシーとロジスティックの問題のため、物理化学的変数(入力)と感覚的変数(出力)のみが利用可能。

より詳しい情報は、[Cortez et al., 2009]を参照。
入力変数(物理化学的試験に基づく)は以下の通り。
1 – 固定酸度
2 – 揮発性の酸度
3 – クエン酸
4 – 残糖
5 – 塩化物
6 – 遊離二酸化硫黄
7 – 全二酸化硫黄
8 – 密度
9 – pH
10 – 硫酸塩
11 – アルコール


出力変数(感覚データに基づく)は以下の通り。
12 – 品質(0から10の間のスコア)

https://archive.ics.uci.edu/ml/datasets/Wine+Quality

データの読み込みと確認と整理

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

# 読み込み
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)

# 学習
# max_iter=10000を入れないと、STOP: TOTAL NO. of ITERATIONS REACHED LIMIT. の警告が出力される
model = LogisticRegression(max_iter=10000)
model.fit(X_train, y_train)

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

結果

train:0.756
test:0.734