責任あるAIは、AIモデルの開発者とエンタープライズ顧客にとって非常に重要です。 責任あるAIは、AIモデルが安全で、安定し、公正で、社会的に倫理的であることを保証するために、モデル開発、トレーニング、微調整、評価、および展開において重要な役割を果たします。 Alibaba Cloud Platform for AI (PAI) のData Science Workshop (DSW) を使用すると、責任あるAIツールを統合して、生成されたAIモデルの公平性分析、エラー分析、および解釈可能性分析を実行できます。
仕組み
公平性分析により、モデルの出力に偏りがなく、不当な要因の影響を受けないことが保証されます。 次のセクションでは、公平性分析のコア原則について説明します。
バイアスの回避: 性別、人種、年齢などの個人的な特性に基づいてAIシステムが不当な決定を下さないように、データとアルゴリズムのバイアスを特定して低減します。
代表的なデータ: AIモデルを代表的なデータセットと一緒にトレーニングして、少数グループを疎外することなく、モデルがすべてのユーザーグループを正確に表してサービスを提供できるようにします。
透明性と説明性: AIシステムの透明性を高め、エンドユーザーと意思決定者が説明可能なAIテクノロジーを使用してAIの意思決定プロセスと出力を理解できるようにします。
継続的な監視と評価: AIシステムを定期的に監視および評価して、発生する可能性のある不公正なバイアスや決定を特定して修正します。
多様性とインクルージョン: 多様性とインクルージョンの概念をAIシステムの設計と開発に組み込み、チーム構成の多様性を含む複数の背景と視点から問題を検討するようにします。
コンプライアンスと倫理原則: AIアプリケーションが危害や不正を引き起こさないようにするために、人権の尊重を含む関連する法律、規制、および倫理基準を遵守します。
このトピックでは、担当ツールボックスを使用して、DSWのモデルの公平性分析を実行する方法について説明します。 このトピックでは、年収が50Kを超えるかどうかを予測するモデルの公平性を、性別と人種の観点から評価します。
環境とリソースの準備
DSWインスタンス: DSWインスタンスがない場合は、DSWインスタンスを作成します。 詳細については、「DSWインスタンスの作成」をご参照ください。 次の設定を使用することを推奨します。
インスタンスタイプ: ecs.gn6v-c8g1.2xlarge
画像: Python3.9以降。 このトピックでは、使用される公式の画像はtensorflow-pytorch-developed: 2.14-pytorch2.1-gpu-py311-cu118-ubuntu22.04です。
モデル: 責任-ai-ツールボックスは、Sklearn、PyTorch、およびTensorFlowフレームワークに基づく回帰およびバイナリ分類モデルをサポートしています。
トレーニングデータセット: データセットを使用することを推奨します。 サンプルデータセットを使用する場合は、このトピックの「ステップ3 データセットを準備する」セクションをご参照ください。
アルゴリズムモデル: アルゴリズムモデルの使用を推奨します。 サンプルアルゴリズムモデルを使用する場合は、このトピックの「ステップ5: モデルのトレーニング」を参照してください。
ステップ1: DSWギャラリーに移動
PAI コンソールにログインします。
左上隅で、ビジネス要件に基づいてリージョンを選択します。
左側のナビゲーションウィンドウで、[クイックスタート] > [ノートブックギャラリー] を選択します。 責任あるAIの公平性を検索し、[DSWで開く] をクリックします。
AIワークスペースとDSWインスタンスを選択し、[ノートブックを開く] をクリックします。 システムはResponsible AI-fairness分析ノートブックを開きます。
ステップ2: 依存関係パッケージのインポート
その後の評価のために、責任のある-ai-toolbox依存関係パッケージ (raiwidgets) をインストールします。
!pip install raiwidgets==0.34.1
手順3: データセットの準備
この例では、OpenMLデータセット1590が使用されています。 次のスクリプトを直接実行して、OpenML 1590データセットをロードできます。
from raiutils.common.retries import retry_function
from sklearn.datasets import fetch_openml
class FetchOpenml(object):
def __init__(self):
pass
# Obtain the OpenML dataset whose data ID is 1590 .
def fetch(self):
return fetch_openml(data_id=1590, as_frame=True)
fetcher = FetchOpenml()
action_name = "Dataset download"
err_msg = "Failed to download openml dataset"
max_retries = 5
retry_delay = 60
data = retry_function(fetcher.fetch, action_name, err_msg,
max_retries=max_retries,
retry_delay=retry_delay)
独自のデータセットを読み込むこともできます。 次のセクションでは、CSV形式のデータセットのサンプルコマンドを示します。
import pandas as pd
# Load your dataset in the CSV format.
# Use pandas to read CSV files.
data = pd.read_csv(filename)
ステップ4: データの前処理
フィーチャ変数とターゲット変数の取得
ターゲット変数は、モデルによって予測された実際の結果を指し、特徴変数は、各インスタンスデータにおけるターゲット変数以外の変数を指す。 この例では、ターゲット変数はクラスであり、特徴変数は性別、人種、年齢です。
クラス: 年収が50Kを超えるかどうか
セックス: 性別
レース: レース
年齢: 年齢
次のスクリプトを実行して、データをX_raw
まで読み取り、サンプルデータの一部を表示します。
# Obtain the feature variables, excluding the target variable.
X_raw = data.data
# Display the first five rows of data of the feature variables, excluding the target variable.
X_raw.head(5)
次のスクリプトを実行して、ターゲット変数の値を設定し、サンプルデータの一部を表示します。 1の値は、50Kを超える収入を示します。 0の値は、50K以下の収入を示します。
from sklearn.preprocessing import LabelEncoder
# Convert the target variable to a binary classification target.
# data.target is the target variable class.
y_true = (data.target == '>50K') * 1
y_true = LabelEncoder().fit_transform(y_true)
import matplotlib.pyplot as plt
import numpy as np
# View the distribution of the target variable.
counts = np.bincount(y_true)
classes = ['<=50K', '>50K']
plt.bar(classes, counts)
機密機能の取得
次のスクリプトを実行して、機密機能として性別と人種を指定し、サンプルデータの一部を表示します。 このようにして、担当ツールボックスは、モデルの推論結果が2つの機密機能のために偏っているかどうかを評価します。 実際のシナリオでは、ビジネス要件に基づいて機密機能を設定できます。
# Specify sex and race as sensitive information.
# Select the columns related to sensitive information from the dataset to form a new DataFrame named `sensitive_features`
sensitive_features = X_raw[['sex','race']]
sensitive_features.head(5)
次のスクリプトを実行して、X_raw
から機密機能とデータを削除し、削除後のサンプルデータを表示します。
# Remove sensitive features from feature variables.
X = X_raw.drop(labels=['sex', 'race'],axis = 1)
X.head(5)
機能コーディングと標準化
次のスクリプトを実行してデータを標準化し、担当ツールボックスに適した形式にデータを変換します。
import pandas as pd
from sklearn.preprocessing import StandardScaler
One-hot encoding
X = pd.get_dummies(X)
# Standardize the feature variables of dataset X
sc = StandardScaler()
X_scaled = sc.fit_transform(X)
X_scaled = pd.DataFrame(X_scaled, columns=X.columns)
X_scaled.head(5)
トレーニングとテストデータの分割
次のスクリプトを実行して、20% のデータをテストデータセットとして分割します。 残りのデータは、訓練データセットとして使用される。
from sklearn.model_selection import train_test_split
# Split the feature variable X and target variable y to training and testing datasets based on the ratio `test_size`.
X_train, X_test, y_train, y_test = \
train_test_split(X_scaled, y_true, test_size=0.2, random_state=0, stratify=y_true)
# Split the sensitive features to training and testing datasets by using the same random seed. Make sure that the split ratio is the same as the previous step.
sensitive_features_train, sensitive_features_test = \
train_test_split(sensitive_features, test_size=0.2, random_state=0, stratify=y_true)
トレーニングデータセットとテストデータセットのデータサイズを確認します。
print("Size of the training dataset:", len(X_train))
print("Size of the test dataset:", len(X_test))
トレーニングデータセットとテストデータセットのインデックスをリセットします。
# Reset the index of DataFrame to prevent index error.
X_train = X_train.reset_index(drop=True)
sensitive_features_train = sensitive_features_train.reset_index(drop=True)
X_test = X_test.reset_index(drop=True)
sensitive_features_test = sensitive_features_test.reset_index(drop=True)
ステップ5: モデルのトレーニング
この例では、SkLearnを使用して、トレーニングデータに基づいてロジスティック回帰モデルをトレーニングします。
Sklearn
from sklearn.linear_model import LogisticRegression
# Create a logistic regression model.
sk_model = LogisticRegression(solver='liblinear', fit_intercept=True)
# Train the model.
sk_model.fit(X_train, y_train)
PyTorch
import torch
import torch.nn as nn
import torch.optim as optim
# Define the logistic regression model.
class LogisticRegression(nn.Module):
def __init__(self, input_size):
super(LogisticRegression, self).__init__()
self.linear = nn.Linear(input_size, 1)
def forward(self, x):
outputs = torch.sigmoid(self.linear(x))
return outputs
# Instantiate the model.
input_size = X_train.shape[1]
pt_model = LogisticRegression(input_size)
# Loss functions and optimizer.
criterion = nn.BCELoss()
optimizer = optim.SGD(pt_model.parameters(), lr=5e-5)
# Train the model.
num_epochs = 1
X_train_pt = X_train
y_train_pt = y_train
for epoch in range(num_epochs):
# Forward propagation.
# Convert DataFrame to tensor.
if isinstance(X_train_pt, pd.DataFrame):
X_train_pt = torch.tensor(X_train_pt.values)
X_train_pt = X_train_pt.float()
outputs = pt_model(X_train_pt)
outputs = outputs.squeeze()
# Convert ndarray to tensor.
if isinstance(y_train_pt, np.ndarray):
y_train_pt = torch.from_numpy(y_train_pt)
y_train_pt = y_train_pt.float()
loss = criterion(outputs, y_train_pt)
# Back propagation and optimization.
optimizer.zero_grad()
loss.backward()
optimizer.step()
TensorFlow
import tensorflow as tf
from tensorflow.keras import layers
# Define the logistic regression model
tf_model = tf.keras.Sequential([
layers.Dense(units=1, input_shape=(X_train.shape[-1],), activation='sigmoid')
])
# Compile the model by using binary cross-entropy loss and stochastic gradient descent optimizer.
tf_model.compile(optimizer='sgd', loss='binary_crossentropy', metrics=['accuracy'])
# Train the model.
tf_model.fit(X_train, y_train, epochs=1, batch_size=32, verbose=0)
ステップ6: モデルの評価
FairnessDashboardを導入し、責任あるツールボックスを使用して、テストデータに基づいて結果を予測し、公平性評価レポートを生成します。
FairnessDashboardは、敏感な変数に基づいて予測結果と実際の結果を分類し、予測結果と実際の結果を比較分析して、異なる敏感な変数に基づいてモデル予測を評価します。
たとえば、性別は機密機能として使用されます。 FairnessDashboardは、性別に基づいて対応する予測結果 (y_pred) と実際の結果 (y_test) を分類し、性別カテゴリの男性と女性の選択率、精度、およびその他の情報をそれぞれ計算して比較します。
この例では、次のスクリプトを実行してモデルを評価します。
Sklearn
from raiwidgets import FairnessDashboard
import os
from urllib.parse import urlparse
# Predict results based on the test dataset.
y_pred_sk = sk_model.predict(X_test)
# Use responsible-ai-toolbox to calculate data information for each sensitive group.
metric_frame_sk = FairnessDashboard(sensitive_features=sensitive_features_test,
y_true=y_test,
y_pred=y_pred_sk, locale = 'zh-Hans')
# Specify the URL link.
metric_frame_sk.config['baseUrl'] = 'https://{}-proxy-{}.dsw-gateway-{}.data.aliyun.com'.format(
os.environ.get('JUPYTER_NAME').replace("dsw-",""),
urlparse(metric_frame_sk.config['baseUrl']).port,
os.environ.get('dsw_region') )
print(metric_frame_sk.config['baseUrl'])
PyTorch
from raiwidgets import FairnessDashboard
import torch
import os
from urllib.parse import urlparse
# Test the model and evaluate model fairness.
pt_model.eval() # Set the model to the evaluation mode.
X_test_pt = X_test
with torch.no_grad():
X_test_pt = torch.tensor(X_test_pt.values)
X_test_pt = X_test_pt.float()
y_pred_pt = pt_model(X_test_pt).numpy()
# Use responsible-ai-toolbox to calculate data information for each sensitive group.
metric_frame_pt = FairnessDashboard(sensitive_features=sensitive_features_test,
y_true=y_test,
y_pred=y_pred_pt.flatten().round(),locale='zh-Hans')
# Specify the URL link.
metric_frame_pt.config['baseUrl'] = 'https://{}-proxy-{}.dsw-gateway-{}.data.aliyun.com'.format(
os.environ.get('JUPYTER_NAME').replace("dsw-",""),
urlparse(metric_frame_pt.config['baseUrl']).port,
os.environ.get('dsw_region') )
print(metric_frame_pt.config['baseUrl'])
TensorFlow
from raiwidgets import FairnessDashboard
import os
from urllib.parse import urlparse
# Test the model and evaluate model fairness.
y_pred_tf = tf_model.predict(X_test).flatten()
# Use responsible-ai-toolbox to calculate data information for each sensitive group.
metric_frame_tf = FairnessDashboard(
sensitive_features=sensitive_features_test,
y_true=y_test,
y_pred=y_pred_tf.round(),locale='zh-Hans')
# Specify the URL link.
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') )
print(metric_frame_tf.config['baseUrl'])
パラメーター:
sensitive_features: 機密機能。
y_true: トレーニングデータセットによって生成された実際の結果。
y_pred: モデルの予測結果。
locale: オプション。 評価パネルの表示言語。 有効な値: 簡体字中国語 (zh-Hans) 、繁体字中国語 (zh-Hant) 、および英語 (en) 。 デフォルト値: en。
ステップ7: 評価レポートを表示
評価が完了したら、URLをクリックして、完全な評価レポートを表示します。
[FairnessDashboard] ページで、[開始] をクリックします。 モデルのメトリックデータの違いを表示するには、次のパラメーターに基づいて、機密機能、パフォーマンスメトリック、および公平性メトリックを順番に設定します。
敏感な特徴: セックス
敏感な特徴: セックス
パフォーマンスメトリック: 精度
公平性の指標: 人口統計学的パリティの違い
精度: サンプルの総数に対する正しく予測されたサンプルの割合。 男性の年収に関するモデル予測の精度 (81.6%) は、女性の年収に関する精度 (93.1%) よりも低い。 しかしながら、両方の精度は、モデル (85.4%) の全体的な精度に比較的近い。
選択率: モデルが予想通りにターゲット変数を生成する確率。 この場合、期待される目標変数は、50Kを超える年収である。 50K (25.7%) を超える年収を有する男性に対するモデル予測の選択率は、50K (7.36%) を超える年収を有する女性に対する予測よりも大きい。 50K (7.36%) を超える年収を持つ女性の選択率は、モデルの全体的な選択率 (19.6%) よりもはるかに低いです。
人口学的パリティ差: 所与の機密属性の下での異なる保護されたグループ間の肯定的な予測結果の確率の差。 値が0に近いほど、グループ間の偏りが小さいことを示す。 モデルの全体的な人口学的パリティ差は18.3% である。
敏感な特徴: レース
敏感な特徴: レース
パフォーマンスメトリック: 精度
公平性の指標: 人口統計学的パリティの違い
精度: サンプルの総数に対する正しく予測されたサンプルの割合。 白人とアジア・パック・アイランダーの個人 (84.9% と79.1%) の年収に関するモデル予測の精度は、黒人、その他、およびアメル・インディアン・エスキモーの個人 (90.9% 、90.8% 、91.9%) の精度よりも低くなっています。 しかしながら、全ての敏感な特徴群の精度は、モデル (85.4%) の全体的な精度に比較的近い。
選択率: モデルが予想通りにターゲット変数を生成する確率。 この場合、期待される目標変数は、50Kを超える年収である。 白人およびアジア・パック・アイランダー個体 (21% および23.9%) の選択率は、黒人、その他、およびアメル・インディアン・エスキモー個体 (8.34% 、10.3% 、および8.14%) の選択率よりも高い。 黒人、その他、およびアメール-インディアン-エスキモーの個人 (8.34% 、10.3% 、および8.14%) の選択率は、モデルの全体的な選択率 (19.6%) よりもはるかに低くなっています。
人口学的パリティ差: 所与の機密属性の下での異なる保護されたグループ間の肯定的な予測結果の確率の差。 値が0に近いほど、グループ間の偏りが小さいことを示す。 モデルの全体的な人口学的パリティ差は18.3% である。