楼主: 时光永痕
1218 0

[数据挖掘新闻] 使用SHAP检测偏差 [推广有奖]

  • 0关注
  • 14粉丝

svip3

学术权威

12%

(VIP/贵宾)八级

8%

威望
0
论坛币
26 个
通用积分
57.2238
学术水平
4 点
热心指数
4 点
信用等级
4 点
经验
34180 点
帖子
2732
精华
0
在线时间
321 小时
注册时间
2020-7-21
最后登录
2024-8-1

楼主
时光永痕 学生认证  发表于 2020-9-16 19:58:23 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币
使用SHAP检测偏差
StackOverflow的年度开发人员调查于今年早些时候结束,他们已经慷慨地发布了(匿名)2019年的结果进行分析。他们对世界各地的软件开发人员的经验有着丰富的见解-他们最喜欢的编辑器是什么?多少年的经验?标签或空格?至关重要的是薪水。软件工程师的薪水不错,有时既令人眼花and乱,又值得新闻报道。
科技行业还痛苦地意识到,它并不总是能实现其所谓的精英管理理想。薪水并非纯粹是功绩,故事的故事告诉我们,名牌学校,年龄,种族和性别等因素都会对薪资等结果产生影响。
机器学习能做的不仅仅是预测事情吗?它可以解释薪水,并突出显示这些因素可能导致工资差异的情况吗?本示例将概述如何使用SHAP(SHapley Additive exPlanations)扩充标准模型,以检测可能涉及其预测的单个实例,然后更深入地探究数据导致这些预测的具体原因。
模型偏差还是数据偏差(大约)?
尽管此主题通常被称为检测“模型偏差”,但是模型只是其训练数据的镜像。如果模型是“有偏见的”,那么它将从数据的历史事实中学到这一点。模型本身并不是问题;它们是分析数据以证明存在偏见的机会。
解释模型并不是什么新鲜事,并且大多数库都可以评估输入对模型的相对重要性。这些是投入影响的汇总视图。但是,某些机器学习模型的输出具有高度的个人影响:您的贷款是否得到批准?您会获得经济援助吗?您是可疑的旅行者吗?
实际上,StackOverflow提供了一个方便的计算器,可以根据调查结果估算一个人的期望薪水。我们只能推测总体预测的准确性,但是开发人员特别关心的只是他或她自己的前景。
正确的问题可能不是,数据是否表明总体存在偏差?但是,数据是否显示了个体偏见?
评估调查数据
幸运的是,2019年的数据干净无误。它包含来自大约88
此示例仅针对全职开发人员。数据集包含大量相关信息,例如多年的经验,教育,角色和人口统计信息。值得注意的是,该数据集不包含有关奖金和权益的信息,仅包含薪水。
它还对有关区块链,嘶嘶声和调查本身的态度的广泛问题做出回应。此处不包括这些内容,因为它们不太可能反映应该确定薪酬的经验和技能。同样,为简单起见,它也将只针对美国开发人员。
在建模之前,数据需要更多的转换。有几个问题可以提出多个答案,例如“作为开发人员,您对生产力的最大挑战是什么?” 这些单个问题会产生多个“是/否”响应,因此需要分解为多个“是/否”功能。
一些选择题,例如“您工作的公司或组织大约雇用多少人?” 提供“ 2-9名员工”之类的回复。这些是有效合并的连续值,将它们映射回推断的连续值(例如“ 2”)可能很有用,以便模型可以考虑其顺序和相对大小。不幸的是,该翻译是手动的,需要进行一些判断。
感兴趣的人可以在随附的笔记本中找到实现此目的的Apache Spark代码。
使用Apache Spark选择模型
借助以机器学习更友好的形式提供的数据,下一步是拟合回归模型,从而根据这些功能预测薪水。经过Spark过滤和转换后,数据集本身只有4MB,包含来自约12
xgboost,一种流行的梯度增强树包,可以在没有Spark的情况下在一台机器上在几分钟内将模型拟合到该数据。xgboost提供了许多可影响模型质量的可调“超参数”:最大深度,学习率,正则化等等。无需猜测,简单的标准做法是尝试对这些值进行大量设置,然后选择能够产生最准确模型的组合。
幸运的是,Spark又回到了这里。它可以并行构建数百个这样的模型,并收集每个模型的结果。由于数据集很小,因此很容易将其广播给工作人员,创建这些超参数的一堆组合进行尝试,并使用Spark来应用相同的简单非分布式xgboost代码,从而可以在本地为每个数据构建模型组合。
...def train_model(params):  (max_depth
  xgb_regressor = XGBRegressor(objective='reg:squarederror'
    learning_rate=learning_rate
    min_child_weight=min_child_weight
    importance_type='total_gain'
  xgb_model = xgb_regressor.fit(b_X_train.value
    eval_set=[(b_X_test.value
                                eval_metric='rmse'
  n_estimators = len(xgb_model.evals_result()['validation_0']['rmse'])
  y_pred = xgb_model.predict(b_X_test.value)
  mae = mean_absolute_error(y_pred
  rmse = sqrt(mean_squared_error(y_pred
  return (params + (n_estimators
...
max_depth =        np.unique(np.geomspace(3
learning_rate =    np.unique(np.around(np.geomspace(0.01
reg_alpha =        [0] + np.unique(np.around(np.geomspace(1
reg_lambda =       [0] + np.unique(np.around(np.geomspace(1
gamma =            np.unique(np.around(np.geomspace(5
min_child_weight = np.unique(np.geomspace(5
parallelism = 128
param_grid = [(choice(max_depth)
  choice(reg_lambda)
params_evals_models = sc.parallelize(param_grid
这将创建很多模型。要跟踪和评估结果,mlflow可以记录每个指标及其度量和超参数,并在笔记本的“实验”中查看它们。此处,将多次运行中的一个超参数与结果精度(平均绝对误差)进行比较:
在保持的验证数据集上显示出最低错误的单个模型是令人感兴趣的。平均薪水约为119
解释xgboost模型
尽管可以使用该模型预测未来的薪水,但问题是该模型对数据有何看法。准确预测工资时,最重要的特征是什么?该xgboost模型本身计算的功能重要性的概念:
import mlflow.sklearnbest_run_id = "..."model = mlflow.sklearn.load_model("runs:/" + best_run_id + "/xgboost")
sorted((zip(model.feature_importances_
最重要的因素是诸如多年的专业编码,组织的规模以及使用Windows等因素。这很有趣,但是很难解释。这些值反映相对而非绝对重要性。也就是说,效果不是以美元衡量的。重要性的定义(总收益)也特定于决策树的构建方式,很难映射为直观的解释。重要的功能甚至不一定与工资呈正相关。
更重要的是,这是总体上重要的特征的“全局”视图。直到更远的时候,性别和种族等因素才出现在此列表中。这并不意味着这些因素仍然不重要。首先,功能可以关联或交互。诸如性别之类的因素可能与树木选择的其他特征相关联,这在某种程度上掩盖了它们的作用。
更有趣的问题不是这些因素在总体上是否重要-它们的平均影响可能相对较小-而是它们在某些情况下是否具有显著作用。在这些情况下,模型告诉我们一些有关个人经验的重要信息,而对于那些个人而言,经验才是最重要的。
将SHAP应用于开发人员级别的解释
幸运的是,在过去的五年左右的时间里,出现了一套在理论上更合理地解释各个预测模型的技术。它们统称为“ 嘘 apley 一个 dditive防爆p lanations”,和方便,在Python包来实现shap。
对于任何模型,该库都会根据模型计算“ SHAP值”。这些值很容易解释,因为每个值都是以特征为单位的特征对预测的影响。SHAP值1000在这里表示“解释为+ $ 1
import shapexplainer = shap.TreeExplainer(model)shap_values = explainer.shap_values(X
SHAP值也是针对每个输入(而不是整个模型)计算的,因此这些说明可分别用于每个输入。对于每个预测,它还可以与每个特征的主要影响分开估计特征交互的影响。
总体解释功能效果
通过简单地平均其绝对值,就可以将开发人员级别的解释汇总为有关功能对整个数据集工资的影响的解释。SHAP对总体最重要功能的评估类似:
SHAP值讲述了一个类似的故事。首先,SHAP能够量化对美元薪资的影响,从而大大改善了对结果的解释。上图是每个功能对开发人员的平均期望薪水的绝对影响图。多年的专业编码经验仍然占主导地位,平均可解释将近$ 15
用SHAP值检验性别的影响
我们开始专门研究性别,种族和其他因素的影响,这些因素大概根本不能预测工资本身。这个例子将研究性别的影响,尽管这绝不表示性别是寻找的唯一或最重要的偏见类型。
性别不是二元的,调查分别识别“男人”,“女人”和“非二元,性别酷儿或性别不符合”以及“跨性别”的回答。(请注意,虽然调查还单独记录了有关性行为的回答,但此处未考虑这些回答。)SHAP计算每种行为对预期薪资的影响。对于男性开发者(仅识别为男性)而言,性别的影响不仅是成为男性的影响,而且还没有识别为女性,变性者等。
SHAP值使我们可以读取这些影响的总和,以供开发人员确定为以下四个类别:
尽管男性开发商的性别大约为-230美元至+890美元,平均约为225美元,但女性的范围更广,从-4
在评估下面的含义时,重要的是要在此处回顾数据和模型的局限性:
关联不是因果关系;“解释”预测薪资是暗示性的,但不能证明该功能直接导致薪资更高或更低
该模型并非十分准确
这只是1年的数据,仅来自美国开发商
这仅反映基本工资,而不反映奖金或股票,后者的变动范围可能更大
性别与互动特征
SHAP库提供了有趣的可视化,利用其隔离特征交互作用的能力。例如,上面的值表明,识别为男性的开发人员的薪水预计比其他人略高,但这还更多吗?这样的依赖图可以帮助:
点是开发人员。左侧的开发人员是那些不识别为男性的开发人员,而右侧的开发人员是那些却识别为男性的开发人员,主要是那些仅识别为男性的开发人员。(为了清楚起见,这些点随机分布在水平方向上。)y轴是SHAP值,或者表示是否为男性的解释说明每个开发人员的预期薪水。如上所述,那些没有被识别为男性的人的SHAP总体呈负值,其中一个变化很大,而其他人则始终呈小正SHAP值。
这种差异背后是什么?SHAP可以选择第二个特征,在给定的值的情况下,其效果变化最大(在此确定是否为男性)。它为“您的工作的结构或计划如何?”选择答案“我从事似乎最重要或最紧迫的工作”。在确定为男性的开发人员中,以这种方式回答的人员(红点)似乎具有稍高的SHAP值。在其他情况下,效果更复杂,但似乎通常具有较低的SHAP值。
解释权留给读者,但也许是:在这种意义上感到有能力的男性开发人员是否也享有较高的薪水,而其他开发人员是否喜欢与低薪职位并驾齐驱?
探索具有巨大性别影响的实例
如何调查薪资受到最大负面影响的开发商?正如可以从总体上看待性别相关功能的效果一样,也可以搜索性别相关功能对预计薪资影响最大的开发人员。这个人是女性,影响是负面的。根据该模型,预计她的收入将因其性别而每年减少约4
在这种情况下,准确的预测薪水为157
影响预测薪资的三个最积极和消极的特征是:
拥有大学学位(仅)(+ $ 18
拥有10年的专业经验(+ $ 9
标识为东亚人(+ $ 9

每周工作40小时(-$ 4
不标识为男性(-$ 4
在100-499名员工的中型组织工作(-$ 9
考虑到对不认同为男性的预期薪资的影响程度,我们可能会在这里停下来并离线调查此案的详细信息,以更好地了解该开发人员周围的环境以及她的经历,薪水或两者兼而有之,需要改变。
解释互动
-$ 4
性别因素本身对预测薪水的影响加起来约为-630美元。而是,SHAP将性别的大部分影响分配给与其他功能的交互:
gender_interactions = interaction_values[gender_feature_locs].sum(axis=0)max_c = np.argmax(gender_interactions)min_c = np.argmin(gender_interactions)
print(X.columns[max_c])
print(gender_interactions[max_c])
print(X.columns[min_c])
print(gender_interactions[min_c])
DatabaseWorkedWith_PostgreSQL
110.64005
Ethnicity_East_Asian
-1372.6714
识别为女性并使用PostgreSQL会对预测薪资产生轻微的积极影响,而对确定为东亚地区的预测薪资则产生负面影响。在这种情况下,很难以这种粒度级别解释这些值,但是可以使用这种附加级别的解释。
将SHAP与Apache Spark一起应用
给定模型,SHAP值是针对每一行独立计算的,因此也可以与Spark并行进行。下面的示例并行计算SHAP值,并类似地查找与性别相关的SHAP值过大的开发人员:
X_df = pruned_parsed_df.drop("ConvertedComp").repartition(16)X_columns = X_df.columns
def add_shap(rows):
  rows_pd = pd.DataFrame(rows
  shap_values = explainer.shap_values(rows_pd.drop(["Respondent"]
  return [Row(*([int(rows_pd["Respondent"])] + [float(f) for f in shap_values])) for i in range(len(shap_values))]
shap_df = X_df.rdd.mapPartitions(add_shap).toDF(X_columns)
effects_df = shap_df.\
  withColumn("gender_shap"
  select("Respondent"
top_effects_df = effects_df.filter(abs(col("gender_shap")) >= 2500).orderBy("gender_shap")
聚集SHAP值
当有大量预测需要使用SHAP评估时,应用Spark是有利的。给定该输出,还可以使用Spark将结果聚类,例如,将k-means均等:
assembler = VectorAssembler(inputCols=[c for c in to_review_df.columns if c != "Respondent"]
clusterer = BisectingKMeans().setFeaturesCol("features").setK(50).setMaxIter(50).setSeed(0)
cluster_model = clusterer.fit(assembled_df)
transformed_df = cluster_model.transform(assembled_df).select("Respondent"
与性别相关的SHAP总体影响最大的集群可能需要进一步调查。集群中那些受访者的SHAP值是多少?就整个开发人员群体而言,集群的成员是什么样的?
min_shap_cluster_df = transformed_df.filter("prediction = 5").\  join(effects_df
  select(gender_cols).groupBy(gender_cols).count().orderBy(gender_cols)
all_shap_df = X_df.select(gender_cols).groupBy(gender_cols).count().orderBy(gender_cols)
expected_ratio = transformed_df.filter("prediction = 5").count() / X_df.count()
display(min_shap_cluster_df.join(all_shap_df
  withColumn("ratio"
  orderBy("ratio"))
例如,在这个集群中代表开发人员(仅女性)的开发人员的比例几乎是开发人员总人数的2.8倍。鉴于先前的分析,这不足为奇。可以进一步研究该类别,以评估特定于该组的其他因素,这些因素导致总体较低的预期薪资。
结论
SHAP的这种类型的分析可以在任何模型上运行,也可以大规模运行。作为一种分析工具,它可以将模型转变为数据侦探,以发现其预测表明需要进行更多检查的单个实例。SHAP的输出易于解释,并产生直观的图,企业用户可以逐案评估。
当然,这种分析不仅限于检查性别,年龄或种族偏见问题。更一般地说,它可以应用于客户流失模型。在这里,问题不只是“这个客户会流失吗?” 但是“为什么客户会搅动?” 由于价格而取消的客户可能会获得折扣,而由于使用量有限而取消的客户可能需要追加销售。
最后,该分析可以作为模型验证过程的一部分来运行。模型验证通常侧重于模型的整体准确性。它还应关注模型的“推理”,或哪些特征对预测的贡献最大。使用SHAP,它还可以帮助检测何时太多的单个预测的解释与总体功能的重要性不一致。

关注 CDA人工智能学院 ,回复“录播”获取更多人工智能精选直播视频!


二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:interactions Apache Spark explanations interaction transformed

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注cda
拉您进交流群
GMT+8, 2026-1-17 04:05