引言:AI系统中的公平性挑战
在AI模型部署中,模型公平性(Fairness)是基础设施工程师和数据科学家必须解决的核心问题之一。如果训练数据包含人口统计学偏见(例如性别、种族、年龄的不均衡代表或历史歧视),模型将固化甚至放大这种偏见,导致对特定群体的不公平结果。解决偏见的方法通常分为三个阶段:预处理(Pre-processing)、过程中处理(In-processing)和后处理(Post-processing)。
本文将聚焦于预处理阶段,详细介绍如何使用强大的开源工具包 IBM AI Fairness 360 (AIF360) 中的 Reweighting(样本权重重构) 算法来消除训练数据中的偏见。
技术原理:Reweighting 算法
Reweighting 是一种基于数据的公平性缓解技术。它的核心目标是确保受保护群体(Protected Group)和非受保护群体(Unprivileged Group)在所有标签类别中对模型训练的贡献是平衡的。
具体来说,Reweighting 算法通过计算调整因子,为训练集中的每个样本生成一个新的权重。这些权重确保了在原始数据集中具有统计差异(Disparate Impact)的群组,在加权后的数据集中表现出更接近的机会平等。
$$W_{(A=a, Y=y)} = \frac{P(Y=y)}{P(A=a) \cdot P(Y=y | A=a)}$$
其中 $A$ 是受保护属性,$Y$ 是标签。
实用操作:使用 AIF360 进行偏见消除
我们将使用 AIF360 库,并模拟一个经典的二分类任务(如信贷审批),其中性别(’sex’)被视为受保护属性。
1. 环境准备与数据设置
首先,确保安装了必要的库:
pip install aif360 pandas numpy scikit-learn
我们创建一个简化的模拟数据集,包含性别(受保护属性)、年龄和是否获得批准(标签)。
import pandas as pd
import numpy as np
from aif360.datasets import StandardDataset
from aif360.algorithms.preprocessing import Reweighting
from aif360.metrics import BinaryLabelDatasetMetric
# 模拟数据:0=女性(未受保护),1=男性(受保护)
data = {
'sex': np.random.choice([0, 1], size=1000, p=[0.6, 0.4]), # 60%女性, 40%男性
'age': np.random.randint(20, 60, size=1000),
'income': np.random.randint(30000, 100000, size=1000),
'approved': np.random.choice([0, 1], size=1000, p=[0.55, 0.45]) # 标签:0=拒绝, 1=批准
}
df = pd.DataFrame(data)
# 定义 AIF360 参数
protected_attribute_names = ['sex']
# 定义特权组和非特权组。假设男性(1)是特权组,女性(0)是非特权组
privileged_groups = [{'sex': 1}]
unprivileged_groups = [{'sex': 0}]
label_names = ['approved']
favorable_label = 1 # 批准是好的结果
# 将 Pandas DataFrame 转换为 AIF360 的 StandardDataset 格式
dataset_orig = StandardDataset(
df,
label_names=label_names,
protected_attribute_names=protected_attribute_names,
privileged_groups=privileged_groups,
unprivileged_groups=unprivileged_groups,
favorable_label=favorable_label
)
2. 评估原始数据偏见
在应用重构之前,我们先使用 差异影响比率 (Disparate Impact Ratio, DIR) 评估原始数据的偏见程度。DIR 定义为非特权组获得有利结果的比例除以特权组获得有利结果的比例。理想情况下,DIR 应该在 0.8 到 1.25 之间。
metric_orig = BinaryLabelDatasetMetric(
dataset_orig,
unprivileged_groups=unprivileged_groups,
privileged_groups=privileged_groups
)
print(f"原始数据的差异影响比率 (DIR): {metric_orig.disparate_impact():.4f}")
3. 应用 Reweighting 算法
现在,我们初始化并应用 Reweighting 算法。这个步骤会计算出新的样本权重,存储在新的 StandardDataset 实例中。
# 初始化 Reweighting 算法
RW = Reweighting(
unprivileged_groups=unprivileged_groups,
privileged_groups=privileged_groups
)
# 应用算法:生成转换后的数据集
dataset_transf = RW.fit_transform(dataset_orig)
# 检查转换后数据的差异影响比率
metric_transf = BinaryLabelDatasetMetric(
dataset_transf,
unprivileged_groups=unprivileged_groups,
privileged_groups=privileged_groups
)
print(f"重构后数据的差异影响比率 (DIR): {metric_transf.disparate_impact():.4f}")
# 提取新的权重
sample_weights = dataset_transf.instance_weights
通过上述操作,我们可以看到转换后的数据集的 DIR 值会更接近 1.0,这表明性别这一受保护属性带来的统计差异被大大削弱了。
4. 使用加权数据训练模型
最后一步是使用这些新生成的 sample_weights 来训练我们的下游模型,例如 Scikit-learn 的逻辑回归模型。大多数现代机器学习框架(如 Scikit-learn、TensorFlow、PyTorch)都支持在训练过程中传入样本权重。
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
# 准备特征 X 和标签 y
X = dataset_orig.features
y = dataset_orig.labels.ravel()
# 分割数据 (这里简化处理,实际中应先分割再应用Reweighting)
X_train, X_test, y_train, y_test, w_train, w_test = train_test_split(
X, y, sample_weights, test_size=0.3, random_state=42
)
# 训练一个考虑公平性权重的模型
model_fair = LogisticRegression(solver='liblinear')
model_fair.fit(X_train, y_train, sample_weight=w_train)
# 训练一个未考虑权重的基线模型
model_baseline = LogisticRegression(solver='liblinear')
model_baseline.fit(X_train, y_train)
print("模型训练完成。公平性模型已在加权数据上训练完成。")
通过这种方式,我们确保了模型在训练阶段就接触到了一个统计上更为平衡的数据集,从而在部署时能够提供更公平的预测结果,有效解决了由于数据采集或历史偏见导致的人口统计学不平等问题。
汤不热吧