Responsible AI-公平性分析
Responsible AI對人工智能模型(AI模型)開發(fā)者和企業(yè)管理者十分重要,Responsible AI貫穿在AI模型的開發(fā)、訓(xùn)練、微調(diào)、評(píng)估、部署等環(huán)節(jié),是保障AI模型安全、穩(wěn)定、公平、符合社會(huì)道德的重要方法。PAI已支持用戶在DSW中集成Responsible AI的相關(guān)工具對產(chǎn)出的AI模型進(jìn)行公平性分析、錯(cuò)誤分析及可解釋性分析。
原理介紹
公平性分析是Responsible AI的一部分,它專注于識(shí)別和糾正AI系統(tǒng)中的偏見,確保模型不會(huì)受到某一不合理因素的影響,從而保證AI系統(tǒng)對所有人都是公平的。公平性分析的核心原理如下:
避免偏見:識(shí)別和減少數(shù)據(jù)和算法中的偏見,確保AI系統(tǒng)不會(huì)因性別、種族、年齡等個(gè)人特征而導(dǎo)致不公平的決策。
代表性數(shù)據(jù):使用代表性數(shù)據(jù)集練習(xí)AI模型,這樣模型就可以準(zhǔn)確地代表和服務(wù)于所有用戶群體,同時(shí)確保少數(shù)群體不會(huì)被邊緣化。
透明度和解釋性:增加AI系統(tǒng)的透明度,通過可解釋的AI技術(shù),讓最終用戶和決策者理解AI決策過程和輸出的原因。
持續(xù)監(jiān)控和評(píng)估:定期監(jiān)控和評(píng)估AI系統(tǒng),以識(shí)別和糾正可能隨時(shí)間出現(xiàn)的任何不公平的偏差或做出的決策。
多樣性和包容性:在AI系統(tǒng)的設(shè)計(jì)和開發(fā)過程中納入多樣性和包容性的觀念,確保從多種背景和觀點(diǎn)出發(fā)考慮問題,包括團(tuán)隊(duì)構(gòu)成的多樣性。
合規(guī)性和道德原則:遵守相關(guān)的法律法規(guī)和道德標(biāo)準(zhǔn),包括對人權(quán)的尊重,以及確保AI應(yīng)用不會(huì)造成傷害或不公。
本文以“評(píng)估一個(gè)預(yù)測年收入是否大于50K的模型在性別、種族因素的公平性”為例,介紹了如何在阿里云PAI的DSW產(chǎn)品中使用responsible-ai-toolbox對模型進(jìn)行公平性分析。
準(zhǔn)備環(huán)境和資源
DSW實(shí)例:如果您還沒有DSW實(shí)例,請參見創(chuàng)建DSW實(shí)例。推薦配置如下:
推薦實(shí)例規(guī)格:ecs.gn6v-c8g1.2xlarge
鏡像選擇:建議使用Python3.9及以上版本。本文選擇的官方鏡像為:tensorflow-pytorch-develop:2.14-pytorch2.1-gpu-py311-cu118-ubuntu22.04
模型選擇:responsible-ai-toolbox支持Sklearn、PyTorch和TensorFlow框架的回歸和二分類模型。
訓(xùn)練數(shù)據(jù)集:推薦您使用自己的數(shù)據(jù)集;如果您需要使用示例數(shù)據(jù)集,請按步驟三:準(zhǔn)備數(shù)據(jù)集操作。
算法模型:推薦您使用自己的算法模型;如果您需要使用示例算法模型,請按步驟五:模型訓(xùn)練操作。
步驟一:進(jìn)入DSW Gallery
登錄PAI控制臺(tái)。
在頂部左上角根據(jù)實(shí)際情況選擇地域。
在左側(cè)導(dǎo)航欄選擇大數(shù)據(jù)與AI體驗(yàn) > DSW Gallery,搜索“Responsible AI-公平性分析”并單擊對應(yīng)卡片上的在阿里云DSW打開。
選擇AI工作空間和DSW實(shí)例,單擊確定,系統(tǒng)會(huì)打開“Responsible AI-公平性分析”Notebook案例。
步驟二:導(dǎo)入依賴包
安裝responsible-ai-toolbox的依賴包(raiwidgets),用于后續(xù)的評(píng)估。
!pip install raiwidgets==0.34.1
步驟三:準(zhǔn)備數(shù)據(jù)集
您可以直接執(zhí)行以下腳本加載OpenML的1590數(shù)據(jù)集,以完成本文的示例。
from raiutils.common.retries import retry_function
from sklearn.datasets import fetch_openml
class FetchOpenml(object):
def __init__(self):
pass
# 獲取 data_id = 1590的OpenML數(shù)據(jù)集
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)
您也可以加載自己的數(shù)據(jù)集,CSV格式的數(shù)據(jù)集對應(yīng)的指令如下:
import pandas as pd
# 加載自己的數(shù)據(jù)集,csv 格式數(shù)據(jù)集
# 使用pandas讀取CSV文件
data = pd.read_csv(filename)
步驟四:數(shù)據(jù)預(yù)處理
獲取特征變量和目標(biāo)變量
目標(biāo)變量是指模型預(yù)測的真實(shí)結(jié)果,特征變量是指每條實(shí)例數(shù)據(jù)中目標(biāo)變量以外的變量。在本文示例中,目標(biāo)變量是“class”,特征變量是“sex、race、age……”:
class:年收入是否大于50K
sex:性別
race:種族
age:年齡
執(zhí)行以下腳本,讀取數(shù)據(jù)到X_raw
,并查看一部分示例數(shù)據(jù):
# 獲取特征變量,不包括目標(biāo)變量。
X_raw = data.data
# 展示特征變量的前5行數(shù)據(jù),不包括目標(biāo)變量。
X_raw.head(5)
執(zhí)行以下腳本,設(shè)置目標(biāo)變量的值,并查看一部分示例數(shù)據(jù)。其中,“1”表示收入>50K,“0”表示收入≤50K。
from sklearn.preprocessing import LabelEncoder
# 轉(zhuǎn)換目標(biāo)變量,轉(zhuǎn)換為二分類目標(biāo)
# data.target 是目標(biāo)變量是“class”
y_true = (data.target == '>50K') * 1
y_true = LabelEncoder().fit_transform(y_true)
import matplotlib.pyplot as plt
import numpy as np
# 查看目標(biāo)變量的分布
counts = np.bincount(y_true)
classes = ['<=50K', '>50K']
plt.bar(classes, counts)
獲取特征敏感特征
執(zhí)行以下腳本,將性別(sex)、種族(race)設(shè)置為敏感特征,并查看一部分示例數(shù)據(jù)。responsible-ai-toolbox會(huì)評(píng)估該模型的推理結(jié)果是否因?yàn)檫@兩個(gè)敏感特征產(chǎn)生偏見。在實(shí)際使用時(shí),您可以按業(yè)務(wù)需要設(shè)置敏感特征。
# 定義“性別”和“種族”為敏感信息
# 首先從數(shù)據(jù)集中選取敏感信息相關(guān)的列,組成新的Dataframe `sensitive_features`
sensitive_features = X_raw[['sex','race']]
sensitive_features.head(5)
執(zhí)行以下腳本,刪除X_raw
中的敏感特征及數(shù)據(jù),并查看刪除后的示例數(shù)據(jù)。
# 將特征變量中的敏感特征刪除
X = X_raw.drop(labels=['sex', 'race'],axis = 1)
X.head(5)
特征編碼和標(biāo)準(zhǔn)化
執(zhí)行以下腳本,對數(shù)據(jù)進(jìn)行標(biāo)準(zhǔn)化處理,轉(zhuǎn)換為適合responsible-ai-toolbox使用的格式。
import pandas as pd
from sklearn.preprocessing import StandardScaler
# one-hot 編碼
X = pd.get_dummies(X)
# 對數(shù)據(jù)集X進(jìn)行特征標(biāo)準(zhǔn)化(scaling)
sc = StandardScaler()
X_scaled = sc.fit_transform(X)
X_scaled = pd.DataFrame(X_scaled, columns=X.columns)
X_scaled.head(5)
劃分訓(xùn)練和測試數(shù)據(jù)
執(zhí)行以下腳本,將20%的數(shù)據(jù)劃分為測試數(shù)據(jù)集,剩余數(shù)據(jù)為訓(xùn)練數(shù)據(jù)集。
from sklearn.model_selection import train_test_split
# 按照`test_size`比例,將特征變量X和目標(biāo)變量y劃分為訓(xùn)練集和測試集
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)
# 使用相同的隨機(jī)種子,將敏感特征劃分為訓(xùn)練集和測試集,確保與上述劃分保持一致
sensitive_features_train, sensitive_features_test = \
train_test_split(sensitive_features, test_size=0.2, random_state=0, stratify=y_true)
分別查看訓(xùn)練數(shù)據(jù)集、測試數(shù)據(jù)集的數(shù)據(jù)量。
print("訓(xùn)練數(shù)據(jù)集的數(shù)據(jù)量:", len(X_train))
print("測試數(shù)據(jù)集的數(shù)據(jù)量:", len(X_test))
分別重置訓(xùn)練數(shù)據(jù)集、測試數(shù)據(jù)集的索引。
# 重置 DataFrame 的索引,避免索引錯(cuò)誤問題
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)
步驟五:模型訓(xùn)練
本文示例中,基于Sklearn使用訓(xùn)練數(shù)據(jù)訓(xùn)練一個(gè)邏輯回歸模型。
Sklearn
from sklearn.linear_model import LogisticRegression
# 創(chuàng)建邏輯回歸模型
sk_model = LogisticRegression(solver='liblinear', fit_intercept=True)
# 模型訓(xùn)練
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
# 實(shí)例化模型
input_size = X_train.shape[1]
pt_model = LogisticRegression(input_size)
# 損失函數(shù)和優(yōu)化器
criterion = nn.BCELoss()
optimizer = optim.SGD(pt_model.parameters(), lr=5e-5)
# 訓(xùn)練模型
num_epochs = 1
X_train_pt = X_train
y_train_pt = y_train
for epoch in range(num_epochs):
# 前向傳播
# DataFrame 轉(zhuǎn)換為 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 轉(zhuǎn)換為 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)
# 反向傳播和優(yōu)化
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')
])
# 編譯模型,使用二元交叉熵?fù)p失和隨機(jī)梯度下降優(yōu)化器
tf_model.compile(optimizer='sgd', loss='binary_crossentropy', metrics=['accuracy'])
# 訓(xùn)練模型
tf_model.fit(X_train, y_train, epochs=1, batch_size=32, verbose=0)
步驟六:模型評(píng)估
引入FairnessDashboard,使用responsible-ai-toolbox加載測試數(shù)據(jù)集進(jìn)行結(jié)果預(yù)測,生成公平性評(píng)估報(bào)告。
FairnessDashboard按照敏感變量分類預(yù)測結(jié)果和真實(shí)結(jié)果,并通過對比分析預(yù)測結(jié)果和真實(shí)結(jié)果,得到在不同敏感變量情況下的模型預(yù)測情況。
以敏感特征值“sex”為例,F(xiàn)airnessDashboard按照“sex”將對應(yīng)的預(yù)測結(jié)果(y_pred)和真實(shí)結(jié)果(y_test)進(jìn)行分類,在“sex”分類中分別計(jì)算“Male”和“Female”的選擇率、精確度等信息并進(jìn)行對比。
本文示例中,基于Sklearn對模型進(jìn)行評(píng)估:
Sklearn
from raiwidgets import FairnessDashboard
import os
from urllib.parse import urlparse
# 根據(jù)測試數(shù)據(jù)集進(jìn)行預(yù)測結(jié)果
y_pred_sk = sk_model.predict(X_test)
# 使用 responsible-ai-toolbox 計(jì)算每個(gè)敏感群體的數(shù)據(jù)信息
metric_frame_sk = FairnessDashboard(sensitive_features=sensitive_features_test,
y_true=y_test,
y_pred=y_pred_sk, locale = 'zh-Hans')
# 設(shè)置URL跳轉(zhuǎn)鏈接
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
# 測試模型并評(píng)估公平性
pt_model.eval() # 設(shè)置模型為評(píng)估模式
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 計(jì)算每個(gè)敏感群體的數(shù)據(jù)信息
metric_frame_pt = FairnessDashboard(sensitive_features=sensitive_features_test,
y_true=y_test,
y_pred=y_pred_pt.flatten().round(),locale='zh-Hans')
# 設(shè)置URL跳轉(zhuǎn)鏈接
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
# 測試模型并評(píng)估公平性
y_pred_tf = tf_model.predict(X_test).flatten()
# 使用 responsible-ai-toolbox 計(jì)算每個(gè)敏感群體的數(shù)據(jù)信息
metric_frame_tf = FairnessDashboard(
sensitive_features=sensitive_features_test,
y_true=y_test,
y_pred=y_pred_tf.round(),locale='zh-Hans')
# 設(shè)置URL跳轉(zhuǎn)鏈接
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'])
關(guān)鍵參數(shù)說明:
sensitive_features:敏感屬性。
y_true:訓(xùn)練數(shù)據(jù)集提供的真實(shí)結(jié)果。
y_pred:模型預(yù)測的結(jié)果。
locale(可選):評(píng)估面板顯示語言類型,支持簡體中文(“zh-Hans”)和繁體中文(“zh-Hant”),默認(rèn)為英語(“en”)。
步驟七:查看評(píng)估報(bào)告
評(píng)估完成后,單擊URL,查看完整的評(píng)估報(bào)告。
在公平性儀表板頁面單擊開始使用,按照以下參數(shù)依次設(shè)置敏感特征、性能指標(biāo)、公平性指標(biāo),查看模型針對敏感特征“sex”或“race”的指標(biāo)數(shù)據(jù)差異。
敏感特征為“sex”
敏感特征:sex
性能指標(biāo):Accuracy
公平性指標(biāo):Demographic parity difference
Accuracy:精確度,是指模型正確預(yù)測的樣本數(shù)占總樣本數(shù)的比例。模型輸出男性個(gè)人年收入的準(zhǔn)確度(81.6%)低于女性個(gè)人年收入的準(zhǔn)確度(93.1%),但是兩者的準(zhǔn)確度與模型總體準(zhǔn)確度(85.4%)都比較接近。
Selection rate:選擇率,是指模型輸出“好”的目標(biāo)變量的概率,這里“好”的目標(biāo)變量是個(gè)人年收入>50K。模型輸出男性個(gè)人年收入>50K的概率(25.7%)大于女性個(gè)人年收入>50K的概率(7.36%),并且模型輸出女性個(gè)人年收入>50K的概率(7.36%)遠(yuǎn)低于個(gè)人年收入>50K的總體概率(19.6%)。
Demographic parity difference:人口統(tǒng)計(jì)公平性差異,是指不同受保護(hù)群體之間,在指定的敏感屬性下獲得積極預(yù)測結(jié)果的概率差異。這個(gè)值越接近0,意味著群體間的偏差越小。模型總體的人口統(tǒng)計(jì)公平性差異為18.3%。
敏感特征為“race”
敏感特征:race
性能指標(biāo):Accuracy
公平性指標(biāo):Demographic parity difference
Accuracy:精確度,是指模型正確預(yù)測的樣本數(shù)占總樣本數(shù)的比例。模型輸出“White”和“Asian-Pac-Islander”個(gè)人年收入的準(zhǔn)確度(84.9%和79.1%)低于“Black”、“Other”和“Amer-Indian-Eskimo”個(gè)人年收入的準(zhǔn)確度(90.9%、90.8%和91.9%),但是所有敏感特征人群的準(zhǔn)確度與模型總體準(zhǔn)確度(85.4%)都比較接近。
Selection rate:選擇率,是指模型輸出“好”的目標(biāo)變量的概率,這里“好”的目標(biāo)變量是個(gè)人年收入>50K。模型輸出“White”和“Asian-Pac-Islander”個(gè)人年收入>50K的選擇率(21%和23.9%)大于“Black”、“Other”和“Amer-Indian-Eskimo”個(gè)人年收入>50K的選擇率 (8.34%、10.3%和8.14%),并且“Black”、“Other”和“Amer-Indian-Eskimo”個(gè)人年收入>50K的選擇率(8.34%、10.3%和8.14%)遠(yuǎn)低于個(gè)人年收入>50K的總體選擇率(19.6%)。
Demographic parity difference:人口統(tǒng)計(jì)公平性差異,是指不同受保護(hù)群體之間,在指定的敏感屬性下獲得積極預(yù)測結(jié)果的概率差異。這個(gè)值越接近0,意味著群體間的偏差越小。模型總體的人口統(tǒng)計(jì)公平性差異為15.8%。