PyCaretの複数モデルによるアンサンブルとは

機械学習には、様々な学習器が存在してします。例えば勾配ブースティングやランダムフォレストなどは単独のアンサンブル学習器です。
機械学習のアンサンブル学習には、ブースティングやバギングという手法があります。
ブースティングは、最初に作成した弱学習器の予測誤差を新しく作成した弱学習器に逐次的に引き継ぎながら予測精度を向上させるアンサンブル手法(逐次学習)です。
バギングは、複数の弱学習器を作成し同時に学習させ、それぞれの結果を用いて最終結果を決定するアンサンブル手法です。
機械学習の個々の学習器には、得意な問題や不得意な問題が存在します。ブースティングやバギングは同じ学習器を用いるため、思ったような汎化性能が得られない場合があります。
これらの問題を解決するために、異なる手法の学習器を複数組み合わせたアンサンブル手法が考案されています。異なる手法の学習器を組み合わせてお互いの弱点を補うことで、汎化性能の向上が期待できます。
複数の異なる学習器を使用することから、モデルアンサンブルと表現した方がわかりやすいかもしれません。
今回は、PyCaretのモデルアンサンブルの実装方法について紹介します。
目次
PyCaretの複数モデルによるアンサンブルとは
PyCaretは、「ブレンドモデル」と「スタックモデル」の2つのモデルアンサンブルを簡単に実装できるAutoMLライブラリです。
「ブレンドモデル」は、複数の異なる手法の弱学習器を使用して学習を行い、それぞれの結果を確立または多数決で決定するモデルアンサンブル手法です。
「スタックモデル」は、複数の異なる手法の弱学習器を使用して学習を行い、それぞれの結果をさらに上位の一つの学習器で学習し決定するモデルアンサンブル手法です。
どちらも、複数の異なる手法の弱学習器を使用する点では同じですが、「ブレンドモデル」では各学習器は横並び、「スタックモデル」は横並びの学習器の上にもう一つ学習器が存在してレイヤー構造を成しており、最終結果の導出方法が異なっています。
学習データの準備とセットアップ
今回のモデルアンサンブルの実験では、毎度おなじみのアヤメのデータを使用して分類問題を解いていきます。今回のトライアルでは、PyCaretのデータセットを利用していきます。
import pandas as pd
from pycaret.datasets import get_data
from pycaret.classification import *
df = get_data('iris')

読み込んだデータ内容について確認します。
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 150 entries, 0 to 149
Data columns (total 5 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 sepal_length 150 non-null float64
1 sepal_width 150 non-null float64
2 petal_length 150 non-null float64
3 petal_width 150 non-null float64
4 species 150 non-null object
dtypes: float64(4), object(1)
memory usage: 6.0+ KB
読み込んだデータをヒストグラムに表してみます。
df.hist()

ヒストグラムは、各種データを階級と度数で表現したグラフです。ヒストグラムを見ることで、データが持つ特徴や関連性を大雑把にとらえることができます。
次に各要素の相関係数を確認してみましょう。
df.corr()

import seaborn as sns
sns.heatmap(df.corr(),annot = True, cmap = 'coolwarm')

花びらの長さ(petal_length)に対して花びらの幅(petal_width)とガクの長さ(sepal_length)の相関が高いことがわかります。
次に、各データ項目の組み合わせごとの散布図を描画してみます。
sns.pairplot(df, hue="species")

機械学習のセットアップを行います。目的変数は「species」です。このデータは、150個のデータレコードから構成されています。setup関数を実行すると、104個の学習用データと46個のテストデータを自動的に生成してくれます。
setup(data = df, target = 'species', session_id=777)
学習器の比較
モデルアンサンブルの候補となる学習器を選定するため、学習器の比較を行います。
compare_models()

それぞれの交差検証の結果、もっと精度が高いのはqda(二次判別分析)でした。次いでlda(線形判別分析)、knn(K-最近傍法)の順で並んでいます。これらの学習器は、すでにスコアが高いため、この問題を解く上では単独でも問題なさそうです。
モデルアンサンブルを実装する
モデルアンサンブルは、異なる手法の弱学習器の組み合わせにより汎化性能を向上させることが目的なので、精度の低い方から選択してトライアルしてみます。
svm(サポートベクターマシン)、ridge(リッジ回帰)とdt(決定木)を組み合わせて、ブレンドモデルとスタックモデルを作成していきます。
ada、ligthtgbmとxgboostはブースティングモデルであるため、今回のトライアルでは除外します。
、個々のモデルの作成
まずは、個々のモデルをcreate_model()関数で作成していきます。
svm = create_model('svm')
ridge = create_model('ridge')
dt = create_model('dt')
ブレンドモデルの作成
ブレンドモデルを作成するには、blend_models関数を使用します。
blender = blend_models(estimator_list = [svm, ridge, dt], method = 'hard')
estimator_listに、先ほど作成した個々のモデルのオブジェクトをリストで渡します。methodは、「hard(多数決)」か「soft(確率)」を選択することができますが、ブレンドするモデルの組み合わせにより選択肢が異なります。
今回の組み合わせでは、「method = soft」はエラーとなるため、「method = hard」を設定しています。

作成したブレンドモデルのハイパーパラメータをチューニングしてみます。
tuned_blender = tune_model(blender)

チューニング前のAccuracy(正解率)、Recall(再現率)、Prec(適合率)及びF1の平均値が向上したことが確認できました。
スタックモデルの作成
スタックモデルを作成するには、stack_models関数を使用します。
stacker = stack_models(estimator_list = [svm, ridge], meta_model = dt)
estimator_listには、svmとridge学習器のオブジェクトをリストで渡します。meta_modelには、dt学習器のオブジェクトを渡します。
これは、1階層目がsvmとridgeの弱学習器レイヤーで、2階層目が1階層目の結果を学習して最終的な結果を出力する弱学習器レイヤーであることを意味しています。

作成したスタックモデルのハイパーパラメータをチューニングしてみます。
tuned_stacker = tune_model(stacker)

こちらも、チューニング前のAccuracy(正解率)、Recall(再現率)、Prec(適合率)及びF1の平均値がすべて向上しました。
まとめ
今回は、アンサンブル機械学習の一種であるブレンドモデルとスタックモデルによるトライアルをやってみました。
ブレンドモデルやスタックモデルは、複数の弱学習器を集めることによって、お互いの弱点を補いながら予測精度を向上させることが可能な優れたアンサンブル学習法です。
このトライアルでは、3つの弱学習器に絞ってモデルアンサンブルを行いましたが、複数の学習器を組み合わせることで、さらに複雑な問題においても汎化性能を高めることができる可能性があります。
PyCaretを利用することで、ligthtgbm、catboostやxgboostなどのブースティングやランダムフォレストに代表されるバギングを組み合わせて、より複雑なアンサンブル機械学習をローコード実装できてしまいます。
あらためてPyCaretのAutoMLの凄さを実感できました。
SDGsと地方創生に関するお問い合わせについて
どんな内容でも構いませんので、気兼ねなくご相談ください。
システムエンジニアリングの経験を持つスタッフが、ボランティアでご相談に応じさせていただきます。