こんにちは、Hawaiiです。
本記事は、「初心者向け|【第二回】機械学習モデルの精度比較検証」の続編です。
機械学習の勉強をする時に、

とアドバイスされる方も多いのではないでしょうか。
実際、このやり方は非常に有効です。
ただ、本当の初心者の頃、こんなことを思っていました。

・こんなに難しいやり方じゃなくて、もっとシンプルなやり方を知りたいだけなのに・・・
そう、kernelは教材ではないので、「まずは最低限の書き方を知りたい」「少しずつステップアップしたい」という要望には応えてくれません。
今回は複数回に及ぶ企画です。
【第一回】
Kaggleのtitanicを使って、複数モデル(決定木やロジスティック回帰)について最低限の基礎的なアプローチのコードを紹介
↓
【第二回】
少しレベルを上げたアプローチ(正則化を実行してみる)
↓
【第三回】←今回はココ
さらにレベルを上げたアプローチ(標準化+正則化を実行してみる)
↓
【第●回】
もう少しレベルを上げる・・と徐々にレベルを上げていき、それぞれについて精度を検証していくことにします。
今回は標準化の回で、「標準化処理が必要なモデル」がロジスティック回帰・サポートベクトルマシンだけですので、分量としては少なくなっています。
本記事の目次は以下の通りです。
①本企画の全体像
②実践
(0ー0)前処理
(0-1)標準化
(1)ロジスティック回帰
(2)サポートベクトルマシン
③まとめ
本企画を一貫して、試す手法とモデルは下記です。
※第三回の本記事では、ロジスティック回帰とサポートベクトルマシンを扱います。
■試す手法
1.最低限の、シンプルな書き方
2.(必要なモデルのみ)正則化
3.(必要なモデルのみ)標準化
4.ハイパーパラメータチューニング
5.特徴量選択
■試すモデル
・ロジスティック回帰
・サポートベクトルマシン
・決定木
・ランダムフォレスト
・アダブースト
①本企画の全体像
企画全体を通じて、アウトプットはこのようなイメージです。
5モデル×5手法の計25パターンについてコードを示しながら解説し、最後に各セルに精度を埋めていきます。
第二回では「2.正則化」までの列の実証が終了したので、現状は以下の様な表になっています。
今回は、「3.標準化」の列のロジスティック回帰・サポートベクトルマシンを実装していこうと思います。
■補足_なぜ他のモデルには標準化は不要なのか?
私もまだ精緻に理解できていないのでざっくりした説明で申し訳ないのですが、
ツリー系(決定木・ランダムフォレスト・アダブースト)のモデルは枝分かれのような分岐(Yes/No判断)で
カテゴリ分けをしていきます。
ですので、「標準化していようが」「していまいが」、ツリー系のモデルでは、判断の結果に影響を及ぼさないのです。
※本記事には載せていないですが、たしかに、標準化をした場合としていない場合で精度を比較した際、全く同じか、
ほぼ精度は変わらなかったです。
②実践
(0-0)前処理
全モデルに共通の処理を行っていきます。
まずは必要なものをインポートしていきます。
command
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
import math
#ロジスティック回帰
from sklearn.linear_model import SGDClassifier
#サポートベクターマシン
from sklearn.svm import SVC
#決定木
from sklearn.tree import DecisionTreeClassifier, export_graphviz
#ランダムフォレスト
from sklearn.ensemble import RandomForestClassifier
#アダブースト
from sklearn.ensemble import AdaBoostClassifier
#標準化のためにインポート
from sklearn.preprocessing import StandardScaler
続いて、データの読み込み→train.csvとtest.csvの結合をします。
command
#データの読み込み
df_train = pd.read_csv("train.csv")
df_test = pd.read_csv("test.csv")
#データの結合
df_train["TrainFlag"] = True
df_test["TrainFlag"] = False
df = df_train.append(df_test)
#最後の提出に必要なのでPassengerIDをdfのindexにしておき、dfからはPassengerID列を削除
df.index = df["PassengerId"]
df.drop("PassengerId", axis = 1, inplace = True)
続いて、最低限の前処理を行います。
command
#欠損値処理
df["Age"] = df["Age"].fillna(df["Age"].median())
df["Embarked"] = df["Embarked"].fillna("S")
#カテゴリ変数処理
df = pd.get_dummies(df, columns = ["Sex", "Embarked"])
#不要列の削除
df = df.drop(['Cabin','Name','Ticket', 'Fare'], axis = 1)
続いて、標準化に移っていきましょう。
(0-1)標準化
標準化は、下記のコードで実行できます。
今回は、1行ずつ愚直に実行していくやり方をお見せします。
私が超初心者だったころは、この書き方しか理解できなかったためです。。
command
stdsc = StandardScaler()
df["Age"] = stdsc.fit_transform(df[["Age"]].values)
df["Parch"] = stdsc.fit_transform(df[["Parch"]].values)
df["Pclass"] = stdsc.fit_transform(df[["Pclass"]].values)
df["Parch"] = stdsc.fit_transform(df[["Parch"]].values)
df["Sex_female"] = stdsc.fit_transform(df[["Sex_female"]].values)
df["Sex_male"] = stdsc.fit_transform(df[["Sex_male"]].values)
df["Embarked_C"] = stdsc.fit_transform(df[["Embarked_C"]].values)
df["Embarked_Q"] = stdsc.fit_transform(df[["Embarked_Q"]].values)
df["Embarked_S"] = stdsc.fit_transform(df[["Embarked_S"]].values)
最後に、train.csvだけをdf_trainとして切り離し、df_trainを訓練データとテストデータに分割します。
command
#訓練データの切り離し
df_train = df[df["TrainFlag"] == True]
df_train= df_train.drop(["TrainFlag"], axis = 1)
#テストデータの切り離し(今回の検証ではsubmitまではしないため、df_testは使いません)
df_test = df[df["TrainFlag"] == False]
df_test = df_test.drop(["TrainFlag"], axis = 1)
df_test = df_test.drop(["Survived"], axis = 1)
#df_trainを訓練データとテストデータに分割
y = df_train["Survived"].values
X = df_train.drop("Survived", axis=1).values
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=1234)
今回は前処理の話を必ずしも全て理解しておく必要はないですが、訓練データとテストデータの結合や切り離しの意味が分からない方は、下記の記事も併せてお読みください。
-
-
Kaggle|訓練データ・テストデータの結合と切り離しの仕方を解説
・Kaggleのtitanicをちょうどやり始めたけど、train.csvとtest.csvの結合の仕方が分からない ・最後にtest.csvの部分だけをKaggleに提出しないといけないけど、どうや ...
続きを見る
(1)ロジスティック回帰
ロジスティック回帰は正則化も前回の記事で行っているので、正則化をしていこうと思います。
■L1正則化
command
#penaltyをl1にする
clf_L1 = SGDClassifier(loss = "log", penalty = "l1", random_state=1234)
#X_train,y_trainを使って訓練
clf_L1.fit(X_train,y_train)
#テストデータを使って精度検証
clf_L1.score(X_test, y_test)
精度は0.809でした。
■L2正則化
command
#penaltyをl2にする
clf_L2 = SGDClassifier(loss = "log", penalty = "l2", random_state=1234)
#X_train,y_trainを使って訓練
clf_L2.fit(X_train,y_train)
#テストデータを使って精度検証
clf_L2.score(X_test, y_test)
精度は0.794でした。
(2)サポートベクトルマシン
サポートベクトルマシンを実装していきます。
command
#モデル構築
clf = SVC(random_state=1234)
#X_train,y_trainを使って訓練
clf.fit(X_train, y_train)
#テストデータを使って精度検証
clf.score(X_test, y_test)
精度は0.832でした。
③まとめ
サポートベクトルマシンは標準化によって精度が割と上がっていますね。
普段自分自身がコンペに参加するときも、標準化は基本的にするようにしています。
■補足
どの「モデル」や「手法」が精度が出やすいかは、使うデータによって変わってきます。
今回は、「titanic」のデータの「私が選んだ変数」の場合の話ですので、
「標準化をしたら必ず精度が上がる」
「(1.シンプル列を見て)サポートベクトルマシンよりランダムフォレストの方が必ず優秀」
というわけではないので、ご注意ください。
特に、今回の企画はデータに対する深い考察をしないまま、「とにかくやってみる」を目標にしているので、
「なるほど、とりあえずこのコードの書き方を真似すれば自分でも実装できるんだ」という主旨であることを理解をして頂けますと幸いです。
次回は第四回として、「ハイパーパラメータチューニングを行った場合」について記事にしていきたいと思います。
最後までお読みいただき、ありがとうございました。