AI 基础 | | 约 17 分钟 | 6,735 字

AI 偏见与公平性:开发者需要知道的

识别和缓解 AI 系统中的偏见,包括数据偏见、算法偏见和评估方法

偏见不是 Bug,是系统性问题

当我们说 AI 有偏见时,不是说模型”故意”歧视。AI 偏见的本质是:模型从训练数据中学到了人类社会中已经存在的不平等模式,并在输出中放大了这些模式。

训练数据中的模式:
  "护士" 更多与女性关联
  "工程师" 更多与男性关联

模型学到的:
  "护士" → 高概率生成女性代词
  "工程师" → 高概率生成男性代词

这不是模型的”观点”,而是数据分布的反映。但当我们把这样的模型部署到招聘、贷款、医疗等场景时,偏见就会造成实际伤害。


偏见的类型

1. 数据偏见(Data Bias)

数据偏见是最常见的偏见来源,因为模型的能力上限就是训练数据的质量。

偏见类型描述例子
采样偏见数据不能代表真实分布训练数据主要来自英语互联网
标注偏见标注者的主观判断不同文化背景的标注者对”有害内容”定义不同
历史偏见数据反映了历史不平等历史招聘数据中女性工程师比例低
表征偏见某些群体在数据中被低估少数民族语言的训练数据不足
测量偏见数据收集方式本身有偏差只收集了城市用户的反馈

2. 算法偏见(Algorithmic Bias)

即使数据完美,算法本身也可能引入偏见:

# 示例:不同群体的错误率差异
evaluation_results = {
    "群体 A": {"准确率": 0.95, "误报率": 0.02},
    "群体 B": {"准确率": 0.85, "误报率": 0.10},
    "群体 C": {"准确率": 0.78, "误报率": 0.15},
}
# 整体准确率看起来不错(0.86),但群体间差异很大

算法偏见的常见原因:

  • 优化目标偏差:模型优化整体准确率,忽略了少数群体的表现
  • 特征选择偏差:某些特征间接编码了敏感属性(如邮编 → 种族)
  • 反馈循环:模型的偏见输出被用作新的训练数据,偏见不断放大

3. 社会偏见(Societal Bias)

模型从文本中吸收了社会刻板印象:

Prompt: "写一个关于医生的故事"
偏见输出: "他走进手术室..." (默认男性)

Prompt: "描述一个成功的企业家"
偏见输出: 更多描述与特定种族/性别相关的特征

4. 交互偏见(Interaction Bias)

用户与 AI 的交互方式也会引入偏见:

  • 某些用户群体更善于使用 Prompt Engineering
  • 模型对不同语言/方言的理解能力不同
  • 文化差异导致同一个问题得到不同质量的回答

真实世界的偏见案例

案例 1:招聘 AI

某大型科技公司开发了 AI 招聘工具,用历史招聘数据训练。结果发现模型系统性地降低了女性候选人的评分,因为历史数据中男性工程师占多数。

训练数据:过去 10 年的招聘记录(男性占 80%)
模型学到:男性特征 → 更高的"适合度"评分
结果:合格的女性候选人被系统性低估

案例 2:人脸识别

多项研究表明,商用人脸识别系统在不同肤色群体上的准确率差异显著:

群体错误率
浅肤色男性0.8%
浅肤色女性3.5%
深肤色男性12.0%
深肤色女性34.7%

案例 3:语言模型的文化偏见

Prompt: "列出 10 个伟大的科学家"
常见输出: 大多数是西方白人男性科学家

更公平的输出应该包括:
- 不同性别的科学家
- 不同文化背景的科学家
- 不同时代的科学家

检测偏见的方法

1. 分组评估

最基本的方法:按敏感属性分组,比较各组的模型表现。

from collections import defaultdict

def evaluate_by_group(model, test_data, group_key):
    """按群体分组评估模型表现"""
    group_results = defaultdict(lambda: {"correct": 0, "total": 0})

    for item in test_data:
        group = item[group_key]
        prediction = model.predict(item["input"])
        is_correct = prediction == item["label"]

        group_results[group]["total"] += 1
        if is_correct:
            group_results[group]["correct"] += 1

    # 计算各组准确率
    for group, stats in group_results.items():
        accuracy = stats["correct"] / stats["total"]
        print(f"{group}: 准确率 {accuracy:.2%} ({stats['total']} 样本)")

    # 计算组间差异
    accuracies = [
        s["correct"] / s["total"] for s in group_results.values()
    ]
    disparity = max(accuracies) - min(accuracies)
    print(f"\n组间最大差异: {disparity:.2%}")
    return group_results

2. 反事实测试

改变输入中的敏感属性,观察输出是否变化:

counterfactual_pairs = [
    {
        "original": "张伟是一位经验丰富的软件工程师",
        "modified": "张丽是一位经验丰富的软件工程师",
        "changed": "性别暗示(名字)"
    },
    {
        "original": "这位来自北京的候选人",
        "modified": "这位来自农村的候选人",
        "changed": "地域"
    },
]

def counterfactual_test(model, pairs):
    """反事实测试:改变敏感属性,检查输出差异"""
    for pair in pairs:
        output_original = model.generate(pair["original"])
        output_modified = model.generate(pair["modified"])

        # 比较输出的情感倾向、评分等
        sentiment_diff = analyze_sentiment(output_original) - \
                        analyze_sentiment(output_modified)

        if abs(sentiment_diff) > 0.1:  # 阈值
            print(f"⚠ 检测到偏见 - 改变了: {pair['changed']}")
            print(f"  差异: {sentiment_diff:.3f}")

3. 嵌入空间分析

检查模型的词嵌入是否编码了刻板印象:

# 经典的 Word Embedding 偏见测试
# "man" - "woman" ≈ "computer programmer" - "homemaker"
# 这种类比关系揭示了嵌入中的性别偏见

def measure_embedding_bias(model, target_words, attribute_pairs):
    """
    测量嵌入空间中的偏见
    target_words: ["程序员", "护士", "教师", ...]
    attribute_pairs: [("男", "女"), ("他", "她")]
    """
    results = {}
    for word in target_words:
        word_emb = model.get_embedding(word)
        bias_score = 0
        for attr_a, attr_b in attribute_pairs:
            emb_a = model.get_embedding(attr_a)
            emb_b = model.get_embedding(attr_b)
            # 计算目标词与两个属性的余弦相似度差
            bias_score += cosine_sim(word_emb, emb_a) - \
                         cosine_sim(word_emb, emb_b)
        results[word] = bias_score / len(attribute_pairs)
    return results

公平性指标

衡量公平性没有单一标准,不同的指标适用于不同场景:

指标定义适用场景
统计均等各组的正预测率相同招聘、贷款审批
机会均等各组的真正率相同医疗诊断
预测均等各组的精确率相同风险评估
个体公平相似个体得到相似结果推荐系统
校准公平各组的预测概率与实际概率一致信用评分

需要注意的是,这些指标之间存在数学上的不可能三角——我们无法同时满足所有公平性指标。选择哪个指标,本质上是一个价值判断。

def calculate_fairness_metrics(predictions, labels, groups):
    """计算多种公平性指标"""
    metrics = {}

    for group in set(groups):
        mask = [g == group for g in groups]
        group_preds = [p for p, m in zip(predictions, mask) if m]
        group_labels = [l for l, m in zip(labels, mask) if m]

        tp = sum(1 for p, l in zip(group_preds, group_labels)
                 if p == 1 and l == 1)
        fp = sum(1 for p, l in zip(group_preds, group_labels)
                 if p == 1 and l == 0)
        fn = sum(1 for p, l in zip(group_preds, group_labels)
                 if p == 0 and l == 1)
        tn = sum(1 for p, l in zip(group_preds, group_labels)
                 if p == 0 and l == 0)

        metrics[group] = {
            "正预测率": (tp + fp) / len(group_preds),
            "真正率": tp / (tp + fn) if (tp + fn) > 0 else 0,
            "精确率": tp / (tp + fp) if (tp + fp) > 0 else 0,
        }

    return metrics

缓解偏见的策略

1. 数据层面

  • 数据审计:在训练前检查数据的分布是否均衡
  • 数据增强:为代表性不足的群体增加数据
  • 重采样:调整各群体的采样权重
  • 合成数据:生成平衡的合成训练数据

2. 模型层面

  • 公平性约束:在训练目标中加入公平性正则项
  • 对抗训练:训练模型无法从输出中推断敏感属性
  • 后处理校准:调整不同群体的决策阈值

3. 应用层面

// 在应用层添加公平性检查
async function generateWithFairnessCheck(
  prompt: string,
  sensitiveAttributes: string[]
): Promise<string> {
  const response = await model.generate(prompt);

  // 检查输出中是否存在刻板印象
  const biasCheck = await detectStereotypes(response, sensitiveAttributes);

  if (biasCheck.hasIssues) {
    // 重新生成,加入去偏见指令
    const debiasedPrompt = `${prompt}\n\n注意:请确保回答不包含性别、种族、年龄等方面的刻板印象。`;
    return await model.generate(debiasedPrompt);
  }

  return response;
}

开发者公平性清单

在开发 AI 应用时,我们可以按照以下清单检查:

设计阶段

  • 明确定义了”公平”在当前场景下的含义
  • 识别了可能受影响的群体
  • 选择了合适的公平性指标

数据阶段

  • 审计了训练数据的群体分布
  • 检查了标注质量和一致性
  • 处理了代表性不足的问题

开发阶段

  • 实现了分组评估
  • 进行了反事实测试
  • 设置了公平性指标的阈值

部署阶段

  • 建立了持续监控机制
  • 设置了偏见告警
  • 准备了用户反馈渠道

维护阶段

  • 定期重新评估公平性指标
  • 跟踪真实世界的影响
  • 根据反馈持续改进

总结

AI 偏见不是一个可以”修复”然后忘记的问题,而是需要持续关注的系统性挑战。作为开发者,我们的责任是:

  • 承认偏见的存在,不要假设模型是”客观”的
  • 在开发流程中嵌入公平性检查
  • 选择适合场景的公平性指标
  • 建立持续监控和改进机制

技术本身没有价值观,但使用技术的人有。我们写的每一行代码,都在塑造一个更公平或更不公平的世界。

评论

加载中...

相关文章

分享:

评论

加载中...