«Che cosa avrei dovuto cambiare»: spiegazioni controfattuali con DiCE

A chi si è visto rifiutare un prestito non interessa quanto ha pesato il reddito: interessa che cosa fare perché la prossima volta sia sì. È una domanda diversa da quella a cui rispondono SHAP e LIME, e ha strumenti suoi. Con il vincolo che separa una spiegazione utile da una che consiglia di ringiovanire di vent'anni.

Un medico può dirti due cose dopo gli esami. La prima: «il colesterolo ha inciso per il 40% sul tuo indice di rischio, il fumo per il 30%». La seconda: «se scendi sotto 200 e smetti di fumare, esci dalla fascia di rischio». Sono entrambe vere e riguardano lo stesso modello, ma solo la seconda si può usare per fare qualcosa lunedì mattina.

Nell’interpretabilità del machine learning la prima è l’attribuzione — quanto ogni feature ha spinto verso quella risposta — ed è ciò che danno LIME e SHAP. La seconda è la spiegazione controfattuale: il punto più vicino al tuo caso in cui il modello avrebbe risposto diversamente. Quando la spiegazione la legge la persona che ha subito la decisione, e non il data scientist che ha addestrato il modello, quasi sempre la domanda vera è la seconda.

Stesso modello, stessa pratica rifiutata, due risposte a due domande diverse. «Perché no?» attribuzione: SHAP, LIME reddito anzianità debito età dice come è composta la decisione non dice che cosa fare «E allora che faccio?» controfattuale: DiCE reddito 28.000 → 31.500 anzianità 14 mesi → 24 mesi debito 9.000 = 9.000 età 31 = 31 (bloccata) indica un percorso, non una diagnosi e solo su ciò che si può cambiare La riga «età, bloccata» è il vincolo che rende utile il metodo: senza, il consiglio sarebbe di ringiovanire

L’attribuzione scompone la decisione presa; il controfattuale descrive la decisione più vicina che sarebbe stata diversa. Il secondo è azionabile solo se qualcuno gli ha detto quali colonne una persona può davvero cambiare.

Che cosa siano attribuzione e controfattuale, e perché siano risposte a domande diverse, il libro lo costruisce per intero nel capitolo sulle spiegazioni locali — LIME, i valori di Shapley e i controfattuali insieme. Qui si passa direttamente a produrli.

Leggi «Spiegazioni locali» nel libro →

Generarli con DiCE

DiCE — Diverse Counterfactual Explanations — nasce dal lavoro di Ramaravind Mothilal, Amit Sharma e Chenhao Tan presentato a FAT* 2020. Funziona con modelli scikit-learn, PyTorch e TensorFlow, e la sequenza minima è tre oggetti e una chiamata.

pip install dice-ml
import dice_ml

dati = dice_ml.Data(
    dataframe=train_df,
    continuous_features=["reddito", "anzianita_mesi", "debito", "eta"],
    outcome_name="approvato",
)
modello = dice_ml.Model(model=clf, backend="sklearn")
spiegatore = dice_ml.Dice(dati, modello, method="random")

risultato = spiegatore.generate_counterfactuals(
    pratica_rifiutata,          # un DataFrame di una riga
    total_CFs=4,
    desired_class="opposite",   # «fammi vedere i casi in cui sarebbe stato sì»
)
risultato.visualize_as_dataframe(show_only_changes=True)

Il parametro method sceglie come si cercano i punti: random campiona, genetic usa un algoritmo evolutivo, gradient sfrutta i gradienti quando il modello è differenziabile. Il primo è il più veloce e va benissimo per capire se il metodo dice qualcosa di sensato sul tuo problema; conviene salire dopo, non prima.

Il vincolo che separa l’utile dall’assurdo

Eseguito così com’è, il codice qui sopra produce quasi sempre almeno un consiglio ridicolo: abbassa l’età di vent’anni, cambia paese di nascita, riduci il numero di figli. Non è un difetto della libreria: il modello è una funzione di quelle colonne, e la funzione non sa che alcune non si possono muovere. Deve saperlo chi la usa, e va detto esplicitamente.

risultato = spiegatore.generate_counterfactuals(
    pratica_rifiutata,
    total_CFs=4,
    desired_class="opposite",
    # solo ciò su cui la persona può agire
    features_to_vary=["reddito", "anzianita_mesi", "debito"],
    # e dentro limiti realistici: nessuno raddoppia lo stipendio in un mese
    permitted_range={"reddito": [28000, 34000], "anzianita_mesi": [14, 30]},
)

Questa è la parte del lavoro che non si può automatizzare e che decide la qualità del risultato. features_to_vary traccia il confine fra ciò che una persona può cambiare e ciò che è, e va discusso con chi conosce il dominio. permitted_range aggiunge la scala del possibile: un controfattuale valido ma irraggiungibile è una risposta formalmente corretta e praticamente offensiva.

Perché servono più risposte, non una

Il nome della libreria mette al centro la diversità, e non è un vezzo. Gli autori sostengono che una spiegazione controfattuale efficace debba avere due proprietà: la fattibilità delle azioni proposte dato il contesto e i vincoli di chi le riceve, e la diversità fra i controfattuali presentati.

La ragione pratica è che una sola strada è quasi sempre la strada sbagliata per qualcuno. «Aumenta il reddito di 3.500 euro» non serve a chi ha un contratto bloccato; «riduci il debito di 4.000» non serve a chi non ha risparmi. Presentandone quattro diversi, la probabilità che almeno uno sia percorribile per quella persona cresce molto — ed è il motivo per cui il metodo cerca punti distanti fra loro invece di limitarsi al più vicino in assoluto.

Controllare che funzionino davvero

Un controfattuale è il risultato di una ricerca, non di una dimostrazione, e la ricerca può fermarsi su un punto che il modello classifica ancora come prima — soprattutto con i metodi campionari e con vincoli stretti, dove lo spazio in cui cercare si restringe molto. Il controllo costa tre righe e va fatto sempre, perché consegnare a una persona un consiglio che non ottiene il risultato promesso è peggio che non consegnare nulla.

proposte = risultato.cf_examples_list[0].final_cfs_df
esito = clf.predict(proposte.drop(columns=["approvato"]))
print(f"controfattuali validi: {esito.sum()} su {len(proposte)}")

Se la resa è bassa, le strade sono due e conviene provarle in quest’ordine: allargare i permitted_range, che spesso sono stati stretti a occhio, e solo dopo passare a method="genetic", che cerca meglio e costa di più.

Quello che un controfattuale non è

Due avvertenze, e sono serie perché il metodo si presta a essere frainteso proprio da chi ne trae più conforto.

Non è una relazione causale. Dice dove passa il confine decisionale del modello, non che cosa succederebbe nel mondo. Se il modello ha imparato che chi ha un’anzianità lavorativa maggiore ripaga meglio, il controfattuale dirà «aspetta dieci mesi»; ma se quella correlazione nascondeva un’altra variabile, aspettare dieci mesi cambierà la risposta del modello senza cambiare il rischio reale. Il controfattuale spiega il modello, mai la realtà.

È anche un manuale per aggirarlo. La stessa informazione che aiuta una persona a migliorare la propria posizione insegna a un’altra il valore minimo da dichiarare per superare la soglia. Nei domini dove il dato è auto-dichiarato — questionari, moduli, autocertificazioni — pubblicare controfattuali precisi significa pubblicare la mappa del confine. È una decisione da prendere consapevolmente, non un dettaglio di implementazione.

E la normativa

C’è una ragione in più per cui vale la pena costruirseli adesso, e riguarda la forma che le spiegazioni dovranno avere. L’articolo 86 dell’AI Act — «diritto alla spiegazione dei singoli processi decisionali» — riconosce a chi è interessato da una decisione presa con un sistema ad alto rischio il diritto di ottenere dal deployer spiegazioni «chiare e significative» sul ruolo del sistema nella procedura decisionale e sui principali elementi della decisione presa.

Su quando quell’obbligo morda, il calendario è in movimento: il grosso degli adempimenti sull’alto rischio è stato rinviato, ed è una vicenda che merita di essere seguita a parte. Ma la direzione della norma è leggibile fin d’ora, ed è interessante per chi progetta: «spiegazioni chiare e significative» destinate alla persona interessata assomigliano molto più a una frase in italiano su che cosa avrebbe cambiato la decisione che a un grafico a barre di valori di Shapley. Il secondo è uno strumento da laboratorio; la prima è quello che una persona può leggere e contestare.

Un’attribuzione spiega il modello a chi l’ha costruito. Un controfattuale spiega la decisione a chi l’ha subita. Sono due destinatari diversi, e solo uno dei due ha dei diritti.

Vale la pena provarlo su un modello che hai già in produzione: mezz’ora, quattro controfattuali su dieci casi rifiutati, letti ad alta voce. Se suonano assurdi, non è il metodo che non funziona — sono i vincoli che nessuno ha ancora scritto, ed è comunque una cosa che era meglio scoprire adesso.

I commenti sono riservati agli iscritti.

Accedi per commentare