見出し画像

シリーズPython⑥ XAI「機械学習を解釈する技術」を最新のライブラリで解釈する

はじめに


機械学習を解釈する技術の紹介

この記事は書籍「機械学習を解釈する技術〜予測力と説明力を両立する実践テクニック」(技術評論社、以下「テキスト」と呼びます)を 最近のPythonで動かすときの留意点を取り扱います。

テキストは、2021年8月に出版された「XAI・説明可能なAI」に関連する書籍です。
4つの基本的な説明指標を非常に丁寧に説明する良書です。
初めて4つの指標を学ぶ方にオススメです!

■ 4つの指標
・PFI : Permutation Feature Importance(特徴量の重要度)
・PD : Partial Dependence(特徴量と予測値の平均的な関係)
・ICE : Individual Conditional Expectation(個別データごとの異質性)
・SHAP : SHapley Additive exPlanations(個別データの特徴量貢献度)

■ テキストの特徴
次の3つの方法を用いて、とにかく、計算ロジックを丁寧に説明しています。
・数式
・簡単なモデルによる計算イメージ図
・コード実装(オリジナルコードと Pythonライブラリ使用コード)

■ 説明に使用する機械学習モデル
・線形重回帰モデル
・Random Forest モデル

■ 利用するプログラム言語
・メインは Python です。
・巻末に R の実装例(tidymodels、DALEX を利用)の掲載があります。

注意のマーク:「いらすとや」さんより

最近の Python 環境で動かすときの留意点と対策

テキストは約2年前に出版されています。
出版後、現在までに Python を取り巻く環境は大きく変化しています。
私もご多分に漏れず変化の波にのまれて、2つの問題に直面しました。

① テキストで利用するデータの取得が困難
② 最近のライブラリでは動かないコードがある

この記事は、私が実施した問題の対策を記載いたします。
テキストを手にした仲間が、ストレスなくコードを動かせたなら、幸いです。

一緒に本を読む子供たちのイラスト:「いらすとや」さんより



まえがき

この記事は、出典に記載の書籍に掲載された文章及びコードを引用し、適宜、掲載文章とコードを改変して書いています。
コードの書き換えは「見つけることができた範囲内の処理内容」であり、処理の正確性は担保しておりません。
誤りや改善点がありましたら、ぜひ教えてください。

【出典】
「機械学習を解釈する技術〜予測力と説明力を両立する実践テクニック」(初版第4刷、森下光之助 著、技術評論社)

記号について
コードのコメントに★印のついている箇所が変更点です。

それでは「説明可能な対策案」を目指して、記事に進みます!!!

説明会・セミナーのイラスト:「いらすとや」さんより


1. 「実データでの分析」で用いるデータセット


【関連する章】
第2章~第6章

テキストは「ボストン住宅価格データセット」を用いて説明指標の分析を行います。
取得方法には scikit-learn の datasets を用いています。

【問題】
scikit-learn のバージョン 1.2 以降、ボストン住宅価格データセットを取得できなくなりました。
従いまして、第2章 2.3.1 「データの読み込み」の「データセットの読み込み」処理でエラーが発生します。

### bostonデータをインポートするコード
from sklearn.datasets import load_boston

【自環境のバージョン】
scikit-learn : 1.3.0

【解決策の一例】
ボストン住宅価格データセットが無いと、テキストの美味しい部分を味わえないので、ぜひとも取得したいです!
ひとまず、ボストン住宅価格データセットを掲載するサイトから入手しましょう。

■ 掲載サイトの例
① rupakc 氏のGitHub(この下線リンクから飛べます)
② kaggle(kaggle ログイン後、下のリンクでデータセットに飛べます)

■ データ取得~読み込みの例
①の rupakc 氏のサイトでデータを取得する場合の手順を例示いたします。

①のサイトを開き、赤枠の下矢印をクリックして、ファイル保存画面を表示します。
ファイル名は表示された「housing.data」のままにして、PythonのNotebookファイルと同じフォルダに保存します。

①のサイトの画面イメージ

2.3.1「データの読み込み」の2つ目のコードを次の内容に差し替えます。

### データセットの読み込み

# 特徴量名の設定
feature_names = ['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS',
                 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT', 'MEDV']

# ファイルの読み込み
X = pd.read_csv('housing.data', names=feature_names, sep='\s+', 
                encoding='utf_8_sig')

# データの整形
y = X['MEDV'].values
X = X.drop('MEDV', axis=1)

【改善後】
特徴量 X と目的変数 y の形状、および、特徴量の先頭5行を表示します。

# 特徴量と目的変数の形状の表示
print('X.shape:', X.shape)
print('y.shape:', y.shape)

# 特徴量の表示
display(X.head())

2.3.2「データの前処理」の「特徴量の出力」の結果と同じになりました。

実行結果のイメージ


ボストン・テリアのイラスト(犬):「いらすとや」さんより


2. seabornのplot引数


【関連する章】
第2章~第5章、付録Bの「plot_scatter(s)関数」など

テキストでは、グラフ描画ライブラリ「seaborn」を多用して、ビジュアルにデータの特徴や説明指標を説明しています。

【問題】
最近の seaborn では、引数の順番が変更された
模様です。
data、x、y ・・・ のように、x 引数、y 引数の前に data 引数が割り込んだため、テキストの順番 x、y ではエラーが発生して、グラフを描画できません。
※おそらく seaborn のバージョン 0.12.0 以降だと思われます。

【自環境のバージョン】
seaborn : 0.12.2

【解決策の一例】
第2章の plot_scatters 関数の定義を例にして、コード変更案を説明します。

### 散布図描画関数の定義
def plot_scatters(x, y, title=None):
    '''目的変数と特徴量の散布図を作成'''
    
    cols = x.columns
    fig, ax = plt.subplots(2, 2)
    
    for ax, c in zip(ax.ravel(), cols):
        # sns.scatterplot(x[c], y, ci=None, ax=ax)     # ★変更
        sns.scatterplot(x=x[c], y=y, ax=ax)            # ★変更 
        ax.set_ylabel('MEDV')
    
    fig.suptitle(title)
    plt.show()

「sns.scatterplot(x=x[c], y=y, ax=ax)」のように、x 軸のデータには x= を、y 軸のデータには y= を付けます
なお併せて、引数 ci を削除しました。

【改善後】
無事に散布図を描画できました!

【影響する他のコード】

  • 第3章・第4章・第5章・付録Bの「plot_scatter 関数」に含まれる sns.scatterplot

  • 第5章の「IndividualConditionalExpectationクラス」に含まれる sns.lineplot と sns.scatterplot

  • Pythonスクリプトファイル「interpret.py」に含まれる sns.lineplot と sns.scatterplot

海を割るモーセのイラスト:「いらすとや」さんより


3. PD・ICEの可視化 by scikit-learn


【関連する章】
第4章・第5章の「plot_partial_dependence」を用いるコード

第4章・第5章の「実データでの分析」の項では、PD、ICEのグラフ可視化に scilit-learn の 「plot_partial_dependence」関数を用いています。

【問題】
最近の scilit-learn では「plot_partial_dependence」関数が削除されました

※おそらく scikit-learn のバージョン 1.2.0 以降だと思われます。
テキストのコードをそのまま実行すると、エラーになり、PDやICEのプロットができません。

【自環境のバージョン】
scikit-learn : 1.3.0

【解決策の一例】
第4章の 4.5.1 「PDによる可視化」の「plot_boston_pd 関数」を例にして、コード変更案を説明します。

### PDの可視化 by scikit-learn

# from sklearn.inspection import plot_partial_dependence   # ★変更
from sklearn.inspection import PartialDependenceDisplay    # ★変更

# 何度か使うのでPartialDependenceDisplayを利用した関数を作成する
def plot_boston_pd(var_name, var_name_jp):
    '''PDを可視化する関数'''
    
    fig, ax = plt.subplots()
    
    # plot_partial_dependence(                             # ★変更
    PartialDependenceDisplay.from_estimator(               # ★変更
        
        estimator=rf,         # 学習済みモデル
        X=X_test,             # PDを計算したいデータ
        features=[var_name],  # PDを計算したい特徴量
        kind='average',       # PDは'average', ICEは'individual', 両方は'both'
        ax=ax,
    )
    
    fig.suptitle(f'{var_name_jp}({var_name})のPartial Dependence Plot')
    plt.show()

「plot_partial_dependence」関数の代替機能は「PartialDependenceDisplay.from_estimator」です。
次の2点を変更します。

  • インポート

    • PartialDependenceDisplay をインポートします。

  • 関数の実行

    • PartialDependenceDisplay.from_estimator に差し替えます。
      なお、引数は、以前の「plot_partial_dependence」関数と同じで動きます。

【改善後】
無事に特徴量「RM」の PD を描画できました!

【影響する他のコード】

  • 第5章 5.6「実データでの分析」の「plot_ice 関数」

暑中お見舞いのイラスト「アイスクリーム」:「いらすとや」さんより


4. shap のインストール


【関連する章】
第6章の 6.6.1「shap パッケージの導入」

第6章の「実データでの分析」の項では、SHAP 値の算出やさまざまなグラフ描画にパッケージ「shap」を利用します。
次のリンクは shap のサイトです。

【問題】
Anaconda 環境に conda コマンドで shap をインストールして、テキストの「SHAP 値を計算するための explainer を作成」コードを実行したところ、エラーになりました。

conda install -c conda-forge shap

■ エラーメッセージ
AttributeError: module 'numpy' has no attribute 'bool'.

実行コードに numpy は含まれていないので、このエラーは謎だらけでした・・・

【エラーの原因】
anacondaで管理可能な shap と numpy のバージョンの関係に問題がありました。

・shap は内部処理で numpy を利用。
・numpy が 1.24.0 にバージョンアップした際に bool に関する処理を削除。
 しかし、shapでは削除した処理を利用していた。
・shap が 0.42.0 にバージョンアップした時に、numpy 利用処理を変更。
・conda コマンドでインストールする shap のバージョンは 0.41.0 。 

まとめます。

  • shap が 0.42.0 より古い場合、numpy は 1.24.0 より古いバージョンが必要

  • shap が 0.42.0 以降の場合、numpy は 1.24.0 以降のバージョンでOK

【自環境のバージョン】
numpy : 1.24.3

更新のマーク:「いらすとや」さんより

【解決策の一例】

主に次の3つの方法でインストール/バージョン変更を行って、 shap と numpy のバージョンの整合性をとります。

■ anaconda で実施できる策
① shap と numpyのバージョン整合性を維持できる仮想環境を作る
② numpy を 1.24.0 よりも前のバージョンにする

■ anaconda で実施できない策
③ pip でバージョン 0.42.0 以上の shap をインストールする

私は、③の pip で バージョン 0.42.1 の shap をインストールしました。
最も簡単に実施できる点を優先しました。
なお、pip でインストールする前に、shap のアンインストールが必要です。

# conda環境のshapをアンインストール
conda uninstall shap

# pipでshapをインストール
pip install shap

【改善後】
無事にインスタンス0の SHAP 滝グラフを描画できました!

【影響する他のコード】

  • 第6章 6.6「実データでの分析」の shap を利用するコード全般

  • 付録B B.5.2「シミュレーションによる比較」の shap を利用するコード全般

カンカン帽のイラスト:「いらすとや」さんより


結び


shap ライブラリは、shap 値を利用した特徴量重要度を可視化できるなど、活用の場が広いと思います。
データ分析のモデルを評価したり、関係者にモデルを伝えるときに、今回学んだ4つの指標を活用したいです。

おわり

ブログの紹介


noteで3つのシリーズ記事を書いています。
ぜひ覗いていってくださいね!

1.のんびり統計
統計検定2級の問題集を手がかりにして、確率・統計をざっくり掘り下げるブログです。
雑談感覚で大丈夫です。ぜひ覗いていってくださいね。
統計検定2級公式問題集CBT対応版に対応しています。

2.Python機械学習プログラミング実践記
書籍「Python機械学習プログラミング PyTorch & scikit-learn編」を学んだときのさまざまな思いを記事にしました。
この書籍は、scikit-learnとPyTorchの教科書です。
よかったらぜひ、お試しくださいませ。

3.データサイエンスっぽいことを綴る
統計、データ分析、AI、機械学習、Pythonのコラムを不定期に綴っています。
「統計」「Python」「数学とPython」「R」のシリーズが生まれています。

最後までお読みいただきまして、ありがとうございました。


この記事が気に入ったらサポートをしてみませんか?