凌晨三点的急诊室,护士小林第一次独立值夜班。分诊台前来了两位病人:一个捂着右下腹,另一个也捂着右下腹,体温、血压、疼痛评分几乎一样。小林想起护士长的叮嘱——“看起来差不多的病人,分诊等级就不能差太多,否则家属要闹翻天的。”这就是个体公平最朴素的直觉:相似的个体,理应得到相似的对待。可问题接踵而至:什么叫“差不多”?体温差 0.3 度算不算?一个 80 岁一个 50 岁算不算?当 AI 模型取代分诊台时,这个“差不多”该如何量化、如何写进代码、又如何与“老人优先”这样的群体公平政策共存?这篇文章,就跟着小林从急诊室的一夜,走进个体公平的定义、数学表达、训练约束与伦理权衡。
掌握个体公平,你就能回答“模型有没有冤枉某个具体的人”这个灵魂拷问——这是算法工程师、AI 伦理审计师在模型上线前必须过关的硬核技能。
目录
可视化演示
展示个体公平核心概念(相似个体→相似预测)、欧氏距离与马氏距离度量的差异,以及个体公平与群体公平的冲突关系,支持三种模式切换。
本节配有交互动效(进入视口后自动加载,约 3KB)。
个体公平:相似个体→相似预测 输入空间相近的个体应获得相近的预测 违反个体公平:相似输入却产生差异预测 d_out(f(x), f(y)) ≤ L · d_in(x, y) Lipschitz连续性约束确保个体公平。
1. 公平概念定义:分诊台上“差不多”的直觉
护士长告诉小林,判断分诊等级有一条铁律:如果两位病人在体温、血压、疼痛评分这些客观指标上几乎一样,那他们拿到的分诊等级也必须几乎一样——一个是“急”一个是“轻”,家属一眼就能看出不对劲。这个直觉放到 AI 模型里,就是个体公平的雏形:给模型的输入“长得像”,模型的输出就该“长得像”。
那么什么才算“像”?模型对每个个体输出一个预测值(分诊等级、审批通过概率等),个体公平要求:当两个个体的特征距离足够小时,他们的预测差异也要被限制在一个小范围里。注意,这跟“对所有人一视同仁”完全是两码事——重症和轻症当然要区别对待,个体公平只约束“相似的人”,不要求“所有人相同”。
个体公平的“直觉版”定义可以写成:
这个定义像分诊台的考核标准:护士长不会要求小林把重症和轻症同等对待,只要求“看着差不多的病人,别给天差地别的等级”。理解了这句直觉,后面的数学都只是把“看着差不多”说得更精确而已。
- 任意个体配对对所有可能的个体组合都做检查,这是“任何人都不被冤枉”的承诺。
- 相似前提只有当特征距离小于阈值时才要求公平,差别大的人不受此约束。
- 预测差异有界最终结论是输出之差被控制在容差之内。
2. 形式化建模表达:把“像”翻译成数字尺子
小林渐渐明白了“差不多”要靠数字说话。她拿出体温计、血压计、血氧仪,每个病人都变成了一组读数——这在数学上叫特征向量,所有可能的读数组合构成特征空间。两个病人像不像,就看他们在特征空间里的距离远不远;而分诊等级则是模型输出的值。
2012年,Dwork 等人正是沿着这条思路给出了个体公平的经典形式化定义:模型 f 在度量空间中是 Lipschitz 连续的。Lipschitz 这个名字听着吓人,本质就是一句话——输入动一点,输出不能动太多。
注意,这个定义把“公平”归结为对模型函数平滑度的要求。曲线越陡峭,L 越大,两个相似个体就越可能被“甩”到不同的预测等级上去;曲线越平缓,L 越小,公平性就越有保障。这就像把分诊台的规矩写成文字:体温差 0.3 度的病人,分诊等级的差别绝不能像体温差 3 度的病人那么大。
- 任意两个个体公式对所有可能配对成立,不留死角。
- 预测绝对差输出之差的绝对值衡量不公平程度。
- 距离缩放上界输出差被输入距离乘以常数 L 封顶。
3. 相似性度量方法:选对尺子才能量对相似
有了“输出差不能太大”的约束,下一个问题接踵而至:用什么尺子量“输入距离”?小林一开始只看体温——结果发现体温一样的病人,一个只是感冒,一个却是阑尾炎发作。她这才明白,尺子选错了,相似就是假象。
最直观的尺子是欧氏距离:把所有特征当成坐标,直接算直线距离。但欧氏距离有个致命伤——它默认每个特征的重要性一样,可现实中体温差 0.5 度和血压差 0.5 的临床意义天差地别,而且体温的数值范围本来就比血压小。马氏距离则聪明得多:它先对每个特征按方差做归一化,再考虑特征之间的相关性,相当于护士长发给小林的那张“综合评估表”:各项指标各有权重,量血压不能只看收缩压,还要结合舒张压和心率。
更灵活的方案是加权特征距离——人为给每个特征分配权重;再进一步就是度量学习:让模型从数据里自动学出这组权重,把“哪些特征该被看重”直接学出来。小林最后给自己定了个规矩:用综合评估表,而不是单看体温。模型的个体公平也一样:尺子选得对不对,决定了公平约束是保护了真正的“相似”,还是仅仅保护了数值上的巧合。
- 向量差先算出两个个体在每个特征上的差。
- 协方差逆矩阵用数据自身的方差-相关结构做“矫正”。
- 二次型内积对矫正后的差向量求加权内积。
- 开方归一开根号得到距离值。
4. 模型训练公平约束:给模型戴上紧箍咒
小林终于上岗了,可她发现光有制度还不够——分诊台忙起来的时候,人脑会偷懒,模型也会。训练一个神经网络或逻辑回归模型时,目标函数只会努力把预测做准,根本不关心“两个相似病人的等级差了多少”。于是研究者想出办法:在损失函数里加一个“公平紧箍咒”,让模型优化时同时考虑准确率和公平性。
这个紧箍咒就是公平正则项:从训练数据里找出“相似个体对”,如果模型给它们的预测差超过了合理范围,就施加额外惩罚。最终总损失等于任务损失加上 λ 倍的公平惩罚,λ 控制紧箍咒的松紧。
除了加正则项,还有两招常用:对抗性训练——让一个“鉴别器”专门找模型输出中不公平的破绽,迫使主模型不断修正;以及后处理校准——模型训练完以后,再对相似个体的输出做一次平滑对齐。小林把考核表贴在分诊台上后,同事们的分诊方案果然收敛多了;模型的公平正则项,就是这个贴在损失函数上的考核表。
- 任务损失先保证模型基本的预测准确率。
- 取平均惩罚对所有相似个体对的超额差异取平均,公平惩罚是总和的平均值。
- 超额部分max 内部算的是“预测差超出合理容差”的部分,没超就不罚。
- 强度系数λ 越大,公平的权重越大。
5. 群体个体冲突:一份让所有人不满的报表
医院为了响应政策,公布了新规定:80 岁以上老人优先分诊。小林照着执行,却发现一个荒诞场景——一位 80 岁老人和一位 50 岁中年人症状几乎一样,按“老人优先”的群体政策,老人拿到更高级别;可按照之前“相似病人相似对待”的个体公平原则,两位本该拿一样的等级。两份规则打架了。
群体公平关心的是统计层面:不同群体(按年龄、性别、种族划分)的预测分布是否均衡。最常见指标是统计均等差异:
矛盾的本质在于:群体公平要求“两个群体之间可以有统计差异”(这正是为了纠正历史不公),而个体公平要求“两个相似个体之间不能有差异”。当群体属性本身就是特征的一部分时,两者必然冲突——老人优先会让相似个体得到不同结果;而强行要求每个相似个体结果一致,群体统计差异又无法归零。这就是著名的“公平悖论”:同时满足两种公平,在数学上常常无解。
- 老人组预测为正的概率群体 A 中模型给出 1 的概率。
- 中年组相应概率另一群体给出 1 的概率。
- 绝对值差额取两者之差的绝对值,衡量群体均衡度。
6. 公平权衡折中策略:在红线和指标之间找平衡
科室会议上吵成一团。最后主任拍板:老人优先的政策只用于“排队顺序”,不用于“病情等级判定”。模型的输出仍然遵循个体公平——相似症状得到相似等级;群体的关怀则通过排队规则去实现,不进模型。这个方案听起来朴素,背后却是公平研究的核心思想:不要做二选一,要做多目标折中。
在模型层面,折中的标准做法是把任务损失、个体公平惩罚、群体公平度量一起写进目标函数,用超参数控制各自的权重:
另一种思路是“公平预算”:设一个“群体差异不得超过 b”的硬约束,在预算内尽可能优化准确率和个体公平,即带约束的优化;还可以搜索 Pareto 最优解集——一组解里,任何一个目标变好都会让另一个变差,这就是公平的“帕累托前沿”,工程师根据业务需求在上面选点。主任的决策其实就是一次手工 Pareto 搜索:从“个体公平”和“群体优惠”两个目标里,找到了一个让大家都勉强接受的操作点。
- 模型参数优化的对象是模型参数 θ。
- 个体约束个体公平惩罚项由 λ₁ 加权。
- 群体约束群体公平差异由 λ₂ 加权。
7. 评估落地实践:查房、留证据、走流程
制度定了,还得有人检查。护士长每个月抽查分诊记录:随机挑出 200 对“特征相似”的病人,核对他们的分诊等级差距是否在容差范围内,最后写成一份公平审计报告——这对应的正是模型上线前的公平性评估。
评估的核心是构造公平测试集,以及量化个体公平指标。一个常用指标是“个体公平满足率”:
落到工程实践,通常有四步:第一,构造含敏感特征和相似对的公平测试集;第二,计算个体公平指标并和基线对比;第三,对超标案例做归因分析,是特征泄漏、度量不当还是约束太弱;第四,输出审计报告,说明公平-准确性权衡的具体数字,为合规审查留下证据。护士长的查房让分诊台不敢松懈,这份审计报告,就是 AI 模型在“分诊台”上留下的值班记录。
- 相似对集合测试集里预先构造的相似个体对。
- 条件指示函数满足则记 1,不满足记 0。
- 取平均最终得到公平满足率。
AI 应用场景
银行信贷审批:相近资质,相近批复
阶段:模型训练与上线前公平性校验
解决的问题:传统信贷模型只看逾期率,即使两个申请人收入、负债、征信几乎相同,也可能因为“历史巧合”被给出截然不同的审批结果,客户投诉和监管风险都很高。引入个体公平约束后,模型对“相似资质的人”给出高度一致的结论,审批逻辑更可解释、更抗投诉。
具体案例:某消金公司上线了带公平正则项的评分卡模型,在训练损失中加入“相似个体对”的预测差异惩罚。上线后审计发现,外部特征距离小于阈值的申请人中,审批结论不一致率从 18% 降到 4%,同时坏账率仅上升 0.3 个百分点。
智能急诊分诊:相似症状,相似等级
阶段:实时推理阶段的公平约束与线上监控
解决的问题:急诊分诊 AI 根据生命体征和主诉给出紧急等级,如果两个症状几乎相同的病人被分到不同等级,轻则引发投诉,重则延误救治。个体公平约束让分诊输出随输入变化更平滑,减少“边界处”的危险跳变。
具体案例:某三甲医院在分诊 AI 的推理层增加了后处理校准:对于相邻体征区间,强制输出等级平滑过渡,并设置公平监控看板,实时统计相似个体对的等级差。上线后,护士对 AI 分诊结果的人工修正率下降了 31%。
招聘简历初筛:相近经历,相近排序
阶段:数据准备阶段的特征选择与公平审计
解决的问题:简历筛选模型若直接用原始特征算欧氏距离,容易因“毕业院校”这类特征的尺度效应,把经历相近的候选人排到天差地别的位置。通过加权特征距离和个体公平审计,确保初筛排序对“相似背景”的候选人保持稳定。
具体案例:某招聘平台对初筛模型做公平审计时发现,两份技能、年限几乎相同的简历,排序分差了 40 分。定位后确定是“毕业院校”权重过高所致。改用马氏距离度量相似性并加入公平正则后,相差降至 6 分,招聘方满意度反而提升。
Python 演示
import numpy as np def sigmoid(z): return 1.0 / (1.0 + np.exp(-np.clip(z, -30, 30))) def make_data(n=600, seed=42): rng = np.random.default_rng(seed) X = rng.uniform(0, 10, size=(n, 2)) eta = 1.0 / (1.0 + np.exp(-(X[:, 0] + X[:, 1] - 10.0))) y = (eta + rng.normal(0, 0.15, n)) > 0.5 return X, y.astype(float) def pair_diff(model, X, n_pairs=200, seed=0): rng = np.random.default_rng(seed) idx = rng.integers(0, len(X), size=n_pairs) diffs = [] for i in idx: dist = np.linalg.norm(X - X[i], axis=1) dist[i] = np.inf j = int(np.argmin(dist)) diffs.append(abs(model.predict_one(X[i]) - model.predict_one(X[j]))) return float(np.mean(diffs)) class FairLogistic: def __init__(self, lam=0.0, lr=0.1, epochs=200, pair_eps=1.0): self.lam = lam self.lr = lr self.epochs = epochs self.pair_eps = pair_eps self.w = None self.b = 0.0 def predict_one(self, x): return sigmoid(x @ self.w + self.b) def predict(self, X): return sigmoid(X @ self.w + self.b) def _fair_grad(self, X, prob, rng): n = X.shape[0] grad = np.zeros(X.shape[1]) count = 0 perm = rng.permutation(n) for k in range(0, n, 2): i = perm[k] j = perm[k + 1] if np.linalg.norm(X[i] - X[j]) < self.pair_eps: diff = prob[i] - prob[j] grad += 2.0 * diff * prob[i] * (1.0 - prob[i]) * X[i] grad -= 2.0 * diff * prob[j] * (1.0 - prob[j]) * X[j] count += 1 if count > 0: grad /= count return grad def fit(self, X, y): n = X.shape[0] self.w = np.zeros(X.shape[1]) self.b = 0.0 rng = np.random.default_rng(0) for epoch in range(self.epochs): prob = self.predict(X) grad_w = X.T @ (prob - y) / n grad_b = np.mean(prob - y) if self.lam > 0.0: grad_w += self.lam * self._fair_grad(X, prob, rng) self.w -= self.lr * grad_w self.b -= self.lr * grad_b return self def main(): X_train, y_train = make_data() X_test, y_test = make_data(seed=7) plain = FairLogistic(lam=0.0) plain.fit(X_train, y_train) acc = float(np.mean((plain.predict(X_test) > 0.5) == y_test)) diff = pair_diff(plain, X_test) fair = FairLogistic(lam=2.0) fair.fit(X_train, y_train) acc2 = float(np.mean((fair.predict(X_test) > 0.5) == y_test)) diff2 = pair_diff(fair, X_test) print("无正则: 准确率", acc, "相近个体预测差", diff) print("有正则: 准确率", acc2, "相近个体预测差", diff2) if __name__ == "__main__": main()
eta = 1.0 / (1.0 + np.exp(-(X[:, 0] + X[:, 1] - 10.0)))生成一条线性决策边界,让模型在边界处天然容易对相近个体产生相反预测。grad_w = X.T @ (prob - y) / n逻辑回归的交叉熵梯度,指向让预测更准的方向。if self.lam > 0.0:是否启用公平正则,控制实验对比的关键开关。grad_w += self.lam * self._fair_grad(X, prob, rng)把伦理约束“接”进梯度下降,准确率和公平一起优化。if np.linalg.norm(X[i] - X[j]) < self.pair_eps:只在“特征相似”的样本对上施加惩罚,这是个体公平的精神所在。grad += 2.0 * diff * prob[i] * (1.0 - prob[i]) * X[i]对 sigmoid 输出差求链式梯度,把惩罚信号传回模型参数。dist[i] = np.inf; j = int(np.argmin(dist))在测试集中找每个个体的最近邻,用于事后评估公平性。fair = FairLogistic(lam=2.0)把公平正则开到 2.0,观察准确率的微小代价换来的公平收益。
常见误区
误区个体公平就是模型给每个人都输出同样的结果,比如每个人通过率都 50%,这样就绝对公平了。
正解完全错了。个体公平只要求“相似的个体相似对待”,重症和轻症、高收入和低收入的人本来就该得到不同结果。如果强行让所有人输出一致,反而抹掉了合理差异,让模型失去预测价值。这和分诊台不会给所有病人贴同一等级是一个道理。
为何常见:人们容易把“公平”误解为“平均”,忽略了公平的前提是“相似性”——先有相似,才有公平。
误区直接用特征的欧氏距离算相似度就好,反正都是数值,算出的距离肯定靠谱。
正解欧氏距离隐含假设每个特征同等重要且互不相关。实际数据里“年龄”数值范围只有 0-100,“收入”却能到几十万,欧氏距离会被数值范围大的特征主导。马氏距离通过协方差矩阵归一化并考虑相关性,本质是“根据数据分布矫正过的距离”。
为何常见:欧氏距离是大家最早学到的距离公式,惯性思维让人忽略了特征尺度问题。
误区公平正则项等于额外加了一层限制,模型准确率一定会显著下降,业务没法用。
正解公平约束本质是一种结构风险正则化,它会抑制模型在边界附近的剧烈震荡。很多场景下准确率只下降不到 1 个百分点,而公平性、鲁棒性和可解释性都提升。上文的 Python 演示里,λ=2 时准确率几乎没降,相似个体预测差却明显缩小。
为何常见:人们把“限制”和“损失”划等号,却忽略了约束也是先验知识。
误区把性别、年龄、种族这些敏感字段直接从特征里删掉,模型不就公平了吗?
正解敏感属性常与其它特征强相关(年龄和工龄、邮政编码和收入),删掉之后这些“代理变量”依然能还原群体信息。个体公平要求的是“相似个体输出相似”,如果代理特征让两个真实相似的人看起来不相似,删敏感属性也无济于事。
为何常见:把公平简单等同于“看不见敏感字段”,没意识到信息可以通过关联特征绕道传播。
误区个体公平和群体公平势不两立,既然数学上无法同时满足,那就只能牺牲一个。
正解数学上的“无法同时满足”是指完全同时满足,但工程上可以用多目标损失、公平预算、Pareto 前沿等手段找折中解,让两个指标都达到可接受水平。就像急诊室把“老人优先”放在排队规则而非病情等级里,让两条公平路线各司其职。
为何常见:把理论上的不可能定理解读为实践上的不可行,忽略了现实中我们从未要求任何指标做到 100%。
面试题
Q1. 个体公平最核心的思想是什么?
- A.对所有个体一视同仁
- B.相似个体获得相似预测← 正确答案
- C.保证群体配额相等
- D.消除所有特征差异
答案:B。个体公平只约束“相似的输入产生相似的输出”,并不要求对所有人一致。A 是平均主义的误读,C 属于群体公平的配额思路,D 抹掉所有差异会让模型失去判别能力。
Q2. 在个体公平的 Lipschitz 条件中,L 的含义是什么?
- A.相似度阈值上限
- B.输出差对输入差的放大倍数← 正确答案
- C.模型训练迭代轮数
- D.输入特征的维度数
答案:B。公式 |f(x)-f(x')| ≤ L·d(x,x') 中,L 是 Lipschitz 常数,表示输入距离每增加 1,输出差最多增加 L。L 越小,函数越平缓,个体越公平。
Q3. 马氏距离相比欧氏距离的主要优势是什么?
- A.计算效率更高
- B.兼顾特征相关性和尺度← 正确答案
- C.无须协方差矩阵
- D.可接受缺失特征
答案:B。马氏距离用协方差矩阵的逆对特征做过归一化和去相关,能避免“数值范围大的维度主导距离”的问题。欧氏距离没有这些矫正,也谈不上处理缺失值。
Q4. 个体公平的训练正则项通常惩罚什么?
- A.模型参数绝对值
- B.相似个体对的输出差异← 正确答案
- C.训练数据的噪声
- D.群体均值的差异
答案:B。正则项从训练数据中找出相似个体对,惩罚 |f(x_i)-f(x_j)| 超过容差的部分。参数绝对值对应 L2 正则,群体均值差异对应群体公平,都不属于个体公平正则。
Q5. 下列哪些方法可用于实现个体公平约束?
- A.损失函数加正则化惩罚← 正确答案
- B.对抗性训练← 正确答案
- C.后处理输出校准← 正确答案
- D.删除所有敏感属性
答案:ABC。正则化、对抗训练、后处理校正是三种主流实现路径。删除敏感属性看似合理,但敏感信息会通过关联特征泄漏,并不能实质保证个体公平。
Q6. 个体公平与群体公平冲突的本质原因是什么?
- A.训练数据量不足
- B.相似个体要一致而群体统计要有差异← 正确答案
- C.模型出现严重过拟合
- D.特征维度太高
答案:B。个体公平要求相似个体输出尽量相同,群体公平却允许甚至要求群体统计结果不同(如纠正历史不公)。两个目标在数学上互相拉扯,与数据量、过拟合无关。
Q7. 用欧氏距离度量个体相似性时最容易忽略什么?
- A.特征尺度不一致← 正确答案
- B.样本数量偏少
- C.标签噪声干扰
- D.模型结构复杂
答案:A。欧氏距离把每个维度等同看待,尺度大的特征会主导距离计算。比如“收入”范围远大于“年龄”时,收入相近会掩盖年龄差异,导致相似性判断失真。
Q8. 下列属于个体公平与群体公平折中方案的有哪些?
- A.设置群体差异公平预算← 正确答案
- B.构造多目标损失函数← 正确答案
- C.搜索 Pareto 最优解集← 正确答案
- D.放弃个体公平只保群体
答案:ABC。公平预算把群体差异限制在可接受范围内,多目标损失用 λ₁/λ₂ 调节两类公平,Pareto 搜索找多目标折中前沿。D 是放弃式回应,谈不上“折中”。
Q9. 评估个体公平的常用手段是什么?
- A.检查相似对的输出差异← 正确答案
- B.比较不同群体均值
- C.计算特征重要性
- D.观察训练损失曲线
答案:A。个体公平的评估核心是构造相似个体对,检查预测差异是否在容差内,计算公平满足率。比较群体均值属于群体公平评估。
Q10. 用欧氏距离定义相似性时,如果某维特征方差远大于其他维,个体公平约束可能失效,原因是?
- A.大方差维度主导了距离计算← 正确答案
- B.协方差矩阵不可逆
- C.特征空间维度发生爆炸
- D.模型分类阈值自动漂移
答案:A。欧氏距离没有按方差归一化,方差大的维度在距离和中占比过大,导致“相似”的判断被单维主导,相似个体对选取失真,公平约束保护的对象与实际语义不符。