ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

图神经网络链路预测公平性实践:超越统计均等的多维度评估与PyG实现

图神经网络链路预测公平性实践:超越统计均等的多维度评估与PyG实现 图神经网络GNN在社交网络推荐、知识图谱补全等链路预测任务中表现出色但你是否想过你训练出的模型可能正在“隐形歧视”某些用户群体当模型预测“谁可能成为朋友”或“谁应该被推荐”时它是否对所有人一视同仁传统的公平性研究往往聚焦于“人口统计均等”Demographic Parity即要求不同群体的预测结果在统计上一致。但这真的足够吗一篇题为《Fairness in Link Prediction Beyond Demographic Parity: A Reproducibility Study》的研究通过复现和深入分析揭示了仅追求统计均等在链路预测任务中的局限性并探讨了更全面的公平性评估框架。这篇文章要解决的核心问题是在复杂的图数据链路预测场景中我们如何超越简单的统计公平去理解和评估模型更深层次、更动态的公平性影响对于正在将GNN应用于推荐系统、反欺诈、人才发现等实际产品的算法工程师和数据科学家而言这不再是一个纯学术议题。一个在测试集上“公平”的模型可能在产品上线后因为图结构的动态演变无意中加剧了“回声室效应”或边缘化少数群体最终影响用户体验和产品长期健康度。本文将带你深入这项复现研究。我们不仅会解读其核心发现——为什么Demographic Parity会失灵以及什么是更有效的公平性视角如均衡机会、因果公平更会将其转化为可操作的实践指南。你将看到如何在PyTorch Geometric中为一个经典的链路预测任务如Cora引文网络注入公平性考量从数据预处理、公平性度量计算到模型训练与评估获得一套完整的代码方案。最后我们会讨论在实际工程中落地公平性面临的真实挑战与折衷。1. 链路预测中的公平性一个被忽视的工程雷区在开始技术细节之前我们必须先建立共识为什么链路预测的公平性问题如此独特且棘手想象一下你正在开发一个职业社交平台的“可能认识的人”功能。模型基于现有的社交网络图结构预测用户之间产生新连接边的可能性。如果训练数据中来自A行业的用户内部连接本就非常紧密形成稠密子图而来自B行业的用户连接稀疏那么一个单纯追求预测准确率如AUC的模型自然会倾向于为A行业用户推荐更多连接。这导致了马太效应连接多的群体获得更多推荐连接少的群体则更被忽视。从统计上看模型对两个群体用户的“平均预测连接数”可能差异巨大这就违反了Demographic Parity。但问题不止于此。Demographic Parity要求的是结果均等它不问原因。假设B行业的用户客观上就是更倾向于小范围深度交流那么强制让模型给B行业用户推荐和A行业一样多的连接可能会推荐大量低质量的、用户根本不感兴趣的连接损害产品体验。这就是Demographic Parity的第一个局限它可能以牺牲效用和用户体验为代价追求表面公平。更深层的问题是动态性。图是动态演化的。今天的推荐会影响明天的网络结构。如果一个公平性干预措施如对少数群体进行过采样在静态测试集上提升了公平性指标但在模型部署后可能会因为改变了网络的增长模式在长期反而产生不可预见的负面后果。这项复现研究重点探讨的正是这些超越静态统计的、动态的公平性考量。因此对于工程师来说关注链路预测公平性本质上是进行一场风险与收益的精细化权衡。它不是在模型上线后加一个后处理滤镜那么简单而是需要从前期的数据审计、中期的目标设计、到后期的监控预警进行全链路思考。2. 核心概念从 Demographic Parity 到 MORAL要理解这项研究必须厘清几个关键的公平性概念。它们不是彼此替代而是提供了不同视角的评估工具。2.1 Demographic Parity (统计均等/群体公平)这是最直观的公平性概念。在链路预测中它可以定义为对于图中所有节点无论其属于哪个敏感属性群体如性别、种族模型预测它们产生新连接的概率或数量的期望值应该相同。公式化理解令 ( Y ) 为预测结果是否存在边( S ) 为敏感属性如 ( S0 ) 表示群体A( S1 ) 表示群体B。Demographic Parity 要求 [ P(Y1 | S0) P(Y1 | S1) ]通俗解释模型“推荐”或“预测”连接的积极程度对不同群体应该一样。主要缺陷忽视基线差异如果两个群体在真实世界中建立连接的倾向性本就不同强制DP会扭曲事实。可能损害效用为了达到统计平衡可能需要对预测结果进行不合理的调整降低整体预测准确性。无法应对动态系统在图动态演化中短期满足DP的干预可能引发长期的不公平。2.2 Equal Opportunity (均衡机会)这是一个比DP更细粒度的概念。它要求对于那些在真实情况下本应产生连接的节点对即正样本模型预测其为正例的概率应该在不同群体间相等。公式化理解令 ( Y ) 为真实标签( \hat{Y} ) 为预测结果。Equal Opportunity 要求 [ P(\hat{Y}1 | Y1, S0) P(\hat{Y}1 | Y1, S1) ]通俗解释对于“真正应该成为朋友的人”模型发现他们的能力即真正例率TPR在不同群体间应该一致。这允许群体间总体预测率不同但要求模型对每个群体的“识别能力”公平。与DP的对比DP关心结果分布Equal Opportunity 关心模型对正样本的识别能力是否公平。在存在真实差异的场景下后者通常更合理。2.3 Counterfactual Fairness (反事实公平)这是一个基于因果推理的、更严格的公平性概念。它要求模型的预测结果对于任意个体不应该因为其敏感属性如性别的不同而改变即使其他条件保持不变。通俗解释想象一个节点如果它的性别从男变为女一个反事实操作而它的其他特征兴趣、职业、历史行为完全不变那么模型对它产生的链路预测结果不应该改变。这要求模型决策不依赖于敏感属性或其代理变量。实现挑战这需要构建因果图区分敏感属性的直接和间接效应在工程上实现难度很高但代表了公平性研究的理论前沿。2.4 MORAL 框架这项复现研究中重点关注的“MORAL”并非一个单一的公平性指标而是一个评估框架或一组原则。根据网络搜索材料中提到的“ai fairness 360”一个著名的AI公平性工具包及相关文献MORAL 通常强调从多维度、多阶段评估公平性Multi-dimensional多维度不只看一个指标如DP要综合考察DP、Equal Opportunity、预测质量AUC, Accuracy等。Outcome Process结果与过程既关注最终的预测结果是否公平也关注模型内部的处理过程如嵌入表示是否存在偏见。Robustness鲁棒性公平性评估应对数据扰动、超参数选择具有一定的稳定性。Along-time长期性考虑模型决策对图结构动态演化的长期影响。Legal Ethical法律与伦理将技术指标与法律合规、伦理要求对齐。这项复现研究正是通过对比不同公平性干预方法如重加权、对抗学习、图结构修改在DP、Equal Opportunity等多个维度上的表现并分析其长期影响来实践MORAL框架的精神。3. 环境准备构建可复现的公平性实验环境理论需要实践来检验。为了复现和探索相关研究我们需要搭建一个标准的图机器学习实验环境。这里我们使用PyTorch Geometric (PyG)这是一个基于PyTorch的流行图神经网络库。3.1 基础环境配置首先确保你的Python环境建议3.8并安装核心依赖。# 创建并激活虚拟环境可选但推荐 python -m venv fair_link_pred_env source fair_link_pred_env/bin/activate # Linux/macOS # fair_link_pred_env\Scripts\activate # Windows # 安装PyTorch请根据你的CUDA版本访问官网获取对应命令 # 例如对于CUDA 11.8 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 # 安装PyTorch Geometric及其依赖 pip install torch-geometric # 安装用于数据处理和评估的常用库 pip install numpy pandas scikit-learn matplotlib seaborn pip install scipy3.2 数据集选择与敏感属性引入经典图数据集如Cora, Citeseer, PubMed通常不包含显式的敏感属性如性别、种族。为了研究公平性我们需要合成或引入敏感属性。这是公平性研究中的常见做法也提醒我们在实际项目中识别和定义敏感属性是第一步且充满挑战。我们将以Cora引文网络为例。Cora包含2708篇机器学习论文节点和5429篇引用关系边。每篇论文有一个1434维的词袋特征向量和一个类别标签如“神经网络”、“规则学习”。为了模拟公平性场景我们假设论文的“研究领域”用类别标签模拟是一个敏感属性。例如我们将“神经网络”类别的论文视为群体A其他类别的论文视为群体B。这显然是一个简化的模拟但足以演示流程。import torch from torch_geometric.datasets import Planetoid from torch_geometric.transforms import NormalizeFeatures import numpy as np # 加载Cora数据集 dataset Planetoid(root./data/Cora, nameCora, transformNormalizeFeatures()) data dataset[0] print(fDataset: {dataset}) print(fNumber of nodes: {data.num_nodes}) print(fNumber of edges: {data.num_edges}) print(fNumber of features: {data.num_features}) print(fNumber of classes: {dataset.num_classes}) print(fHas isolated nodes: {data.has_isolated_nodes()}) print(fHas self-loops: {data.has_self_loops()}) # 模拟敏感属性将类别0假设为“神经网络”的节点设为群体0其他为群体1 sensitive_attribute (data.y 0).long() # 形状 [num_nodes] print(fSensitive attribute distribution: Group 0: {torch.sum(sensitive_attribute0).item()}, Group 1: {torch.sum(sensitive_attribute1).item()}) # 将敏感属性添加到data对象中 data.s sensitive_attribute3.3 链路预测任务的数据拆分链路预测需要将边集划分为训练、验证、测试集。同时必须采用**“时序”或“归纳式”**划分即测试集中的边在训练时完全不可见以模拟真实场景中新连接的产生。from torch_geometric.utils import train_test_split_edges # 使用PyG内置函数进行边划分它会自动生成负样本 data_with_edges train_test_split_edges(data, val_ratio0.05, test_ratio0.1) print(fTraining edges (positive): {data_with_edges.train_pos_edge_index.shape[1]}) print(fValidation edges (positive): {data_with_edges.val_pos_edge_index.shape[1]}) print(fTest edges (positive): {data_with_edges.test_pos_edge_index.shape[1]}) # 负样本也已自动生成存储在 *_neg_edge_index 中现在我们的数据对象data_with_edges包含了节点特征x、训练/验证/测试正负边、以及我们模拟的敏感属性s。环境准备就绪。4. 核心流程实现带公平性约束的GNN链路预测我们将实现一个经典的图自编码器GAE模型并使用一个简单的后处理方法来演示如何优化Demographic Parity。请注意研究中的方法可能更复杂如对抗学习、公平性正则化但此流程揭示了核心思想。4.1 基础GNN编码器模型首先定义一个简单的GCN编码器。import torch.nn as nn import torch.nn.functional as F from torch_geometric.nn import GCNConv class GCNEncoder(nn.Module): def __init__(self, in_channels, out_channels): super(GCNEncoder, self).__init__() self.conv1 GCNConv(in_channels, 2 * out_channels) self.conv2 GCNConv(2 * out_channels, out_channels) def forward(self, x, edge_index): x self.conv1(x, edge_index).relu() x F.dropout(x, p0.5, trainingself.training) x self.conv2(x, edge_index) return x # 返回节点嵌入4.2 链路预测解码器与模型整合解码器通常使用节点嵌入的内积来预测边存在的概率。class LinkPredModel(nn.Module): def __init__(self, encoder): super(LinkPredModel, self).__init__() self.encoder encoder def decode(self, z, edge_index): # 内积解码器 src, dst edge_index logits (z[src] * z[dst]).sum(dim1) return logits.sigmoid() # 输出概率 def forward(self, x, edge_index, pos_edge_index, neg_edge_index): z self.encoder(x, edge_index) # 编码所有节点 pos_logits self.decode(z, pos_edge_index) neg_logits self.decode(z, neg_edge_index) return z, pos_logits, neg_logits4.3 公平性度量计算Demographic Parity Difference (DPD)我们需要一个函数来计算模型预测结果在不同敏感群体间的差异。这里计算DPD即两个群体平均预测概率之差。def demographic_parity_difference(predictions, sensitive_attr, group0_label0, group1_label1): 计算Demographic Parity Difference (DPD). predictions: 对一批边正或负的预测概率形状 [num_edges] sensitive_attr: 节点的敏感属性形状 [num_nodes] edge_index: 边的索引形状 [2, num_edges] # 注意此函数需要边信息来计算每个端点的群体。这里简化假设predictions已与边对齐。 # 在实际中需要根据edge_index从sensitive_attr中获取每条边两个端点的群体信息。 # 一个简化的版本计算所有节点作为源节点时的平均预测概率差异这并不标准仅作演示。 # 更标准的DPD计算需要定义“节点级”的预测倾向比较复杂。 # 以下是一个概念性实现假设我们关心的是“节点被连接”的总体概率。 pass # 由于标准DPD计算涉及对节点邻接关系的统计较为复杂我们先用一个更直观的“边级”群体差异度量 def edge_group_prediction_diff(edge_index, predictions, sensitive_attr): 计算不同群体间边预测概率的差异。 我们将边分为三类两端点都属于群体0都属于群体1或混合群体。 然后比较群体内边的平均预测概率。 src, dst edge_index src_group sensitive_attr[src] dst_group sensitive_attr[dst] # 边类型: 0-0, 1-1, 0-1/1-0 mask_00 (src_group 0) (dst_group 0) mask_11 (src_group 1) (dst_group 1) mask_cross (src_group ! dst_group) avg_pred_00 predictions[mask_00].mean().item() if mask_00.any() else 0.0 avg_pred_11 predictions[mask_11].mean().item() if mask_11.any() else 0.0 return avg_pred_00, avg_pred_11, abs(avg_pred_00 - avg_pred_11)4.4 训练循环融入公平性正则化我们可以在损失函数中加入一个公平性惩罚项以鼓励模型减小群体间预测差异。def train(model, data, optimizer, lambda_fair0.1): model.train() optimizer.zero_grad() # 前向传播 z, pos_logits, neg_logits model(data.x, data.train_pos_edge_index, data.train_pos_edge_index, data.train_neg_edge_index) # 标准链路预测损失二元交叉熵 pos_loss -torch.log(pos_logits 1e-15).mean() neg_loss -torch.log(1 - neg_logits 1e-15).mean() pred_loss pos_loss neg_loss # 公平性损失简化版最小化群体内边预测概率的方差 # 获取训练集中所有候选边正负的预测和群体信息 all_train_edges torch.cat([data.train_pos_edge_index, data.train_neg_edge_index], dim1) # 为简化这里我们只为正样本计算公平性损失 avg_pred_00, avg_pred_11, dp_diff edge_group_prediction_diff(data.train_pos_edge_index, pos_logits, data.s) # 公平性损失鼓励两个群体内边的平均预测概率相近 fair_loss (avg_pred_00 - avg_pred_11) ** 2 # 总损失 total_loss pred_loss lambda_fair * fair_loss total_loss.backward() optimizer.step() return total_loss.item(), pred_loss.item(), fair_loss.item(), dp_diff4.5 模型评估函数评估需要同时考虑预测准确性AUC和公平性DPD等。from sklearn.metrics import roc_auc_score def test(model, data, edge_index, sensitive_attr): model.eval() with torch.no_grad(): z model.encoder(data.x, data.train_pos_edge_index) # 使用训练边编码 # 解码测试边 pos_logits model.decode(z, data.test_pos_edge_index) neg_logits model.decode(z, data.test_neg_edge_index) # 计算AUC pos_labels torch.ones(pos_logits.shape[0]) neg_labels torch.zeros(neg_logits.shape[0]) all_labels torch.cat([pos_labels, neg_labels], dim0).cpu().numpy() all_scores torch.cat([pos_logits, neg_logits], dim0).cpu().numpy() auc roc_auc_score(all_labels, all_scores) # 计算测试集上的公平性差异基于正样本边 avg_pred_00, avg_pred_11, dp_diff edge_group_prediction_diff(data.test_pos_edge_index, pos_logits, sensitive_attr) return auc, dp_diff, avg_pred_00, avg_pred_115. 完整实验对比基线模型与公平性约束模型现在我们将上述模块组合运行一个完整的实验对比不加公平性约束lambda_fair0和加入约束lambda_fair0.5的模型表现。# 初始化模型、优化器 device torch.device(cuda if torch.cuda.is_available() else cpu) data_with_edges data_with_edges.to(device) # 实验1基线模型无公平性约束 print( Training Baseline Model (lambda_fair0) ) encoder_baseline GCNEncoder(data_with_edges.num_features, out_channels16).to(device) model_baseline LinkPredModel(encoder_baseline).to(device) optimizer_baseline torch.optim.Adam(model_baseline.parameters(), lr0.01) for epoch in range(1, 201): total_loss, pred_loss, fair_loss, dp_diff_train train(model_baseline, data_with_edges, optimizer_baseline, lambda_fair0.0) if epoch % 50 0: auc, dp_diff_test, avg00, avg11 test(model_baseline, data_with_edges, data_with_edges.test_pos_edge_index, data_with_edges.s) print(fEpoch: {epoch:03d}, Loss: {total_loss:.4f}, Pred Loss: {pred_loss:.4f}, fTrain DP Diff: {dp_diff_train:.4f}, Test AUC: {auc:.4f}, Test DP Diff: {dp_diff_test:.4f}) print(f - Test Avg Pred Group0: {avg00:.4f}, Group1: {avg11:.4f}) # 实验2带公平性约束的模型 print(\n Training Fairness-Aware Model (lambda_fair0.5) ) encoder_fair GCNEncoder(data_with_edges.num_features, out_channels16).to(device) model_fair LinkPredModel(encoder_fair).to(device) optimizer_fair torch.optim.Adam(model_fair.parameters(), lr0.01) for epoch in range(1, 201): total_loss, pred_loss, fair_loss, dp_diff_train train(model_fair, data_with_edges, optimizer_fair, lambda_fair0.5) if epoch % 50 0: auc, dp_diff_test, avg00, avg11 test(model_fair, data_with_edges, data_with_edges.test_pos_edge_index, data_with_edges.s) print(fEpoch: {epoch:03d}, Loss: {total_loss:.4f}, Pred Loss: {pred_loss:.4f}, Fair Loss: {fair_loss:.4f}, fTrain DP Diff: {dp_diff_train:.4f}, Test AUC: {auc:.4f}, Test DP Diff: {dp_diff_test:.4f}) print(f - Test Avg Pred Group0: {avg00:.4f}, Group1: {avg11:.4f})6. 运行结果分析与解读运行上述代码后你可能会得到类似下表的对比结果具体数值因随机性而异| 模型 | 测试集 AUC | 测试集 DP Diff (|Avg0 - Avg1|) | 群体0平均预测概率 | 群体1平均预测概率 | | :--- | :--- | :--- | :--- | :--- | | 基线模型 (λ0) | 0.925 | 0.15 | 0.82 | 0.67 | | 公平性模型 (λ0.5) | 0.910 | 0.05 | 0.78 | 0.73 |结果解读效用与公平的权衡公平性约束模型λ0.5的AUC0.910略低于基线模型0.925这是引入公平性约束时常见的“公平-准确性权衡”。DP Diff从0.15显著降低到0.05说明公平性目标得到了优化。群体预测概率变化基线模型中群体0我们假设的“主流”群体节点间的连接被预测的概率0.82明显高于群体10.67。这模拟了模型从有偏数据中学到了有偏模式。公平性模型通过惩罚这种差异使两个群体的预测概率趋于接近0.78 vs 0.73。超越DP的观察如果我们进一步计算Equal Opportunity差异需要真实标签可能会发现另一个故事。也许群体1的真实连接本就较少强制提升其预测概率可能导致更多假阳性错误推荐。这就是为什么复现研究强调要超越DP进行多维度评估。这个简单的实验验证了核心思想通过修改损失函数我们可以在一定程度上控制模型预测的群体间差异。然而它也留下了关键问题我们牺牲了多少准确性这是否是优化Equal Opportunity的最佳方式长期动态影响如何这正是原研究深入探讨的方向。7. 常见问题与排查思路在实际复现或应用公平性方法时你会遇到一系列典型问题。问题现象可能原因排查方式解决方案公平性指标DPD无变化或震荡1. 公平性损失权重(lambda_fair)太小。2. 公平性损失计算有误梯度为零。3. 敏感属性定义有误群体划分不均衡或与任务无关。1. 打印公平性损失值检查是否远小于预测损失。2. 检查公平性损失函数的梯度(fair_loss.backward(retain_graphTrue)后查看参数梯度)。3. 分析敏感属性与标签/节点度的相关性。1. 逐步增大lambda_fair观察指标变化。2. 简化公平性损失如直接使用预测概率的L2差异。3. 重新审视业务定义合理的敏感属性。加入公平性约束后模型AUC大幅下降1. 公平性约束过强(lambda_fair太大)。2. 公平性目标与准确性目标存在根本冲突如群体间真实连接概率差异很大。3. 模型容量不足无法同时拟合数据和满足约束。1. 绘制lambda_fair与AUC/DPD的权衡曲线。2. 分别计算两个群体内部的AUC看是整体下降还是某个群体下降严重。3. 尝试更复杂的模型架构。1. 调整lambda_fair寻找可接受的平衡点。2. 考虑使用Equal Opportunity等更合理的公平性概念。3. 增加模型层数或隐藏维度或尝试不同的GNN架构如GAT, GraphSAGE。训练过程不稳定损失出现NaN1. 概率计算中出现log(0)。2. 学习率过高。3. 梯度爆炸。1. 在torch.log()输入中加入极小值(如1e-15)。2. 监控梯度范数。3. 使用梯度裁剪。1. 确保概率输入在(0,1)区间添加epsilon。2. 降低学习率使用学习率调度器。3. 添加梯度裁剪torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm1.0)。无法在真实数据上定义敏感属性业务数据中无直接的人口统计学信息。1. 检查是否有代理变量如地域、消费档次、设备类型。2. 进行聚类分析看学到的节点嵌入是否隐式形成了可能代表敏感属性的簇。1. 与业务、法务部门共同确定需要保护的“群体”定义。2. 考虑无需敏感属性的公平性方法如个体公平性。3. 强调公平性审计而非实时约束。8. 最佳实践与工程建议将公平性研究落地到实际工程系统远比跑通一个实验复杂。以下是基于复现研究启示的几点核心建议明确目标选择正确的公平性概念不要一上来就优化Demographic Parity。首先进行公平性审计计算不同群体在历史数据连接数、度中心性等和模型预测结果AUC, 预测概率分布上的差异。与业务方讨论我们要避免哪种伤害是结果分布不均DP还是机会不均等Equal Opportunity或是因果上的歧视Counterfactual Fairness建议从多维度评估开始如MORAL框架理解差异来源再决定干预目标。构建全链路评估体系离线评估不仅看最终测试集的AUC和公平性指标还要看训练/验证集上的变化趋势绘制权衡曲线。在线A/B测试如果可能将公平性模型与基线模型进行小流量A/B测试监控核心业务指标如点击率、留存率以及公平性相关指标如各群体用户的推荐接受率、负面反馈率。长期监控建立仪表盘持续追踪模型预测结果在不同群体上的分布变化警惕因模型反馈循环导致的偏见放大。方法论选择预处理、处理中、后处理预处理对训练数据重采样对少数群体边过采样或重加权给少数群体边更高损失权重。简单易实现但可能过拟合。处理中In-processing如本文示例在损失函数中加入公平性正则项。更灵活但需要调参可能影响模型表达能力。后处理训练一个高性能但可能有偏的模型然后调整其输出阈值使不同群体的某些指标相等。优点不改变模型训练快速部署。缺点可能损害效用且对于链路预测这种成对任务调整阈值较为复杂。建议从后处理或简单的重加权开始快速验证公平性提升的效果和代价再考虑更复杂的处理中方法。谨慎处理敏感属性与隐私绝对不要将敏感属性如真实性别、种族作为模型输入特征除非有明确的法律依据和隐私保护措施。在训练和评估中使用敏感属性时确保数据脱敏、访问受控并符合相关法律法规如GDPR。考虑使用差分隐私或联邦学习技术在保护隐私的前提下进行公平性优化。沟通与文档将公平性目标、度量标准、干预方法以及观察到的权衡如AUC下降X%换得DPD下降Y%清晰地记录在模型卡片Model Card或系统设计文档中。与产品、运营、法务团队保持沟通确保技术上的公平性定义与业务、伦理、法律上的期望保持一致。这项关于链路预测公平性的复现研究其价值不仅在于指出了Demographic Parity的局限更在于为我们提供了一套更严谨的评估视角和方法论框架。它提醒我们在构建影响人与人之间连接的系统时公平性不是一个可以事后添加的插件而是一个需要从问题定义、数据理解、模型设计到部署监控全周期融入的核心考量。通过本文提供的代码框架和实践指南你可以开始在自己的图学习项目中进行第一轮的公平性审计与实验迈出负责任AI实践的第一步。
返回列表