Ga naar hoofdinhoud

Bias meten in machine learning: de statistische biastest

Deze tutorial definieert statistische bias in een machinelearningmodel en laat zien hoe je de test uitvoert op synthetische data.
DataRobot Inc
DataRobot Inc

Maak je gratis account aan

Oefen en volg je voortgang.

Ga verder met GoogleDoor verder te gaan, accepteer je ons Gebruiksvoorwaarden, onze Privacybeleid en dat je gegevens in de VS worden opgeslagen.

Dit artikel is geschreven door Sarah Khatry en Haniyeh Mahmoudian, data scientists bij DataRobot.

De vraag naar bias in machinelearningmodellen heeft de afgelopen jaren veel aandacht gekregen. Verhalen over ontsporende modellen halen het nieuws, en mensenrechtenjuristen, politici en journalisten hebben allemaal bijgedragen aan het gesprek over welke ethiek en waarden we terug willen zien in de modellen die we bouwen.

Menselijke vooringenomenheid is een lastige kwestie en niet altijd eenvoudig te definiëren, maar bias in machine learning is uiteindelijk wiskundig. Er zijn veel verschillende soorten tests die je op je model kunt uitvoeren om verschillende vormen van bias in de voorspellingen op te sporen. Welke test je kiest, hangt vooral af van wat jij belangrijk vindt en de context waarin het model wordt gebruikt.

Eén van de breedst toepasbare tests is statistische pariteit; in deze hands-on tutorial lopen we die stap voor stap door. Let op: bias wordt altijd beoordeeld ten opzichte van verschillende groepen mensen die worden onderscheiden door een beschermd kenmerk in je data, zoals ras, gender, leeftijd, seksualiteit, nationaliteit, enzovoort.

Met statistische pariteit is je doel te meten of de verschillende groepen een gelijke kans hebben op een gunstige uitkomst. Een klassiek voorbeeld is een wervingsmodel, waarbij je wilt waarborgen dat mannelijke en vrouwelijke sollicitanten een gelijke kans hebben om aangenomen te worden. In een bevooroordeeld model zie je juist dat één groep bevoorrecht is met een hogere kans op aanname, terwijl de andere groep benadeeld wordt.

Om te laten zien hoe dit in de praktijk werkt, construeren we eerst synthetische data met vooraf ingestelde bias, bevestigen we via analyse dat de data de bedoelde situatie weerspiegelt, en passen we tot slot de test voor statistische pariteit toe.

Synthetische data genereren

In deze tutorial gebruiken we het pandas-pakket in Python, maar elke stap in dit proces is ook te reproduceren in R.

import pandas as pd

Om synthetische data te genereren met één beschermd kenmerk en modelvoorspellingen, moeten we eerst een paar inputs specificeren: het totale aantal records, het beschermde kenmerk zelf (hier twee generieke waarden, A en B), en de modelvoorspelling die hoort bij de gunstige uitkomst, in dit voorbeeld de waarde 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

Net als in het echt zijn groepen A en B mogelijk niet gelijk verdeeld in onze data. In de onderstaande code hebben we bepaald dat 60% van de populatie in onze data uit de bevoorrechte groep B komt, die 30% kans heeft op de gunstige uitkomst. De benadeelde groep A vormt de overige 40% van de data en heeft slechts 15% kans op de gunstige uitkomst.

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

Voor elk record in de data wijzen we willekeurig een beschermde groep en een voorspelling toe, waarbij we de eerder gespecificeerde bias als gewichten gebruiken. Daarna maken we een dataframe van de lijst met records.

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'])

De data interpreteren

Nu we onze synthetische data hebben, gaan we analyseren wat we gebouwd hebben. Voor elke groep, A versus B, wat is hun kansverdeling op het behalen van de gunstige of ongunstige uitkomst?

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

Als we de tabel bekijken, is het niet moeilijk te zien dat groep B bijna dubbel zoveel kans heeft op de gunstige uitkomst, met een waarschijnlijkheid van 28,6%. Onze synthetische data was ontworpen met een kans van 30%, dus we zitten daar dicht bij. We slaan de kansen vervolgens op in een dictionary.

Omdat de data willekeurig wordt gegenereerd, kan jouw code een iets ander resultaat geven.

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

De test voor statistische pariteit

Voor elke groep geeft statistische pariteit de verhouding van hun kans op de gunstige uitkomst ten opzichte van de kans op de gunstige uitkomst van de bevoorrechte groep. We lopen de dictionary langs van elke beschermde groep met hun kans op een gunstige uitkomst om de verhoudingen te berekenen.

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

Voor de bevoorrechte groep, B, is de score voor statistische pariteit 1, zoals het hoort. Voor de andere groep, A, is de score 0,526, wat aangeeft dat zij grofweg de halve kans hebben op de gunstige uitkomst vergeleken met groep B.

De statistische biastest geeft een eenvoudige beoordeling van hoe verschillend de voorspelde uitkomsten kunnen zijn voor geselecteerde groepen in je data. Het doel van het meten van bias is tweeledig. Enerzijds levert deze test een transparante maatstaf op, wat de communicatie makkelijker en concreter maakt. Idealiter is het identificeren van bias echter de eerste stap om die in je model te verminderen. Dit is een hot topic in de machine learning, met veel technieken die worden ontwikkeld om verschillende soorten bias en modelaanpakken te adresseren.

Met de juiste combinatie van test- en mitigatietechnieken kun je je model iteratief verbeteren, bias verminderen en nauwkeurigheid behouden. Je kunt machinelearningsystemen zo ontwerpen dat ze niet alleen leren van historische uitkomsten, maar ook jouw waarden weerspiegelen in toekomstige besluitvorming.

Ontdek hoe je AI bouwt die je kunt vertrouwen met DataRobot.

Onderwerpen

Gerelateerd