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
登录PAI控制台。
在顶部左上角根据实际情况选择地域。
在左侧导航栏选择快速开始 > Notebook Gallery,搜索Responsible AI-公平性分析,并单击对应卡片上的在DSW中打开。
选择DSW实例,单击打开Notebook,系统会打开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,查看完整的评估报告。
在公平性仪表板页面单击开始使用,按照以下参数依次设置敏感特征、性能指标、公平性指标,查看模型针对敏感特征“sex”或“race”的指标数据差异。
敏感特征为“sex”
敏感特征:sex
性能指标:Accuracy
公平性指标:Demographic parity difference
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
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%。