如何輕松檢查你的機器學習模型是否公平?
譯文【51CTO.com快譯】我們生活在日益分裂的世界。在世界上一些地區,種族和性別之間的差異和不平等現象在加劇。用于建模的數據大體上體現了數據源。世界可能有偏見,因此數據和模型可能會體現這一點。我們提出了一種方法,機器學習工程師可以輕松檢查模型是否有偏見。現在我們的公平性工具僅適用于分類模型。
案例分析
為了表明dalex公平性模塊(https://dalex.drwhy.ai/)的功能,我們將使用著名的德國信貸數據集(https://archive.ics.uci.edu/ml/datasets/statlog+(german+credit+data)為每個信貸申請者賦予風險。這個簡單的任務可能需要使用可解釋的決策樹分類器。
- # imports
- import dalex as dx
- import numpy as np
- from sklearn.compose import ColumnTransformer
- from sklearn.pipeline import Pipeline
- from sklearn.preprocessing import OneHotEncoder
- from sklearn.tree import DecisionTreeClassifier
- # credit data
- data = dx.datasets.load_german()
- # risk is the target
- X = data.drop(columns='risk')
- y = data.risk
- categorical_features = ['sex', 'job', 'housing', 'saving_accounts', "checking_account", 'purpose']
- categorical_transformer = Pipeline(steps=[
- ('onehot', OneHotEncoder(handle_unknown='ignore'))
- ])
- preprocessor = ColumnTransformer(transformers=[
- ('cat', categorical_transformer, categorical_features)
- ])
- clf = Pipeline(steps=[
- ('preprocessor', preprocessor),
- ('classifier', DecisionTreeClassifier(max_depth=7, random_state=123))
- ])
- clf.fit(X, y)
- exp = dx.Explainer(clf, X, y)
一旦有了dx.Explainer,我們需要執行方法model_fairness(),以便它可以利用protected矢量來計算子組中的所有必要度量,該矢量是一個數組或列表,列出了表明每一個觀察對象(個人)的性別、種族或國籍等方面的敏感屬性。除此之外,我們需要指出哪個子組(即protected的哪個獨特元素)具有最高特權,這可以通過privileged參數來完成,本例中將是較年長男性。
- # array with values like male_old, female_young, etc.
- protected = data.sex + '_' + np.where(data.age < 25, 'young', 'old')
- privileged = 'male_old'
- fobject = exp.model_fairness(protected = protected, privileged=privileged)
該對象有許多屬性,我們不會遍歷每一個屬性,而是著重介紹一種方法和兩個圖。
那么,我們的模型是否有偏見?
這個問題很簡單,但由于偏見的性質,答案將是要看情況。但是這種方法從不同的視角來度量偏見,因此確保沒有任何有偏見的模型是漏網之魚。要檢查公平性,就得使用fairness_check()方法。
- fobject.fairness_check(epsilon = 0.8) # default epsilon
以下內容是來自上述代碼的控制臺輸出。
- Bias detected in 1 metric: FPR
- Conclusion: your model cannot be called fair because 1 metric score exceeded acceptable limits set by epsilon.
- It does not mean that your model is unfair but it cannot be automatically approved based on these metrics.
- Ratios of metrics, based on 'male_old'. Parameter 'epsilon' was set to 0.8 and therefore metrics should be within (0.8, 1.25)
- TPR ACC PPV FPR STP
- female_old 1.006508 1.027559 1.000000 0.765051 0.927739
- female_young 0.971800 0.937008 0.879594 0.775330 0.860140
- male_young 1.030369 0.929134 0.875792 0.998532 0.986014
FPR(誤報率)這個度量發現了偏見。上述輸出表明無法自動批準模型(如上述輸出中所述),因此得由用戶來決定。我認為這不是公平的模型。較低的FPR意味著特權子組比無特權子組更容易出現誤報。
詳述fairness_check()
我們獲得有關偏見、結論和度量比率原始DataFrame的信息。有幾個度量:TPR(正陽性率)、ACC(準確度)、PPV(陽性預測值)、FPR(假陽性率)和STP(統計奇偶性)。這些度量來自每個無特權子組的混淆矩陣(https://en.wikipedia.org/wiki/Confusion_matrix),然后除以基于特權子組的度量值。有三種可能的結論:
- # not fair
- Conclusion: your model is not fair because 2 or more metric scores exceeded acceptable limits set by epsilon.
- # neither fair or not
- Conclusion: your model cannot be called fair because 1 metric score exceeded acceptable limits set by epsilon.It does not mean that your model is unfair but it cannot be automatically approved based on these metrics.
- # fair
- Conclusion: your model is fair in terms of checked fairness metrics.
DA真正公平模型不會超出任何度量,但是當真實值(目標)依賴敏感屬性時,事情會變得復雜,并超出本文探討的范圍。簡而言之,一些度量會不一樣,但不一定會超出用戶的閾值。如果您想了解更多,建議您閱讀《公平性和機器學習》一書(https://fairmlbook.org/),尤其是第二章。
但有人會問:為何我們的模型不公平?我們基于什么依據來決定?
回答這個問題很棘手,但到目前為止判斷公平性的方法似乎是最佳方法。每個子組的分數通常應接近特權子組的分數。從數學的角度來看,特權度量和無特權度量的分數之間的比率應接近1。該值越接近1,表明模型越公平。但為了稍微放寬該標準,這樣表述更合理:
其中ε是介于0和1之間的值,它應該是該比率的最小可接受值。默認情況下,它是0.8,遵循招聘中常見的五分之四規則(80%規則)。很難在度量的公平和歧視差異之間找到一個非任意邊界;檢查度量的比率是否恰好為1毫無意義,因為如果比率為0.99會怎樣? 這就是為什么我們決定選擇0.8作為默認的ε,因為對于可接受的歧視程度而言,它是有形閾值的唯一已知值。當然,用戶可以根據需要更改這個值。
偏見也可以繪出來
有兩個偏見檢測圖可用(不過有更多的方法可以直觀顯示偏見)。
- fairness_check——直觀顯示fairness_check()方法
- metric_scores——直觀顯示metric_scores屬性,它是度量的原始分數。
類型只需傳遞到plot方法的type參數。
- fbject.plot()
上圖顯示了與公平性檢查輸出相似的內容。度量名已改成更標準的公平性等效項,但是公式指出了我們引用的度量。上圖很直觀:如果條柱到達紅色區域,表示度量超出基于ε的范圍。條柱長度等效于| 1-M |,其中M是無特權度分數除以特權度量分數(因此就像之前的公平性檢查一樣)。
- fobject.plot(type=’metric_scores’)
度量分數圖輔以公平性檢查很好地表明了度量及其比率。在這里,這些點是原始的度量分數。垂直線表示特權度量分數。離那條線越近越好。
可以將多個模型放在一個圖中,以便輕松相互比較。不妨添加幾個模型,直觀顯示metric_scores:
- from sklearn.ensemble import RandomForestClassifier
- from sklearn.linear_model import LogisticRegression
- from sklearn.preprocessing import StandardScaler
- # create models
- numeric_features = ['credit_amount', 'duration', 'age']
- numeric_transformer = Pipeline(steps=[
- ('scaler', StandardScaler())])
- categorical_transformer = Pipeline(steps=[
- ('onehot', OneHotEncoder(handle_unknown='ignore'))])
- preprocessor = ColumnTransformer(
- transformers=[
- ('cat', categorical_transformer, categorical_features),
- ('num', numeric_transformer, numeric_features)])
- clf_forest = Pipeline(steps=[('preprocessor', preprocessor),
- ('classifier', RandomForestClassifier(random_state=123, max_depth=4))]).fit(X,y)
- clf_logreg = Pipeline(steps=[('preprocessor', preprocessor),
- ('classifier', LogisticRegression(random_state=123))]).fit(X,y)
- # create Explainer objects
- exp_forest = dx.Explainer(clf_forest, X,y, verbose = False)
- exp_logreg = dx.Explainer(clf_logreg, X,y, verbose = False)
- # create fairness explanations
- fobject_forest = exp_forest.model_fairness(protected, privileged)
- fobject_logreg = exp_logreg.model_fairness(protected, privileged)
- # lets see their metric scores
- fobject.plot(objects=[fobject_forest, fobject_logreg], type = "metric_scores")
上述代碼的輸出。
現在不妨檢查基于fairness_check的圖:
我們可以看到RandomForestClassifier在綠色區域內,因此就這些度量而言,它是公平的。另一方面,LogisticRegression在三個度量方面抵達紅色區域,因此不能稱之為公平的。
每個圖都是交互式的,是使用python可視化包plotly繪制的。
結語
dalex中的公平性模塊是確保模型公平的統一且可訪問的方法。還有其他方法可以直觀顯示模型偏見,請務必查看一下!將來會增加緩解偏見的方法。長期計劃是增添對 individual fairness和 fairness in regression的支持。
務必看一下。您可以使用以下命令來安裝dalex:
- pip install dalex –U
原文標題:How to easily check if your Machine Learning model is fair?,作者:Jakub Wiśniewski
【51CTO譯稿,合作站點轉載請注明原文譯者和出處為51CTO.com】