責任ある AI は、AI モデルを構築または使用する開発者や組織にとって、きわめて重要なプラクティスです。これは、AI モデルのライフサイクル全体 (開発、トレーニング、ファインチューニング、評価、デプロイを含む) にわたり、AI システムの安全性、信頼性、公平性、倫理性を確保するのに役立ちます。Platform for AI (PAI) を使用すると、責任ある AI ツールを Data Science Workshop (DSW) に統合して、AI モデルの公平性分析、エラー分析、解釈可能性分析を実行できます。
仕組み
責任ある AI プラクティスの一環として、エラー分析はモデルのパフォーマンスを理解し、向上させるための重要なステップです。その中心的な原則は、AI モデルの予測におけるエラーを体系的に特定、分析、解決し、精度と公平性を高めることです。エラー分析の中心的な原則は次のとおりです。
エラーの特定:モデルの予測エラーを特定します。これには、モデルの予測をグラウンドトゥルースと比較して、不一致を見つけることが含まれます。エラーは、偽陽性や偽陰性など、さまざまなタイプに分類できます。
エラーの分類:エラーをその特性に基づいて分類します。これにより、データ不均衡、不十分な特徴量、モデルのバイアスなどの根本原因をより深く理解するのに役立ちます。このプロセスには、ドメインの専門知識と人間の判断が必要になる場合があります。
根本原因の分析:各エラーカテゴリの原因を分析します。このステップは、モデルの最適化を直接導くため、きわめて重要です。これには、データ品質、モデル設計の問題、特徴量エンジニアリング、またはデータ表現の問題の分析が含まれる場合があります。
是正措置の実施:分析に基づいて、開発チームはモデルの問題に対処するための具体的な措置を講じることができます。これらの措置には、データクレンジング、データセットのリバランス、モデルアーキテクチャの変更、新しい特徴量の導入、または異なるアルゴリズムの使用などが含まれる場合があります。
反復と評価:エラー分析は一度きりのタスクではなく、反復的なプロセスです。モデルを修正するたびに、再度エラー分析を実行して、変更が効果的であったか、パフォーマンスが向上したか、または新しい問題が発生したかを評価する必要があります。
文書化と報告:透明性と解釈可能性を確保するために、エラー分析のプロセス、結果、および是正措置を徹底的に文書化します。これは、チームメンバーがモデルの制限を理解するのに役立ち、他のプロジェクトフェーズに貴重なフィードバックを提供します。
このチュートリアルでは、PAI DSW の responsible-ai-toolbox を使用して AI モデルのエラー分析を実行する方法を説明します。この例のタスクは、国勢調査データセットに基づいて、個人の年間収入が 50K を超えるかどうかを予測することです。
前提条件
DSW インスタンス。お持ちでない場合は、「DSW インスタンスの作成」をご参照ください。推奨される構成は次のとおりです。
推奨インスタンスタイプ:ecs.gn6v-c8g1.2xlarge
イメージ:Python 3.9 以降を推奨します。このチュートリアルでは、公式イメージ tensorflow-pytorch-develop:2.14-pytorch2.1-gpu-py311-cu118-ubuntu22.04 を使用します。
モデル:responsible-ai-toolbox は、Scikit-learn フレームワークの回帰モデルとバイナリ分類モデルをサポートしています。
トレーニングデータセット:独自のトレーニングデータセットを使用します。このチュートリアルのサンプルデータセットを使用するには、「ステップ3:データセットの準備」をご参照ください。
アルゴリズムモデル:独自のアルゴリズムモデルを使用します。このチュートリアルのサンプルモデルを使用するには、「ステップ5:モデルのトレーニング」をご参照ください。
ステップ1:DSW ギャラリーへの移動
PAI コンソールにログインします。
左上隅で、必要に応じてリージョンを選択します。
左側のナビゲーションウィンドウで、QuickStart > [ノートブックギャラリー] を選択し、「Responsible AI-Error Analysis」を検索して、カード上の Open in DSW をクリックします。
DSW インスタンスを選択し、Open Notebook をクリックします。「Responsible AI-Error Analysis」ノートブックが開きます。
ステップ2:依存関係のインポート
評価に使用される responsible-ai-toolbox の raiwidgets 依存関係をインストールします。
!pip install raiwidgets==0.34.1モデルトレーニングのために、責任ある AI と Scikit-learn の依存関係をインポートします。
# 責任ある AI の依存関係をインポート
import zipfile
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
import pandas as pd
from lightgbm import LGBMClassifier
from raiutils.dataset import fetch_dataset
import sklearn
from packaging import version
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformerステップ3:データセットの準備
国勢調査データセットをダウンロードして展開します。展開されたフォルダには、トレーニングデータ adult-train.csv とテストデータ adult-test.csv が含まれています。
# データセットファイルの名前を指定します。
outdirname = 'responsibleai.12.28.21'
zipfilename = outdirname + '.zip'
# データセットをダウンロードして展開します。
fetch_dataset('https://publictestdatasets.blob.core.windows.net/data/' + zipfilename, zipfilename)
with zipfile.ZipFile(zipfilename, 'r') as unzip:
unzip.extractall('.')ステップ4:データの事前処理
トレーニングデータ
adult-train.csvとテストデータadult-test.csvをロードします。トレーニングデータとテストデータを、特徴量変数とターゲット変数に分割します。ターゲット変数は、モデルが予測する実際の結果です。特徴量変数は、各データインスタンスにおけるターゲット変数以外の変数です。この例では、ターゲット変数は
incomeで、特徴量変数にはworkclass、education、およびmarital-statusなどが含まれます。トレーニングデータをトレーニング用に NumPy フォーマットに変換します。
# トレーニングデータとテストデータをロードします。
train_data = pd.read_csv('adult-train.csv', skipinitialspace=True)
test_data = pd.read_csv('adult-test.csv', skipinitialspace=True)
# 特徴量とターゲット変数の列を定義します。
target_feature = 'income'
categorical_features = ['workclass', 'education', 'marital-status',
'occupation', 'relationship', 'race', 'gender', 'native-country']
# 特徴量とターゲット変数を分割する関数を定義します。
def split_label(dataset, target_feature):
X = dataset.drop([target_feature], axis=1)
y = dataset[[target_feature]]
return X, y
# 特徴量とターゲット変数を分割します。
X_train_original, y_train = split_label(train_data, target_feature)
X_test_original, y_test = split_label(test_data, target_feature)
# NumPy フォーマットに変換します。
y_train = y_train[target_feature].to_numpy()
y_test = y_test[target_feature].to_numpy()
# テストサンプルを定義します。
test_data_sample = test_data.sample(n=500, random_state=5)独自のデータセットをロードすることもできます。次のコマンドは、CSV 形式のデータセットをロードする方法を示しています。
import pandas as pd
# CSV 形式で独自のデータセットをロードします。
# pandas を使用して CSV ファイルを読み取ります。
try:
data = pd.read_csv(filename)
except:
passステップ5:モデルのトレーニング
この例では、Scikit-learn を使用してデータトレーニングパイプラインを構築し、バイナリ分類モデルをトレーニングします。
# scikit-learn のバージョンに基づいて ohe_params パラメーターを定義します。
if version.parse(sklearn.__version__) < version.parse('1.2'):
ohe_params = {"sparse": False}
else:
ohe_params = {"sparse_output": False}
# 特徴量変換のための分類パイプラインを定義します。入力パラメーター X はトレーニングデータを表します。
def create_classification_pipeline(X):
pipe_cfg = {
'num_cols': X.dtypes[X.dtypes == 'int64'].index.values.tolist(),
'cat_cols': X.dtypes[X.dtypes == 'object'].index.values.tolist(),
}
num_pipe = Pipeline([
('num_imputer', SimpleImputer(strategy='median')),
('num_scaler', StandardScaler())
])
cat_pipe = Pipeline([
('cat_imputer', SimpleImputer(strategy='constant', fill_value='?')),
('cat_encoder', OneHotEncoder(handle_unknown='ignore', **ohe_params))
])
feat_pipe = ColumnTransformer([
('num_pipe', num_pipe, pipe_cfg['num_cols']),
('cat_pipe', cat_pipe, pipe_cfg['cat_cols'])
])
pipeline = Pipeline(steps=[('preprocessor', feat_pipe),
('model', LGBMClassifier(random_state=0))])
return pipeline
# 分類モデルのトレーニングパイプラインを作成します。
pipeline = create_classification_pipeline(X_train_original)
# モデルをトレーニングします。
model = pipeline.fit(X_train_original, y_train)ステップ6:責任ある AI コンポーネントの追加
次のスクリプトを実行して、エラー分析コンポーネントを責任ある AI に追加し、rai_insights を使用して計算を実行します。
# RAI ダッシュボードコンポーネントをインポートします。
from raiwidgets import ResponsibleAIDashboard
from responsibleai import RAIInsights
# RAIInsights オブジェクトを定義します。
from responsibleai.feature_metadata import FeatureMetadata
feature_metadata = FeatureMetadata(categorical_features=categorical_features, dropped_features=[])
rai_insights = RAIInsights(model, train_data, test_data_sample, target_feature, 'classification',
feature_metadata=feature_metadata)
# エラー分析コンポーネントを追加します。
rai_insights.error_analysis.add()
# RAI 計算を実行します。
rai_insights.compute()ステップ7:責任ある AI ダッシュボードの作成
フィルターを適用してさまざまなコホートを作成し、特定のデータセグメントを分析します。例は次のとおりです。
年齢が 65 未満で、週あたりの労働時間が 40 を超える。
配偶者の状況が「未婚」または「離婚」。
インデックスが 20 未満。
予測された Y が >50K。
真の Y が >50K。
ResponsibleAIDashboardをインポートし、responsible-ai-toolbox を使用してモデルを分析します。
from raiutils.cohort import Cohort, CohortFilter, CohortFilterMethods
import os
from urllib.parse import urlparse
# 年齢が 65 未満で、週あたりの労働時間が 40 を超える。
cohort_filter_age = CohortFilter(
method=CohortFilterMethods.METHOD_LESS,
arg=[65],
column='age')
cohort_filter_hours_per_week = CohortFilter(
method=CohortFilterMethods.METHOD_GREATER,
arg=[40],
column='hours-per-week')
user_cohort_age_and_hours_per_week = Cohort(name='Cohort Age and Hours-Per-Week')
user_cohort_age_and_hours_per_week.add_cohort_filter(cohort_filter_age)
user_cohort_age_and_hours_per_week.add_cohort_filter(cohort_filter_hours_per_week)
# 配偶者の状況が「未婚」または「離婚」。
cohort_filter_marital_status = CohortFilter(
method=CohortFilterMethods.METHOD_INCLUDES,
arg=["Never-married", "Divorced"],
column='marital-status')
user_cohort_marital_status = Cohort(name='Cohort Marital-Status')
user_cohort_marital_status.add_cohort_filter(cohort_filter_marital_status)
# インデックスが 20 未満。
cohort_filter_index = CohortFilter(
method=CohortFilterMethods.METHOD_LESS,
arg=[20],
column='Index')
user_cohort_index = Cohort(name='Cohort Index')
user_cohort_index.add_cohort_filter(cohort_filter_index)
# 予測された Y が >50K。
cohort_filter_predicted_y = CohortFilter(
method=CohortFilterMethods.METHOD_INCLUDES,
arg=['>50K'],
column='Predicted Y')
user_cohort_predicted_y = Cohort(name='Cohort Predicted Y')
user_cohort_predicted_y.add_cohort_filter(cohort_filter_predicted_y)
# 真の Y が >50K。
cohort_filter_true_y = CohortFilter(
method=CohortFilterMethods.METHOD_INCLUDES,
arg=['>50K'],
column='True Y')
user_cohort_true_y = Cohort(name='Cohort True Y')
user_cohort_true_y.add_cohort_filter(cohort_filter_true_y)
cohort_list = [user_cohort_age_and_hours_per_week,
user_cohort_marital_status,
user_cohort_index,
user_cohort_predicted_y,
user_cohort_true_y]
# 責任ある AI ダッシュボードを作成します。
metric_frame_tf = ResponsibleAIDashboard(rai_insights, cohort_list=cohort_list, feature_flights="dataBalanceExperience")
# リダイレクト用の URL を設定します。
metric_frame_tf.config['baseUrl'] = 'https://{}-proxy-{}.dsw-gateway-{}.data.aliyun.com'.format(
os.environ.get('JUPYTER_NAME').replace("dsw-",""),
urlparse(metric_frame_tf.config['baseUrl']).port,
os.environ.get('dsw_region') )ステップ8:エラー分析の表示
URL をクリックして、責任ある AI ダッシュボードを開きます。

エラー分析の表示:
ツリーマップ

[Tree Map] をクリックします。[Select metric] ドロップダウンリストから [Error rate] を選択して、エラー分析を実行します。ツリービューは、モデルの特徴量の値に基づいてデータを二分木に分割します。たとえば、このツリーのルートノードの下にある 2 つのブランチは、以下を表します。
marital-status == Married-civ-spouse(54/224)
marital-status != Married-civ-spouse(18/276)
この例には 500 のサンプルが含まれており、72 の予測エラーがあるため、エラー率は 14.4% (72/500) です。二分木の各ノードには、ブランチの条件を満たすデータポイントの総数、予測エラーの数、およびエラー率が表示されます。
赤いノードに注目します。赤の色合いが濃いほど、エラー率が高いことを示します。
この例では、最も濃い赤色のリーフノードをクリックします。これにより、モデルの予測エラー率が、次のすべての条件を満たすデータに対して 43.40% にも達することがわかります。
marital-status == Married-civ-spouse
fnlwgt <= 207583
hours-per-week > 40.5
ヒートマップ

[ヒートマップ] をクリックしてヒートマップビューに切り替えます。[メトリックの選択] ドロップダウンリストから、[エラーレート] を選択します。
(オプション) パラメーターを構成します。
分位数ビニング:連続変数を複数の間隔に分割する方法で、各間隔には同じ数のデータポイントが含まれます。
オフに設定すると、デフォルトの均一ビニング戦略が使用され、各間隔の長さが同じになります。
オンに設定すると、分位数ビニングが有効になります。各間隔には同じ数のデータポイントが含まれるため、間隔全体でデータが均等に分布します。
ビニングのしきい値:データをビニングするための間隔の数。この例では、デフォルトは 8 で、
ageとhours-per-weekを 8 つの等しい間隔に分割します。
ヒートマップで、クロス分析のために 2 つの入力特徴量を選択します。この例では、
ageとhours-per-weekを使用します。赤いセルに注目します。赤の色合いが濃いほど、エラー率が高いことを示します。
2 つの特徴量が次の範囲に該当する場合、エラー率は最も高くなります (最大 100%)。
age[71.8,80.9], hours-per-week[39.0,51.0]
age[44.4,53.5], hours-per-week[75.0,87.0]
age[16.9,26.1], hours-per-week[63.0,75.0]
...