全部產品
Search
文件中心

Platform For AI:Responsible AI-公平性分析

更新時間:Jul 13, 2024

Responsible AI對人工智慧模型(AI模型)開發人員和企業管理者十分重要,Responsible AI貫穿在AI模型的開發、訓練、微調、評估、部署等環節,是保障AI模型安全、穩定、公平、符合社會道德的重要方法。PAI已支援使用者在DSW中整合Responsible AI的相關工具對產出的AI模型進行公平性分析、錯誤分析及可解釋性分析。

原理介紹

公平性分析是Responsible AI的一部分,它專註於識別和糾正AI系統中的偏見,確保模型不會受到某一不合理因素的影響,從而保證AI系統對所有人都是公平的。公平性分析的核心原理如下:

  • 避免偏見:識別和減少資料和演算法中的偏見,確保AI系統不會因性別、種族、年齡等個人特徵而導致不公平的決策。

  • 代表性資料:使用代表性資料集練習AI模型,這樣模型就可以準確地代表和服務於所有使用者群體,同時確保少數群體不會被邊緣化。

  • 透明度和解釋性:增加AI系統的透明度,通過可解釋的AI技術,讓終端使用者和決策者理解AI決策過程和輸出的原因。

  • 持續監控和評估:定期監控和評估AI系統,以識別和糾正可能隨時間出現的任何不公平的偏差或做出的決策。

  • 多樣性和包容性:在AI系統的設計和開發過程中納入多樣性和包容性的觀念,確保從多種背景和觀點出發考慮問題,包括團隊構成的多樣性。

  • 合規性和道德原則:遵守相關的法律法規和道德標準,包括對人權的尊重,以及確保AI應用不會造成傷害或不公。

本文以“評估一個預測年度營收是否大於50K的模型在性別、種族因素的公平性”為例,介紹了如何在阿里雲PAI的DSW產品中使用responsible-ai-toolbox對模型進行公平性分析。

準備環境和資源

  • DSW執行個體:如果您還沒有DSW執行個體,請參見建立DSW執行個體。推薦配置如下:

    • 推薦執行個體規格:ecs.gn6v-c8g1.2xlarge

    • 鏡像選擇:建議使用Python3.9及以上版本。本文選擇的官方鏡像為:tensorflow-pytorch-develop:2.14-pytorch2.1-gpu-py311-cu118-ubuntu22.04

    • 模型選擇:responsible-ai-toolbox支援Sklearn、PyTorch和TensorFlow架構的迴歸和二分類模型。

  • 訓練資料集:推薦您使用自己的資料集;如果您需要使用樣本資料集,請按步驟三:準備資料集操作。

  • 演算法模型:推薦您使用自己的演算法模型;如果您需要使用樣本演算法模型,請按步驟五:模型訓練操作。

步驟一:進入DSW Gallery

  1. 登入PAI控制台

  2. 在頂部左上方根據實際情況選擇地區。

  3. 在左側導覽列選擇巨量資料與AI體驗 > DSW Gallery,搜尋“Responsible AI-公平性分析”並單擊對應卡片上的在阿里雲DSW開啟

  4. 選擇AI工作空間DSW執行個體,單擊確定,系統會開啟“Responsible AI-公平性分析”Notebook案例。

步驟二:匯入依賴包

安裝responsible-ai-toolbox的依賴包(raiwidgets),用於後續的評估。

!pip install raiwidgets==0.34.1

步驟三:準備資料集

您可以直接執行以下指令碼載入OpenML的1590資料集,以完成本文的樣本。

from raiutils.common.retries import retry_function
from sklearn.datasets import fetch_openml

class FetchOpenml(object):
    def __init__(self):
        pass
    # 擷取 data_id = 1590的OpenML資料集
    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

# 載入自己的資料集,csv 格式資料集
# 使用pandas讀取CSV檔案
data = pd.read_csv(filename)

步驟四:資料預先處理

擷取特徵變數和目標變數

目標變數是指模型預測的真實結果,特徵變數是指每條執行個體資料中目標變數以外的變數。在本文樣本中,目標變數是“class”,特徵變數是“sex、race、age……”:

  • class:年度營收是否大於50K

  • sex:性別

  • race:種族

  • age:年齡

執行以下指令碼,讀取資料到X_raw,並查看一部分樣本資料:

# 擷取特徵變數,不包括目標變數。
X_raw = data.data
# 展示特徵變數的前5行資料,不包括目標變數。
X_raw.head(5)

執行以下指令碼,設定目標變數的值,並查看一部分樣本資料。其中,“1”表示收入>50K,“0”表示收入≤50K。

from sklearn.preprocessing import LabelEncoder

# 轉換目標變數,轉換為二分類目標
# data.target 是目標變數是“class”
y_true = (data.target == '>50K') * 1
y_true = LabelEncoder().fit_transform(y_true)

import matplotlib.pyplot as plt
import numpy as np

# 查看目標變數的分布
counts = np.bincount(y_true)
classes = ['<=50K', '>50K']
plt.bar(classes, counts)

擷取特徵敏感特徵

執行以下指令碼,將性別(sex)、種族(race)設定為敏感特徵,並查看一部分樣本資料。responsible-ai-toolbox會評估該模型的推理結果是否因為這兩個敏感特徵產生偏見。在實際使用時,您可以按業務需要設定敏感特徵。

# 定義“性別”和“種族”為敏感資訊
# 首先從資料集中選取敏感資訊相關的列,組成新的Dataframe `sensitive_features`
sensitive_features = X_raw[['sex','race']]
sensitive_features.head(5)

執行以下指令碼,刪除X_raw中的敏感特徵及資料,並查看刪除後的樣本資料。

# 將特徵變數中的敏感特徵刪除
X = X_raw.drop(labels=['sex', 'race'],axis = 1)
X.head(5)

特徵編碼和標準化

執行以下指令碼,對資料進行標準化處理,轉換為適合responsible-ai-toolbox使用的格式。

import pandas as pd
from sklearn.preprocessing import StandardScaler

# one-hot 編碼
X = pd.get_dummies(X)

# 對資料集X進行特徵標準化(scaling)
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

# 按照`test_size`比例,將特徵變數X和目標變數y劃分為訓練集和測試集
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)

# 使用相同的隨機種子,將敏感特徵劃分為訓練集和測試集,確保與上述劃分保持一致
sensitive_features_train, sensitive_features_test = \
    train_test_split(sensitive_features, test_size=0.2, random_state=0, stratify=y_true)

分別查看訓練資料集、測試資料集的資料量。

print("訓練資料集的資料量:", len(X_train))
print("測試資料集的資料量:", len(X_test))

分別重設訓練資料集、測試資料集的索引。

# 重設 DataFrame 的索引,避免索引錯誤問題
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)

步驟五:模型訓練

本文樣本中,基於Sklearn使用訓練資料訓練一個羅吉斯迴歸模型。

Sklearn

from sklearn.linear_model import LogisticRegression

# 建立羅吉斯迴歸模型
sk_model = LogisticRegression(solver='liblinear', fit_intercept=True)
# 模型訓練
sk_model.fit(X_train, y_train)

PyTorch

import torch
import torch.nn as nn
import torch.optim as optim

# 定義羅吉斯迴歸模型
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

# 執行個體化模型
input_size = X_train.shape[1]
pt_model = LogisticRegression(input_size)

# 損失函數和最佳化器
criterion = nn.BCELoss()
optimizer = optim.SGD(pt_model.parameters(), lr=5e-5)

# 訓練模型
num_epochs = 1
X_train_pt = X_train
y_train_pt = y_train
for epoch in range(num_epochs):
    # 前向傳播
    # DataFrame 轉換為 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()
    # ndarray 轉換為 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)

    # 反向傳播和最佳化
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

TensorFlow

import tensorflow as tf
from tensorflow.keras import layers

# 定義羅吉斯迴歸模型
tf_model = tf.keras.Sequential([
    layers.Dense(units=1, input_shape=(X_train.shape[-1],), activation='sigmoid')
])

# 編譯模型,使用二元交叉熵損失和隨機梯度下降最佳化器
tf_model.compile(optimizer='sgd', loss='binary_crossentropy', metrics=['accuracy'])

# 訓練模型
tf_model.fit(X_train, y_train, epochs=1, batch_size=32, verbose=0)

步驟六:模型評估

引入FairnessDashboard,使用responsible-ai-toolbox載入測試資料集進行結果預測,產生公平性評估報告。

FairnessDashboard按照敏感變數分類預測結果和真實結果,並通過對比分析預測結果和真實結果,得到在不同敏感變數情況下的模型預測情況。

以敏感特徵值“sex”為例,FairnessDashboard按照“sex”將對應的預測結果(y_pred)和真實結果(y_test)進行分類,在“sex”分類中分別計算“Male”和“Female”的選擇率、精確度等資訊並進行對比。

本文樣本中,基於Sklearn對模型進行評估:

Sklearn

from raiwidgets import FairnessDashboard
import os
from urllib.parse import urlparse
# 根據測試資料集進行預測結果
y_pred_sk = sk_model.predict(X_test)

# 使用 responsible-ai-toolbox  計算每個敏感群體的資料資訊
metric_frame_sk = FairnessDashboard(sensitive_features=sensitive_features_test,
                  y_true=y_test,
                  y_pred=y_pred_sk, locale = 'zh-Hans')

# 設定URL跳轉連結
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
# 測試模型並評估公平性
pt_model.eval()  # 設定模型為評估模式
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()

# 使用 responsible-ai-toolbox  計算每個敏感群體的資料資訊
metric_frame_pt = FairnessDashboard(sensitive_features=sensitive_features_test,
                           y_true=y_test,
                           y_pred=y_pred_pt.flatten().round(),locale='zh-Hans')

# 設定URL跳轉連結
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
# 測試模型並評估公平性
y_pred_tf = tf_model.predict(X_test).flatten()

# 使用 responsible-ai-toolbox  計算每個敏感群體的資料資訊
metric_frame_tf = FairnessDashboard(
                           sensitive_features=sensitive_features_test,
                           y_true=y_test,
                           y_pred=y_pred_tf.round(),locale='zh-Hans')

# 設定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') )
print(metric_frame_tf.config['baseUrl'])

關鍵參數說明:

  • sensitive_features:敏感屬性。

  • y_true:訓練資料集提供的真實結果。

  • y_pred:模型預測的結果。

  • locale(可選):評估面板顯示語言類型,支援簡體中文(“zh-Hans”)和繁體中文(“zh-Hant”),預設為英語(“en”)。

步驟七:查看評估報告

評估完成後,單擊URL,查看完整的評估報告。

image

公平性儀表板頁面單擊開始使用,按照以下參數依次設定敏感特徵、效能指標、公平性指標,查看模型針對敏感特徵“sex”或“race”的指標資料差異。

敏感特徵為“sex”

  • 敏感特徵:sex

  • 效能指標:Accuracy

  • 公平性指標:Demographic parity difference

image

  • Accuracy:精確度,是指模型正確預測的樣本數佔總樣本數的比例。模型輸出男性個人年度營收的準確度(81.6%)低於女性個人年度營收的準確度(93.1%),但是兩者的準確度與模型總體準確度(85.4%)都比較接近。

  • Selection rate:選擇率,是指模型輸出“好”的目標變數的機率,這裡“好”的目標變數是個人年度營收>50K。模型輸出男性個人年度營收>50K的機率(25.7%)大於女性個人年度營收>50K的機率(7.36%),並且模型輸出女性個人年度營收>50K的機率(7.36%)遠低於個人年度營收>50K的總體機率(19.6%)。

  • Demographic parity difference:人口統計公平性差異,是指不同受保護群體之間,在指定的敏感屬性下獲得積極預測結果的機率差異。這個值越接近0,意味著群體間的偏差越小。模型總體的人口統計公平性差異為18.3%。

敏感特徵為“race”

  • 敏感特徵:race

  • 效能指標:Accuracy

  • 公平性指標:Demographic parity difference

image

  • Accuracy:精確度,是指模型正確預測的樣本數佔總樣本數的比例。模型輸出“White”和“Asian-Pac-Islander”個人年度營收的準確度(84.9%和79.1%)低於“Black”、“Other”和“Amer-Indian-Eskimo”個人年度營收的準確度(90.9%、90.8%和91.9%),但是所有敏感特徵人群的準確度與模型總體準確度(85.4%)都比較接近。

  • Selection rate:選擇率,是指模型輸出“好”的目標變數的機率,這裡“好”的目標變數是個人年度營收>50K。模型輸出“White”和“Asian-Pac-Islander”個人年度營收>50K的選擇率(21%和23.9%)大於“Black”、“Other”和“Amer-Indian-Eskimo”個人年度營收>50K的選擇率 (8.34%、10.3%和8.14%),並且“Black”、“Other”和“Amer-Indian-Eskimo”個人年度營收>50K的選擇率(8.34%、10.3%和8.14%)遠低於個人年度營收>50K的總體選擇率(19.6%)。

  • Demographic parity difference:人口統計公平性差異,是指不同受保護群體之間,在指定的敏感屬性下獲得積極預測結果的機率差異。這個值越接近0,意味著群體間的偏差越小。模型總體的人口統計公平性差異為15.8%。