
Dieser Artikel wurde von Sarah Khatry und Haniyeh Mahmoudian, Data Scientists bei DataRobot, verfasst.
Die Frage nach Bias in Machine-Learning-Modellen steht seit einigen Jahren stark im Fokus. Fehlentscheidungen von Modellen schaffen es in die Schlagzeilen, und Menschenrechtsjuristinnen, Politiker und Journalistinnen diskutieren, welche Ethik und Werte sich in den Systemen widerspiegeln sollen, die wir entwickeln.
Während menschlicher Bias komplex und oft schwer zu fassen ist, ist Bias im Machine Learning am Ende des Tages mathematisch. Es gibt viele verschiedene Tests, mit denen du unterschiedliche Verzerrungen in den Vorhersagen deines Modells aufspüren kannst. Welcher Test sinnvoll ist, hängt vor allem davon ab, was dir wichtig ist und in welchem Kontext das Modell eingesetzt wird.
Einer der am breitesten einsetzbaren Tests ist die statistische Parität, die wir in diesem praxisnahen Tutorial Schritt für Schritt durchgehen. Bias wird dabei stets relativ zu unterschiedlichen Personengruppen bewertet, die in deinen Daten über ein geschütztes Merkmal identifiziert werden, z. B. Ethnie, Geschlecht, Alter, sexuelle Orientierung, Staatsangehörigkeit usw.
Mit statistischer Parität misst du, ob verschiedene Gruppen die gleiche Wahrscheinlichkeit haben, ein vorteilhaftes Ergebnis zu erreichen. Ein klassisches Beispiel ist ein Einstellungsmodell, bei dem du sicherstellen willst, dass Bewerberinnen und Bewerber die gleiche Chance auf eine Einstellung haben. In einem verzerrten Modell erkennst du dagegen, dass eine Gruppe privilegiert ist und eine höhere Einstellungswahrscheinlichkeit hat, während die andere benachteiligt ist.
Um zu zeigen, wie das in der Praxis funktioniert, erzeugen wir zunächst synthetische Daten mit einem vorab festgelegten Bias, prüfen dann per Analyse, ob die Daten dem gewünschten Szenario entsprechen, und führen anschließend den Statistical-Parity-Test durch.
Synthetische Daten erzeugen
In diesem Tutorial nutzen wir das Paket pandas in Python, aber jeder Schritt lässt sich auch in R reproduzieren.
import pandas as pd
Um synthetische Daten mit einem geschützten Merkmal und Modellvorhersagen zu generieren, brauchen wir zunächst ein paar Eingaben: die Gesamtanzahl der Datensätze, das geschützte Merkmal selbst (hier zwei generische Ausprägungen A und B) und die Modellvorhersage, die dem vorteilhaften Ergebnis zugeordnet ist, in diesem Beispiel der Wert 1.
num_row = 1000 # number of rows in the data
prot_att = 'prot_att' # column name for protected attribute
model_pred_bin = 'prediction' # column name for predictions
pos_label = 1 # prediction value associated to positive/favorable outcome
prot_group = ['A','B'] # two groups in our protected attribute
Wie im echten Leben sind die Gruppen A und B in unseren Daten möglicherweise nicht gleich verteilt. Im folgenden Code legen wir fest, dass 60% der Population zur privilegierten Gruppe B gehören, die eine 30%ige Chance auf das vorteilhafte Ergebnis hat. Die benachteiligte Gruppe A stellt die verbleibenden 40% der Daten und hat nur eine Wahrscheinlichkeit von 15% für das vorteilhafte Ergebnis.
priv_g = 'B' # privileged group
priv_g_rate = 60 # 60% of the population is from group B
priv_p_rate = 30 # 30% of the predictions for group B was for favorable outcome 1
unpriv_p_rate = 15 # 15% of the predictions for group A was for favorable outcome 1
biased_list_priv = [prot_group[0]] * (100 - priv_g_rate) + [prot_group[1]] * priv_g_rate
biased_list_pos_priv = [0] * (100 - priv_p_rate) + [1] * priv_p_rate
biased_list_pos_unpriv = [0] * (100 - unpriv_p_rate) + [1] * unpriv_p_rate
Für jeden Datensatz weisen wir zufällig eine geschützte Gruppe und eine Vorhersage zu, wobei wir die zuvor definierten Verzerrungen als Gewichte verwenden, und erstellen daraus anschließend ein DataFrame.
list_df = [] # empty list to store the synthetic records
for i in range(0, num_row):
# generating random value representing protected groups with bias towards B
prot_rand = random.choices(biased_list_priv)[0]
if prot_rand == priv_g:
prot_g = priv_g
# generating random binary value representing prediction with bias towards 0
pred = random.choices(biased_list_pos_priv)[0]
# adding the new record to the list
list_df.append([prot_g,pred])
else:
prot_g = prot_group[0]
pred = random.choices(biased_list_pos_unpriv)[0]
list_df.append([prot_g,pred])
# create a dataframe from the list
df = pd.DataFrame(list_df,columns=['prot_att','prediction'])
Die Daten interpretieren
Jetzt, wo wir unsere synthetischen Daten haben, analysieren wir, was wir gebaut haben. Für jede Gruppe, A vs. B: Wie hoch ist ihre Klassenwahrscheinlichkeit, ein vorteilhaftes bzw. nachteiliges Ergebnis zu erzielen?
df_group = (df.groupby([prot_att])[model_pred_bin].value_counts() / df.groupby([prot_att])[
model_pred_bin].count()).reset_index(name='probability')
print(df_group)
prot_att prediction probability
0 A 0 0.849490
1 A 1 0.150510
2 B 0 0.713816
3 B 1 0.286184
Ein Blick auf die Tabelle zeigt: Gruppe B hat fast die doppelte Chance auf das vorteilhafte Ergebnis, mit einer Wahrscheinlichkeit von 28,6%. Unsere synthetischen Daten wurden für 30% ausgelegt, wir liegen also nah dran. Anschließend speichern wir die Wahrscheinlichkeiten in einem Dictionary.
Da die Daten zufällig generiert werden, können deine Ergebnisse leicht abweichen.
prot_att_dic = {}
for att in prot_group:
temp = df_group[(df_group[prot_att] == att) & (df_group[model_pred_bin] == pos_label)]
prob = float(temp['probability'])
prot_att_dic[att] = prob
Der Statistical-Parity-Test
Für jede Gruppe liefert die statistische Parität das Verhältnis ihrer Wahrscheinlichkeit für das vorteilhafte Ergebnis im Vergleich zur Wahrscheinlichkeit der privilegierten Gruppe. Wir iterieren über das Dictionary der geschützten Gruppen mit ihren Wahrscheinlichkeiten, um die Verhältnisse zu berechnen.
prot_test_res = {}
for k in prot_att_dic.keys():
res = float(prot_att_dic[k] / prot_att_dic[priv_g])
prot_test_res[k] = res
for key in prot_test_res.keys():
value = prot_test_res[key]
print(key, ' : ', value)
A : 0.5259207131128314
B : 1.0
Für die privilegierte Gruppe B ist der Statistical-Parity-Score 1, wie erwartet. Für die andere Gruppe A liegt der Score bei 0,526, was bedeutet, dass sie in etwa nur halb so häufig das vorteilhafte Ergebnis erreicht wie Gruppe B.
Der statistische Bias-Test bietet eine einfache Einschätzung, wie stark sich die vorhergesagten Ergebnisse für ausgewählte Gruppen in deinen Daten unterscheiden können. Das Ziel der Bias-Messung ist zweifach: Einerseits entsteht eine transparente, leicht kommunizierbare Kennzahl. Idealerweise ist die Identifikation von Bias aber der erste Schritt, um ihn im Modell zu mindern. Dies ist ein aktives Forschungsfeld im Machine Learning, in dem viele Verfahren entwickelt werden, um unterschiedliche Arten von Bias und Modellierungsansätzen zu berücksichtigen.
Mit der richtigen Kombination aus Tests und Gegenmaßnahmen lässt sich dein Modell iterativ verbessern, Bias reduzieren und Genauigkeit erhalten. So entwickelst du Machine-Learning-Systeme, die nicht nur aus historischen Ergebnissen lernen, sondern auch deine Werte in künftigen Entscheidungen abbilden.
Finde heraus, wie du vertrauenswürdige KI aufbaust – mit DataRobot.
