多次元のモデル:機械学習

%matplotlib inline
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv('./input/wine.csv')
df.head(2)

モデルには11の変数あり。

# グラフにプロットしてみよう

# 高評価ワインのデータのみ取得
df1 = df[df['評価'] == 1]
# 低評価ワインのデータのみ取得
df0 = df[df['評価'] == 0]

plt.scatter(df1["酢酸"], df1["クエン酸"], color='red')
plt.scatter(df0["酢酸"], df0["クエン酸"], color='blue');
# 説明変数Xと目的変数yの取得
X = df.iloc[:, :-1]  # 最後の列以外の全列
y = df.iloc[:, -1]  # 最後の列

df.ilocの解説

元になるデータセットから特徴行列(説明変数)Xと目的変数yを取り出します。以降のクエストでは、特徴行列のことを説明変数ということもあります。

X = df.iloc[:, :-1]
y = df.iloc[:, -1]

今までpandasのDataFrameで列の値を抽出するにはdf[[“アルコール度数”, “密度”]]のようにカラムの名前を指定します。
ですが11種類ある名前を列挙するのは面倒です。

df.ilocからアクセスすれば、行と列の数字(インデックス番号)からDataFrameを取り出せます。

df.iloc

ここで大括弧内は [取り出す行, 取り出す列] を指定します。
[:, :-1]は「行の全て、列は始めから最後1つ前まで」という意味になります。

リストや文字列においても[:]は「全て取り出す」という意味になりますし、[:-1]は「始めから最後1つ前まで」という意味になります。

データの分割 train_test_split 解説

from sklearn.model_selection import train_test_split
# データをトレーニング用、評価(テスト)用に分割
(X_train, X_test,
 y_train, y_test) = train_test_split(
    X, y, test_size=0.3, random_state=0,
)

データセットから取り出したX、yをさらに、「トレーニング用」と「テスト用」にデータ分割します。

データセットの全てを使って学習(トレーニング)して、同じデータでテストをしては意味がありません。テストの答えを元に分類器が学習してしまうので、不用意にスコアが高くなってしまいます。

それを避けるために、ここでtrain_test_split関数を使ってデータ分割をしています。
train_test_split関数はデータをランダムに、好きの割合で分割できる便利な関数です。

X_train: トレーニング用の特徴行列(「アルコール度数」「密度」「クエン酸」などのデータ)
X_test: テスト用の特徴行列
y_train: トレーニング用の目的変数(「美味しいワイン」か「そうでもないワインか」)
y_test: テスト用の目的変数
train_test_splitには以下のような引数を与えます。

第1引数: 特徴行列 X
第2引数: 目的変数 y
test_size=: テスト用のデータを何割の大きさにするか
test_size=0.3で、3割をテスト用のデータとして置いておけます
random_state=: データを分割する際の乱数のシード値
同じ結果が返るように0を指定していますが、これは勉強用であり普段は指定しません

ロジスティック回帰による分類と精度を計算

from sklearn.linear_model import LogisticRegression
lr = LogisticRegression(C=1000, solver='liblinear')
lr.fit(X_train, y_train)
LogisticRegression(C=1000, class_weight=None, dual=False, fit_intercept=True,
                   intercept_scaling=1, l1_ratio=None, max_iter=100,
                   multi_class='auto', n_jobs=None, penalty='l2',
                   random_state=None, solver='liblinear', tol=0.0001, verbose=0,
                   warm_start=False)
lr.score(X_test, y_test)
0.8222222222222222

scikit-learnのおかげで、たったの数行で機械学習ができています。

今回は全てのデータを学習には使わず、トレーニング用とテスト用に分割しています。
学習させたあとにスコアの測定もしています。

X_train, X_test, y_train, y_test = train_test_split(X, y)
lr = LogisticRegression(...)
lr.fit(X_train, y_train)
lr.score(X_test, y_test)

※ solver='liblinear'で、liblinearというソルバーを指定しています。C=1000については後述します。

  1. データをトレーニング用、テスト用に分割
  2. 分類器を初期化
  3. トレーニングデータで学習
    • lr.fit(...): 特徴行列と目的変数で学習
  4. テストデータでスコア測定
    • lr.score(...): データを元にスコアを01で返す

lr.scoreは結果が正しいかを正解の割合で返します。内部的にはlr.predict(X_test)を実行し、y_testと比較することでスコアを算出してくれています。
今回はスコアが0.8程度になりました。これはテストデータの8割のワインで美味しいか美味しくないかを正しく分類できたということになります。

この処理の流れ(データ分割、トレーニング、スコア測定)は機械学習でよく実施します。

特に、scikit-learnの分類器は全て同じ基本的なメソッド.fit()や.predict()、.score()を持っています。
今後学ぶ他の分類器を使うときにも同じような流れでスコアを測定できます。形として身に染み込ませておくと良いでしょう。

ハイパーパラメーターC

ハイパーパラメーターCがモデルの過学習を防ぐ逆正則化パラメーターになります。
細かい内容は後のクエストで深く学びますので、今は「そういうものか」と思っておいてください。

今回、トレーニング用のデータとテスト用にデータ分割して学習・評価をしました。
このとき「トレーニング用のデータに過度に最適化してしまうこと」を過学習といいます。その過学習を防ぐためのパラメーターがCで、大きければ大きいほど過学習に陥りやすくなります。大きすぎると過学習に陥る可能性がありますし、小さすぎると学習にならないという問題があります。

今回もC=1000が最適な値かどうかは分かりません。
学習モデルのハイパーパラメーターは最適な値を設定する必要があります。
また、学習モデルによってハイパーパラメーターの種類や量は異なります。

コメント

タイトルとURLをコピーしました