Preparazione dei dati MinDiff

introduzione

Quando implementi MinDiff, dovrai prendere decisioni complesse mentre scegli e modellare il tuo input prima di passarlo al modello. Queste decisioni determineranno in gran parte il comportamento di MinDiff all'interno del tuo modello.

Questa guida tratterà gli aspetti tecnici di questo processo, ma non discuterà come valutare un modello per l'equità o come identificare particolari sezioni e metriche per la valutazione. Si prega di consultare la guida Fairness Indicatori per dettagli su questo.

Per dimostrare MinDiff, questa guida utilizza il reddito dataset UCI . Il compito del modello è prevedere se un individuo ha un reddito superiore a $ 50.000, in base a vari attributi personali. Questa guida presuppone c'è un divario problematica nel FNR (tasso di falsi negativi) fra "Male" e "Female" fette e il proprietario del modello (si) ha deciso di applicare MinDiff per affrontare la questione. Per ulteriori informazioni sugli scenari in cui si può scegliere di applicare MinDiff, consultare la pagina dei requisiti .

MinDiff funziona penalizzando la differenza nei punteggi di distribuzione tra gli esempi in due insiemi di dati. Questa guida dimostrerà come scegliere e costruire questi set MinDiff aggiuntivi e come impacchettare tutto insieme in modo che possa essere passato a un modello per l'addestramento.

Impostare

pip install -q --upgrade tensorflow-model-remediation
import tensorflow as tf
from tensorflow_model_remediation import min_diff
from tensorflow_model_remediation.tools.tutorials_utils import uci as tutorials_utils

Dati originali

A scopo dimostrativo e per ridurre i tempi di esecuzione, questa guida utilizza solo una frazione campione del set di dati sul reddito dell'UCI. In un ambiente di produzione reale, verrebbe utilizzato l'intero set di dati.

# Sampled at 0.3 for reduced runtimes.
train = tutorials_utils.get_uci_data(split='train', sample=0.3)

print(len(train), 'train examples')
9768 train examples

Conversione in tf.data.Dataset

MinDiffModel richiede che l'ingresso sia un tf.data.Dataset . Se stavi utilizzando un formato di input diverso prima di integrare MinDiff, dovrai convertire i dati di input.

Utilizzare tf.data.Dataset.from_tensor_slices per convertire a tf.data.Dataset .

dataset = tf.data.Dataset.from_tensor_slices((x, y, weights))
dataset.shuffle(...)  # Optional.
dataset.batch(batch_size)

Vedere Model.fit documentazione per i dettagli sulle equivalenze tra i due metodi di input.

In questa guida, l'input viene scaricato come Pandas DataFrame e quindi necessita di questa conversione.

# Function to convert a DataFrame into a tf.data.Dataset.
def df_to_dataset(dataframe, shuffle=True):
  dataframe = dataframe.copy()
  labels = dataframe.pop('target')
  ds = tf.data.Dataset.from_tensor_slices((dict(dataframe), labels))
  if shuffle:
    ds = ds.shuffle(buffer_size=5000)  # Reasonable but arbitrary buffer_size.
  return ds

# Convert the train DataFrame into a Dataset.
original_train_ds = df_to_dataset(train)

Creazione di dati MinDiff

Durante l'addestramento, MinDiff incoraggerà il modello a ridurre le differenze nelle previsioni tra due set di dati aggiuntivi (che possono includere esempi dal set di dati originale). La selezione di questi due set di dati è la decisione chiave che determinerà l'effetto che MinDiff avrà sul modello.

I due set di dati dovrebbero essere selezionati in modo tale che la disparità di prestazioni che si sta tentando di correggere sia evidente e ben rappresentata. Poiché l'obiettivo è quello di ridurre un divario tra FNR "Male" e "Female" fette, ciò significa creare un insieme di dati con un solo marcati positivamente "Male" esempi e un altro con solo marcati positivamente "Female" esempi; questi saranno i set di dati MinDiff.

Per prima cosa, esamina i dati presenti.

female_pos = train[(train['sex'] == ' Female') & (train['target'] == 1)]
male_pos = train[(train['sex'] == ' Male') & (train['target'] == 1)]
print(len(female_pos), 'positively labeled female examples')
print(len(male_pos), 'positively labeled male examples')
385 positively labeled female examples
2063 positively labeled male examples

È perfettamente accettabile creare set di dati MinDiff da sottoinsiemi del set di dati originale.

Anche se non ci sono 5.000 o più positivi "Male" esempi come raccomandato nella guida requisiti , ci sono oltre 2.000, ed è ragionevole cercare con che molti prima di raccogliere più dati.

min_diff_male_ds = df_to_dataset(male_pos)

Positivi "Female" esempi, tuttavia, sono molto più scarse a 385. Questo è probabilmente troppo piccolo per la buona prestazione e così richiederà tirando in ulteriori esempi.

full_uci_train = tutorials_utils.get_uci_data(split='train')
augmented_female_pos = full_uci_train[((full_uci_train['sex'] == ' Female') &
                                       (full_uci_train['target'] == 1))]
print(len(augmented_female_pos), 'positively labeled female examples')
1179 positively labeled female examples

L'utilizzo dell'intero set di dati ha più che triplicato il numero di esempi che possono essere utilizzati per MinDiff. È ancora basso ma è sufficiente provare come primo passaggio.

min_diff_female_ds = df_to_dataset(augmented_female_pos)

Entrambi i set di dati MinDiff sono significativamente più piccoli dei 5.000 o più esempi consigliati. Sebbene sia ragionevole tentare di applicare MinDiff con i dati correnti, potrebbe essere necessario prendere in considerazione la raccolta di dati aggiuntivi se si osservano prestazioni scadenti o sovradattamento durante l'allenamento.

utilizzando tf.data.Dataset.filter

In alternativa, è possibile creare i due set di dati MinDiff direttamente dall'originale convertito Dataset .

# Male
def male_predicate(x, y):
  return tf.equal(x['sex'], b' Male') and tf.equal(y, 0)

alternate_min_diff_male_ds = original_train_ds.filter(male_predicate).cache()

# Female
def female_predicate(x, y):
  return tf.equal(x['sex'], b' Female') and tf.equal(y, 0)

full_uci_train_ds = df_to_dataset(full_uci_train)
alternate_min_diff_female_ds = full_uci_train_ds.filter(female_predicate).cache()

Le risultanti alternate_min_diff_male_ds e alternate_min_diff_female_ds saranno equivalenti in uscita min_diff_male_ds e min_diff_female_ds rispettivamente.

Costruire il tuo set di dati di allenamento

Come passaggio finale, i tre set di dati (i due appena creati e l'originale) devono essere uniti in un unico set di dati che può essere passato al modello.

Batch dei set di dati

Prima dell'unione, i set di dati devono essere raggruppati.

  • Il set di dati originale può utilizzare lo stesso batch utilizzato prima dell'integrazione di MinDiff.
  • Non è necessario che i set di dati MinDiff abbiano la stessa dimensione batch del set di dati originale. Con ogni probabilità, uno più piccolo funzionerà altrettanto bene. Sebbene non sia nemmeno necessario che abbiano la stessa dimensione di batch l'uno dell'altro, si consiglia di farlo per ottenere le migliori prestazioni.

Anche se non strettamente necessario, si consiglia di utilizzare drop_remainder=True per i due insiemi di dati MinDiff come questo farà sì che essi hanno lotti omogenei.

original_train_ds = original_train_ds.batch(128)  # Same as before MinDiff.

# The MinDiff datasets can have a different batch_size from original_train_ds
min_diff_female_ds = min_diff_female_ds.batch(32, drop_remainder=True)
# Ideally we use the same batch size for both MinDiff datasets.
min_diff_male_ds = min_diff_male_ds.batch(32, drop_remainder=True)

Imballaggio le serie di dati con pack_min_diff_data

Una volta che i set di dati sono stati preparati, impacchettali in un singolo set di dati che verrà poi passato al modello. Un singolo batch del set di dati risultante conterrà un batch di ciascuno dei tre set di dati preparati in precedenza.

È possibile farlo utilizzando l'apposita utils funzione nel tensorflow_model_remediation pacchetto:

train_with_min_diff_ds = min_diff.keras.utils.pack_min_diff_data(
    original_dataset=original_train_ds,
    sensitive_group_dataset=min_diff_female_ds,
    nonsensitive_group_dataset=min_diff_male_ds)

E questo è tutto! Sarete in grado di utilizzare altre util funzioni nel pacchetto per singoli lotti decomprimere, se necessario.

for inputs, original_labels in train_with_min_diff_ds.take(1):
  # Unpacking min_diff_data
  min_diff_data = min_diff.keras.utils.unpack_min_diff_data(inputs)
  min_diff_examples, min_diff_membership = min_diff_data
  # Unpacking original data
  original_inputs = min_diff.keras.utils.unpack_original_inputs(inputs)

Con i tuoi dati appena formati, ora sei pronto per applicare MinDiff nel tuo modello! Per informazioni su come questo viene fatto, si prega di dare un'occhiata alle altre guide che iniziano con integrazione MinDiff con MinDiffModel .

Utilizzo di un formato di imballaggio personalizzato (opzionale)

Puoi decidere di mettere insieme i tre set di dati nel modo che preferisci. L'unico requisito è che dovrai assicurarti che il modello sappia come interpretare i dati. L'implementazione predefinita di MinDiffModel presuppone che i dati sono stati confezionati utilizzando min_diff.keras.utils.pack_min_diff_data .

Un modo semplice per formattare il vostro input come si vuole è quello di trasformare i dati come passo finale dopo aver utilizzato min_diff.keras.utils.pack_min_diff_data .

# Reformat input to be a dict.
def _reformat_input(inputs, original_labels):
  unpacked_min_diff_data = min_diff.keras.utils.unpack_min_diff_data(inputs)
  unpacked_original_inputs = min_diff.keras.utils.unpack_original_inputs(inputs)

  return {
      'min_diff_data': unpacked_min_diff_data,
      'original_data': (unpacked_original_inputs, original_labels)}

customized_train_with_min_diff_ds = train_with_min_diff_ds.map(_reformat_input)

Il vostro modello avrà bisogno di sapere come leggere questo ingresso personalizzato come dettagliato nella guida Personalizzazione MinDiffModel .

for batch in customized_train_with_min_diff_ds.take(1):
  # Customized unpacking of min_diff_data
  min_diff_data = batch['min_diff_data']
  # Customized unpacking of original_data
  original_data = batch['original_data']

Risorse addizionali

Questa guida delinea il processo e il processo decisionale che puoi seguire ogni volta che applichi MinDiff. Il resto delle guide si basa su questo quadro. Per rendere questo più semplice, la logica trovata in questa guida è stata scomposta nelle funzioni di supporto:

  • get_uci_data : Questa funzione è già utilizzato in questa guida. Esso restituisce un DataFrame contenente i dati di reddito UCI dalla scissione indicato campionato a qualsiasi tasso è indicato (100% se non specificato).
  • df_to_dataset : Questa funzione converte un DataFrame in un tf.data.Dataset descritta in questa guida con la funzionalità di essere in grado di passare la batch_size come parametro.
  • get_uci_with_min_diff_dataset : restituisce Questa funzione un tf.data.Dataset contenente sia i dati originali ei dati MinDiff imballato insieme utilizzando la bonifica Biblioteca Modello util funzioni come descritto in questa guida.

Il resto delle guide si baserà su queste per mostrare come utilizzare altre parti della libreria.