第5回に教師あり学習・回帰を扱いました.教師あり学習には他に分類もあります.
◇ 広い意味を持つ分類 (classification)
大辞林より
◇ 教師あり学習・分類 (supervised learning - classification)
◇ 教師あり学習「分類」と「回帰」の違い
◇ 教師あり学習「分類」と教師なし学習「クラスタリング」の違い
第3回では,決定木分析を用いて,アヤメの種類の分類モデルを作成した.この節で紹介するロジスティック回帰でも,決定木と同様に分類の予測モデルを作ることができる
アヤメの分類問題に関し,Qiitaにもk-近傍法(k-NN)やサポートベクターマシン(SVM)の実装例があり,ご都合の良い際にご参照ください
◇ STEP 0 準備
# Pandasをインポート import pandas as pd # train_test_splitをインポート(データの分割用) from sklearn.model_selection import train_test_split
◇ STEP 1 データの読み込み
#アヤメデータの取得 df = pd.read_csv("https://www2.cmds.kobe-u.ac.jp/~masa-n/dshandson/iris-sample.csv") #確認 df
◇ STEP 2 欠損値を穴埋めする
# 平均値による欠損値の穴埋め df_mean = df.mean() train2 = df.fillna(df_mean) # 特徴量と正解データに分割 x = train2.loc[:,:'花びらの幅'] t = train2['品種'] # 特徴量の標準化 from sklearn.preprocessing import StandardScaler sc = StandardScaler() new = sc.fit_transform(x)
◇ STEP 3 訓練データと検証用データを分割する
# 訓練データと検証データに分割 x_train, x_val, y_train, y_val = train_test_split(new, t, test_size = 0.2, random_state = 0)
◇ STEP 4 ロジスティック回帰による学習
from sklearn.linear_model import LogisticRegression model = LogisticRegression(random_state = 0, C = 0.1, multi_class = 'auto', solver = 'lbfgs')
☆☆ モデル変数 = LogisticRegression(C = 値,multi_class = 'auto', solver = 'lbfgs')
◇ STEP 5 正解率を確認する
model.fit(x_train, y_train) print(model.score(x_train, y_train)) model.score(x_val, y_val)
【実行結果】
0.925 0.9333333333333333
◇ STEP 6 係数を確認する
model.coef_ # 係数の確認
◇ STEP 7 新規データで予測する
x_new = [[1, 2, 3, 4]] # 新規データ model.predict(x_new) # 新規データで予測
【実行結果】
array(['Iris-virginica'], dtype=object)
◇ STEP 8 確率の予測結果を確認する
model.predict_proba(x_new)
☆☆ モデル変数.predict_proba( 2次元データ )
実際の業務では,正解データの件数の比率に大きな差がある場合も多々ある.このようなデータを不均衡データと呼ぶ.モデルの作成と学習時に,不均衡データの考慮が必要
◇ 不均衡データで対応するようなモデルの例:決定木(DecisionTreeClassifier)
''class_weight = 'balanced' という引数を指定すると
☆☆ 不均衡データに対処する決定木モデルの作成
tree.DecisionTreeClassifier( class_weight = 'balanced' )
※ class_weight 引数は不均衡データのときに指定する.決定木モデルだけでなく,他の分類モデルでも同様に指定できる.例,LogisticRegression( class_weight = 'balanced' )
第5回で皆さんに実際に体験して頂いたように,過学習(overfitting)とは「訓練データでは予測と実際の誤差が少ないのに,未知のテストデータでは,誤差が大きくなる現象」である
◇ 誤差が生じている不適切な状況を考えると,以下の2通りがある
◇ 正解データにおける平均値からのばらつきをノイズと呼ぶ
☆☆ バイアス・バリアンス分解
実際と予測の誤差 = バイアス + バリアンス + ノイズ
これから話すランダムフォレストは決定木の上位互換である.皆さんは第3回で体験して頂いた決定木を振り返って,左右2つに分岐していくフローチャートを「木」と呼ぶ
フォレストのことは「森」である.ランダムフォレストは,たくさんの決定木を作成し,それぞれの木に予測させ,その結果の多数決で最終結果を求めるという手法である
ランダムフォレストは通常の決定木に比べて過学習(overfitting)を防ぐことができる
以下を従って,ランダムフォレストの実装からモデルを理解してみましょう
◇ STEP 0 Pandasなどのモジュールを読み込む
# モジュールの読み込み import pandas as pd from sklearn.model_selection import train_test_split %matplotlib inline
◇ STEP 1 データを読み込む
df = pd.read_csv('https://www.es4.eedept.kobe-u.ac.jp/~chensinan/share/Survived.csv') # csvファイルの読み込み # 確認する df.head(2)
このデータを利用して,それぞれの乗客がこの客船の沈没事故に遭遇した場合に,無事生還できるかどうかを予測しましょう
◇ STEP 2 欠損値を穴埋める
jo1 = df['Pclass'] == 1 jo2 = df['Survived'] == 0 jo3 = df['Age'].isnull() df.loc[(jo1) & (jo2) & (jo3), 'Age'] = 43 jo2 = df['Survived'] == 1 df.loc[(jo1) & (jo2) & (jo3), 'Age'] = 35 jo1 = df['Pclass'] == 2 jo2 = df['Survived'] == 0 jo3 = df['Age'].isnull() df.loc[(jo1) & (jo2) & (jo3), 'Age'] = 26 jo2 = df['Survived'] == 1 df.loc[(jo1) & (jo2) & (jo3), 'Age'] = 20 jo1 = df['Pclass'] == 3 jo2 = df['Survived'] == 0 jo3 = df['Age'].isnull() df.loc[(jo1) & (jo2) & (jo3), 'Age'] = 43 jo2 = df['Survived'] == 1 df.loc[(jo1) & (jo2) & (jo3), 'Age'] = 35
◇ STEP 3 文字データの列を数値に変換する
# 特徴量として利用する列のリスト col = ['Pclass', 'Age', 'SibSp', 'Parch', 'Fare'] x = df[col] t = df['Survived'] # Sex列は文字の列なのでダミー変数化 dummy = pd.get_dummies(df['Sex'], drop_first = True) x = pd.concat([x, dummy], axis = 1) x.head(2)
◇ STEP 4 ランダムフォレストの選定
# ランダムフォレストのインポート from sklearn.ensemble import RandomForestClassifier x_train, x_test, y_train, y_test = train_test_split(x, t, test_size = 0.2, random_state = 0) model = RandomForestClassifier(n_estimators = 200, random_state = 0)
☆☆ モデル変数
モデル変数 = RandomForestClassifier(n_estimators=〇, random_state=〇, max_depth=△)
※ n_estimatorsで作成する木の数を指定
※ 木の深さの最大値は,すべての木で共通
◇ STEP 5 モデルの学習
model.fit(x_train, y_train) print(model.score(x_train, y_train)) print(model.score(x_test, y_test))
【実行結果】
0.9887640449438202 0.8715083798882681
◇ STEP 6 単純な決定木分類と比較する
from sklearn import tree model2 = tree.DecisionTreeClassifier(random_state = 0) model2.fit(x_train, y_train) print(model2.score(x_train, y_train)) print(model2.score(x_test, y_test))
【実行結果】
0.9887640449438202 0.8156424581005587
◇ STEP 7 特徴量の重要度を確認する
importance = model.feature_importances_ # 特徴量重要度 # 列との対応がわかりやすいようにシリーズ変換 pd.Series(importance, index = x_train.columns)
【実行結果】
Pclass 0.079546 Age 0.323012 SibSp 0.045682 Parch 0.032854 Fare 0.265573 male 0.253334 dtype: float64
一方で決定木だけでなく,さまざまな予測モデルを作成して,最終的に1つの予測結果を出す手法のことをアンサンブル学習と呼ぶ
アンサンブル学習は,大きくわけてバンギングとブースティングという手法に類別することができる
ブースティングの手法の中に最も基本的なのはアダブーストである
【Pythonハンズオン6-2】の継続として,以下を行う
◇ STEP 8 アダブーストを実装する
# アダブーストのインポート from sklearn.ensemble import AdaBoostClassifier # ベースとなるモデル from sklearn.tree import DecisionTreeClassifier x_train, x_test, y_train, y_test = train_test_split(x, t, test_size = 0.2, random_state = 0) # 最大の深さ5の決定木を何個も作っていく base_model = DecisionTreeClassifier(random_state = 0, max_depth = 5) # 決定木を500個作成 model = AdaBoostClassifier(n_estimators = 500, random_state = 0, base_estimator = base_model) model.fit(x_train,y_train) # 学習 print(model.score(x_train, y_train)) # 訓練データの正解率 print(model.score(x_test, y_test)) # テストデータの正解率
【実行結果】
0.9887640449438202 0.8100558659217877
☆☆ モデルの作成
変数=AdaBoostClassifier(n_estimator=モデル数,random_state=数値,base_model=決定木などのモデル)
※ ベースモデルには,決定木やロジスティック回帰等を指定することができる(一般的には決定木を利用)
第3回のモデルの評価では,皆さんは精度(Accuracy)と混同行列(confution_matrix)を扱って頂いた.その他さまざまなな性能評価の指標もある.
【ハンズオン6-2】における客船の沈没事故のデータを利用し続き,分類の予測性能評価の実装から手法を理解してみましょう
◇ STEP 1 データの準備
# モジュールの読み込み import pandas as pd # データの準備 df = pd.read_csv('https://www.es4.eedept.kobe-u.ac.jp/~chensinan/share/Survived.csv') df = df.fillna(df.mean()) x = df[['Pclass', 'Age']] t = df['Survived']
◇ STEP 2 モデルの準備
# モデルの準備 from sklearn import tree model = tree.DecisionTreeClassifier(max_depth = 2, random_state = 0) model.fit(x, t)
◇ STEP 3 適合率,再現率,F値を一括で計算
classification_report関数で再現率と適合率を一括で計算してみましょう
from sklearn.metrics import classification_report pred = model.predict(x) out_put = classification_report(y_pred = pred, y_true = t) print(out_put)
☆☆ 適合率(precision)
☆☆ 再現率(recall)
☆☆ F値(f1-score)
◇ STEP 4 classification_report関数にパラメータ引数を指定
out_put = classification_report(y_pred = pred, y_true = t, output_dict = True) # out_putをデータフレームに変換 pd.DataFrame(out_put)
他指標には,特異度,偽陽性率,ROC曲線,AUC(曲線下面積)等もある