🦕
いろんなClassifierの決定境界を可視化してみた
sklearn公式でもここにあったが、自分メモ用にいろんなClassifierの決定境界を可視化してみた。
試したのは
- sklearn SVC(linear)
- sklearn SVC(rbf)
- sklearn MLP
- sklearn kNN
- sklearn Gaussian Naive Bayes
- sklearn Decision Tree
- sklearn Random Forest
- sklearn Adaboost
- sklearn Gradient Boosting
- sklearn Hist Gradient Boosting
- XGBoost
- LightGBM
- Catboost
- Tabnet
前準備
!pip install -q catboost pytorch-tabnet
import numpy as np
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
使ったデータ
今回使うシミュレーションデータは3クラス分類の2次元データ。
xs, ys = make_blobs(n_samples=1_000, centers=3, cluster_std=1, random_state=0)
可視化すると、こんなデータ。
plt.scatter(xs[:, 0], xs[:, 1], c=ys, s=10, cmap=plt.cm.coolwarm)
plt.show()
決定境界を見るためのコード
学習済みのclassifierを渡せば良いように書いた。
2枚表示されるが、左図は学習データにズームしたVer、右図はズームアウトしたVer。
def simulate(clf, x_min=-6, x_max=6, y_min=-4, y_max=8):
fig, ax = plt.subplots(1, 2, figsize=(18, 6))
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.01), np.arange(y_min, y_max, 0.01))
z = clf.predict(np.array([xx.ravel(), yy.ravel()]).T)
ax[0].contourf(xx, yy, z.reshape(xx.shape), alpha=0.2, cmap=plt.cm.coolwarm)
ax[0].scatter(xs[:, 0], xs[:, 1], c=ys, s=10, cmap=plt.cm.coolwarm)
xx, yy = np.meshgrid(np.arange(x_min*2, x_max*2, 0.01), np.arange(y_min*2, y_max*2, 0.01))
z = clf.predict(np.array([xx.ravel(), yy.ravel()]).T)
ax[1].contourf(xx, yy, z.reshape(xx.shape), alpha=0.2, cmap=plt.cm.coolwarm)
ax[1].scatter(xs[:, 0], xs[:, 1], c=ys, s=10, cmap=plt.cm.coolwarm)
plt.show()
可視化結果
ほとんどハイパーパラメータのチューニングはしていない。
SVC(kernel='linear')
from sklearn.svm import SVC
clf = SVC(kernel='linear')
clf.fit(xs, ys)
simulate(clf)
直線の境界なので見た目がシンプル。
SVC(kernel='rbf')
clf = SVC(kernel='rbf')
clf.fit(xs, ys)
simulate(clf)
赤い境界が外全部を囲むので、とびっきりの外挿が来たらやばそう。
MLPClassifier
from sklearn.neural_network import MLPClassifier
clf = MLPClassifier(random_state=0)
clf.fit(xs, ys)
simulate(clf)
ズームしているとちょっと折線になってる。が、全体的にあシンプルな境界。層が小さいから?
KNeighborsClassifier
from sklearn.neighbors import KNeighborsClassifier
clf = KNeighborsClassifier(n_neighbors=3)
clf.fit(xs, ys)
simulate(clf)
ズームアウトするとシンプルだが、ズームインすると複雑な境界面がある。
GaussianNB
from sklearn.naive_bayes import GaussianNB
clf = GaussianNB()
clf.fit(xs, ys)
simulate(clf)
直線っぽいが、ちょっと学習データの分布に引っ張られてちょっと曲線の境界?
DecisionTreeClassifier
from sklearn.tree import DecisionTreeClassifier
clf = DecisionTreeClassifier(random_state=0)
clf.fit(xs, ys)
simulate(clf)
ちょっと外れたデータの判別に境界が引っ張られる分、外挿にはロバストとは見えない。
RandomForestClassifier
from sklearn.ensemble import RandomForestClassifier
clf = RandomForestClassifier(random_state=0)
clf.fit(xs, ys)
simulate(clf)
DecisionTreeよりも決定境界に柔軟さがあるように見える。
AdaBoostClassifier
from sklearn.ensemble import AdaBoostClassifier
clf = AdaBoostClassifier(random_state=0)
clf.fit(xs, ys)
simulate(clf)
赤の決定境界が一部青側にあってちょっと気持ち悪い。
GradientBoostingClassifier
from sklearn.ensemble import GradientBoostingClassifier
clf = GradientBoostingClassifier(random_state=0)
clf.fit(xs, ys)
simulate(clf)
RandomForestよりも細かい境界が多く見える。ちょっと
HistGradientBoostingClassifier
from sklearn.ensemble import HistGradientBoostingClassifier
clf = HistGradientBoostingClassifier(random_state=0)
clf.fit(xs, ys)
simulate(clf)
ズームアウトした境界はRandomForestよりもシンプルに見えて違和感も少ない。
これがlightgbmにインスパイアされたものらしいので、lightgbmとほとんど同じに見える。
XGBClassifier
import xgboost as xgb
clf = xgb.XGBClassifier(random_state=0)
clf.fit(xs, ys)
simulate(clf)
LGBMClassifier
import lightgbm as lgb
clf = lgb.LGBMClassifier(random_state=0)
clf.fit(xs, ys)
simulate(clf)
CatBoostClassifier
from catboost import CatBoostClassifier
clf = CatBoostClassifier(random_state=0, metric_period=100)
clf.fit(xs, ys)
simulate(clf)
けっこう決定境界が外れ値に引っ張られた結果になっている。
TabNetClassifier
from pytorch_tabnet.tab_model import TabNetClassifier
clf = TabNetClassifier(seed=0)
clf.fit(xs, ys)
simulate(clf)
全体的にはきれいに境界があるように見えるが、上の部分に赤が突然出てきたり、極端な外挿で変な挙動をしそう。
Discussion