Vai al contenuto principale

Misurare il bias nel machine learning: il test di bias statistico

Questo tutorial definisce il bias statistico in un modello di machine learning e mostra come eseguire il test su dati sintetici.
DataRobot Inc
DataRobot Inc

Crea il tuo account gratuito

Pratica and corso your progress.

Continua con GoogleContinuando, accetti la nostra Termini di utilizzo, i nostri Informativa sulla privacy e il fatto che i tuoi dati sono archiviati negli USA.

Questo articolo è stato scritto da Sarah Khatry e Haniyeh Mahmoudian, data scientist in DataRobot.

La questione del bias nei modelli di machine learning ha attirato molta attenzione negli ultimi anni. Le storie di modelli che sbagliano fanno notizia, e giuristi umanitari, politici e giornalisti hanno tutti contribuito alla discussione su quali principi etici e valori vogliamo vedere riflessi nei modelli che costruiamo.

Se il bias umano è un tema spinoso e non sempre facile da definire, il bias nel machine learning è, in fin dei conti, matematico. Esistono molti tipi di test che puoi eseguire sul tuo modello per identificare diverse forme di bias nelle sue previsioni. Quale test eseguire dipende principalmente da ciò che ti interessa e dal contesto in cui viene usato il modello.

Uno dei test più ampiamente applicabili è la parità statistica, che questo tutorial pratico ti guiderà a eseguire. Il bias viene sempre valutato rispetto a diversi gruppi di persone identificati da un attributo protetto nei tuoi dati, ad esempio razza, genere, età, orientamento sessuale, nazionalità, ecc.

Con la parità statistica, l’obiettivo è misurare se i diversi gruppi hanno pari probabilità di ottenere un esito favorevole. Un esempio classico è un modello di assunzione, per cui vorresti assicurarti che candidati uomini e donne abbiano la stessa probabilità di essere assunti. In un modello con bias, invece, identificherai che un gruppo è privilegiato con una probabilità più alta di essere assunto, mentre l’altro è svantaggiato.

Per mostrare come funziona in pratica, costruiremo prima dati sintetici con un bias predefinito, poi confermeremo tramite analisi che i dati riflettono la situazione che avevamo in mente e, infine, applicheremo il test di parità statistica.

Generazione di dati sintetici

In questo tutorial useremo il pacchetto pandas in Python, ma ogni passaggio può essere riprodotto anche in R.

import pandas as pd

Per generare dati sintetici con un attributo protetto e le previsioni del modello, dobbiamo prima specificare alcuni input: il numero totale di record, l’attributo protetto stesso (qui due valori generici, A e B) e la previsione del modello associata all’esito favorevole, in questo esempio il valore 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

Come nella vita reale, i gruppi A e B potrebbero non essere distribuiti in modo uniforme nei nostri dati. Nel codice seguente abbiamo deciso che il 60% della popolazione nei dati apparterrà al gruppo privilegiato B, che ha il 30% di probabilità di ricevere l’esito favorevole. Il gruppo non privilegiato A costituirà il restante 40% dei dati e avrà solo il 15% di probabilità dell’esito favorevole.

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

Per ogni record dei dati, assegniamo casualmente un gruppo protetto e una previsione, usando come pesi il bias specificato, quindi creiamo un dataframe dall’elenco dei record.

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

Interpretazione dei dati

Ora che abbiamo i nostri dati sintetici, analizziamo cosa abbiamo costruito. Per ciascun gruppo, A rispetto a B, qual è la loro probabilità di classe di ottenere l’esito favorevole o sfavorevole?

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

Osservando la tabella, non è difficile vedere che il gruppo B ha una probabilità quasi doppia di ottenere l’esito favorevole, con una probabilità del 28,6%. I nostri dati sintetici erano stati progettati per avere una probabilità del 30%, quindi siamo vicini all’obiettivo. Salviamo poi le probabilità in un dizionario.

Poiché è generato casualmente, il tuo codice potrebbe dare un risultato leggermente diverso.

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

Il test di parità statistica

Per ciascun gruppo, la parità statistica restituisce il rapporto tra la sua probabilità di ottenere l’esito favorevole e la probabilità del gruppo privilegiato di ottenere lo stesso esito. Iteriamo sul dizionario di ciascun gruppo protetto con la sua probabilità di esito favorevole per costruire i rapporti.

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

Per il gruppo privilegiato, B, il punteggio di parità statistica è 1, come previsto. Per l’altro gruppo, A, il punteggio è 0,526, il che indica che ha all’incirca metà della probabilità di ottenere l’esito favorevole rispetto al gruppo B.

Il test di bias statistico fornisce una valutazione semplice di quanto possano differire gli esiti previsti per gruppi specifici nei tuoi dati. L’obiettivo di misurare il bias è duplice. Da un lato, questo test produce una metrica trasparente, rendendo la comunicazione più semplice e concreta. Idealmente, però, identificare il bias è il primo passo per iniziare a mitigarlo nel tuo modello. Si tratta di un tema molto attivo di ricerca nel machine learning, con molte tecniche in fase di sviluppo per gestire diversi tipi di bias e approcci di modellazione.

Con la giusta combinazione di tecniche di test e mitigazione, diventa possibile migliorare progressivamente il tuo modello, ridurre il bias e preservare l’accuratezza. Puoi progettare sistemi di machine learning che non si limitino a imparare dagli esiti storici, ma riflettano i tuoi valori nelle decisioni future.

Scopri come creare un’IA affidabile con DataRobot.

Argomenti

Correlato