8.2 モデル評価の書き方

機械学習 (教師あり学習) において, 基本的にモデルの評価は観測値と予測値の比較でなされます. よって, ここでもインプットの形式を統一することができます(とはいえ, モデル自体に比べてモデルの評価指標は頻繁に変更するものではありませんが). scikit-learn.metrics にはよく使われる指標が多く用意されています. 今回のタスクで重要なのは対数損失ですが, これも log_loss() として用意されています.

from sklearn.metrics import log_loss

logis_std_pca.fit(X, y)
## Pipeline(steps=[('standardize', StandardScaler()), ('PCA', PCA()),
##                 ('logistic', LogisticRegression(random_state=42))])
log_loss(y,logis_std_pca.predict_proba(X)[:, 1])
## 0.624504669268661

なお, 分類器の .score() が返すのは的中率です. そして, 今回のタスクでは対数損失ではなく, これを分かりやすくした正規化交差エントロピー (NE) を使用します. この指標の意味と計算方法は scikit-learn に用意されていません. 我々が作成したml_sharedには normalized_entropy() 関数として用意されています. NE から何を読み取れるかについては 10章で改めて説明します.

視覚的にモデルの評価を行うこともできます. 例えば, plot_roc_curve で ROC 曲線を描くことができます.

from sklearn.metrics import roc_curve, RocCurveDisplay
_ = RocCurveDisplay.from_estimator(logis_std_pca, X, y).plot()
plt.show()

ROC曲線の例

ただし, この方法では訓練/検証データごとにROC曲線を描くとか, モデル間の比較といったことが面倒です. plotnine を使う方法も紹介します. 少し長いですが, まずデータを訓練・テストに分割し, それぞれロジスティック回帰とランダムフォレストで学習, そして データ x モデルの4通りの結果をデータフレームにしています.

from sklearn.metrics import roc_curve, roc_auc_score
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=.3, random_state=42)
_ = rf.fit(X_train, y_train)

df_roc = []
for name, model in dict(
    logistic=logis,
    randomforest=rf
).items():
    p_train = model.predict_proba(X_train)[:, 1]
    p_test = model.predict_proba(X_test)[:, 1]
    auc_train = roc_auc_score(y_train, p_train)
    auc_test = roc_auc_score(y_test, p_test)
    df_roc += [pd.concat([
        pd.DataFrame(roc_curve(y_train, p_train)[:2],
                     index=['fpr', 'tpr']).transpose().assign(
            model=name, data='train', auc=auc_train),
        pd.DataFrame(roc_curve(y_test, p_test)[:2],
                     index=['fpr', 'tpr']).transpose().assign(
            model=name, data='test', auc=auc_test)
    ])]
df_roc = pd.concat(df_roc)

これを plotnine でまとめて描画します. plot_roc_auc() は AUC の値も表示しているため, こちらでもラインプロットに重ねて表示しています. しかし, plotnine の仕様上色と線種の凡例が個別に表示されるため, AUCの値は自分で表示する処理を書く必要があります.

ggplot(df_roc, aes(x='fpr', y='tpr',
                   color='model', linetype='data')
      ) + geom_line(size=1.5) + geom_text(
    aes(x='x', y='y', label='label'),
    data=df_roc[['data', 'model', 'auc']].drop_duplicates(
        ignore_index=True).assign(
        y=lambda d: d.index/10, x=.5,
        label=lambda d: d.model + d.data.map('({}): '.format) + d.auc.map('{:.4f}'.format)
    ),
    ha='left'
)

複数ROC曲線の同時プロット

モデルをどのように評価するかはタスクに応じてよく考えるべきです. ここで紹介したのはあくまで一例です. より詳しい話は 9 章を参考にしてください.