Personalizzazione di MinDiffModel

introduzione

Nella maggior parte dei casi, utilizzando MinDiffModel direttamente come descritto in "Integrazione MinDiff con MinDiffModel" guida è sufficiente. Tuttavia, è possibile che tu abbia bisogno di un comportamento personalizzato. Le due ragioni principali di ciò sono:

  • Il keras.Model si utilizza ha un comportamento personalizzato che si desidera conservare.
  • Si desidera che il MinDiffModel si comporti in modo diverso da quello predefinito.

In entrambi i casi, è necessario creare una sottoclasse MinDiffModel per ottenere i risultati desiderati.

Impostare

pip install -q --upgrade tensorflow-model-remediation
import tensorflow as tf
tf.get_logger().setLevel('ERROR')  # Avoid TF warnings.
from tensorflow_model_remediation import min_diff
from tensorflow_model_remediation.tools.tutorials_utils import uci as tutorials_utils

Innanzitutto, scarica i dati. Per brevità, la logica preparazione ingresso è stato fattorizzato nella helper funzioni come descritto nella guida di preparazione ingresso . Puoi leggere la guida completa per i dettagli su questo processo.

# Original Dataset for training, sampled at 0.3 for reduced runtimes.
train_df = tutorials_utils.get_uci_data(split='train', sample=0.3)
train_ds = tutorials_utils.df_to_dataset(train_df, batch_size=128)

# Dataset needed to train with MinDiff.
train_with_min_diff_ds = (
    tutorials_utils.get_uci_with_min_diff_dataset(split='train', sample=0.3))

Conservazione delle personalizzazioni del modello originale

tf.keras.Model è progettato per essere facilmente personalizzabile tramite sottoclassi come descritto qui . Se il modello è personalizzato implementazioni che si desidera conservare in sede di applicazione MinDiff, è necessario creare una sottoclasse MinDiffModel .

Modello personalizzato originale

Per vedere come è possibile conservare le personalizzazioni, creare un modello personalizzato che imposta un attributo al True quando la sua personalizzato train_step si chiama. Questa non è una personalizzazione utile, ma servirà a illustrare il comportamento.

class CustomModel(tf.keras.Model):

  # Customized train_step
  def train_step(self, *args, **kwargs):
    self.used_custom_train_step = True  # Marker that we can check for.
    return super(CustomModel, self).train_step(*args, **kwargs)

La formazione di un tale modello sarebbe lo stesso aspetto di un normale Sequential modello.

model = tutorials_utils.get_uci_model(model_class=CustomModel)  # Use CustomModel.

model.compile(optimizer='adam', loss='binary_crossentropy')

_ = model.fit(train_ds.take(1), epochs=1, verbose=0)

# Model has used the custom train_step.
print('Model used the custom train_step:')
print(hasattr(model, 'used_custom_train_step'))  # True
Model used the custom train_step:
True

Sottoclasse MinDiffModel

Se si dovesse cercare di usare MinDiffModel direttamente, il modello non avrebbe usato il costume train_step .

model = tutorials_utils.get_uci_model(model_class=CustomModel)
model = min_diff.keras.MinDiffModel(model, min_diff.losses.MMDLoss())

model.compile(optimizer='adam', loss='binary_crossentropy')

_ = model.fit(train_with_min_diff_ds.take(1), epochs=1, verbose=0)

# Model has not used the custom train_step.
print('Model used the custom train_step:')
print(hasattr(model, 'used_custom_train_step'))  # False
Model used the custom train_step:
False

Per poter utilizzare il corretto train_step metodo, hai bisogno di una classe personalizzata che le sottoclassi sia MinDiffModel e CustomModel .

class CustomMinDiffModel(min_diff.keras.MinDiffModel, CustomModel):
  pass  # No need for any further implementation.

La formazione questo modello utilizzerà il train_step da CustomModel .

model = tutorials_utils.get_uci_model(model_class=CustomModel)

model = CustomMinDiffModel(model, min_diff.losses.MMDLoss())

model.compile(optimizer='adam', loss='binary_crossentropy')

_ = model.fit(train_with_min_diff_ds.take(1), epochs=1, verbose=0)

# Model has used the custom train_step.
print('Model used the custom train_step:')
print(hasattr(model, 'used_custom_train_step'))  # True
Model used the custom train_step:
True

Personalizzazione comportamenti predefiniti di MinDiffModel

In altri casi, si consiglia di cambiare i comportamenti di default specifiche di MinDiffModel . La maggior parte dei casi l'uso comune di questo sta cambiando il comportamento disimballaggio predefinito per gestire correttamente i vostri dati se non si utilizza pack_min_diff_data .

Quando si impacchettano i dati in un formato personalizzato, potrebbe apparire come segue.

def _reformat_input(inputs, original_labels):
  min_diff_data = min_diff.keras.utils.unpack_min_diff_data(inputs)
  original_inputs = min_diff.keras.utils.unpack_original_inputs(inputs)

  return ({
      'min_diff_data': min_diff_data,
      'original_inputs': original_inputs}, original_labels)

customized_train_with_min_diff_ds = train_with_min_diff_ds.map(_reformat_input)

I customized_train_with_min_diff_ds set di dati resi lotti composti di tuple (x, y) dove x è un dict contenente min_diff_data e original_inputs ed y è original_labels .

for x, _ in customized_train_with_min_diff_ds.take(1):
  print('Type of x:', type(x))  # dict
  print('Keys of x:', x.keys())  # 'min_diff_data', 'original_inputs'
Type of x: <class 'dict'>
Keys of x: dict_keys(['min_diff_data', 'original_inputs'])

Questo formato dei dati non è ciò che MinDiffModel si aspetta di default e passando customized_train_with_min_diff_ds ad esso comporterebbe un comportamento imprevisto. Per risolvere questo problema dovrai creare la tua sottoclasse.

class CustomUnpackingMinDiffModel(min_diff.keras.MinDiffModel):

  def unpack_min_diff_data(self, inputs):
    return inputs['min_diff_data']

  def unpack_original_inputs(self, inputs):
    return inputs['original_inputs']

Con questa sottoclasse puoi allenarti come con gli altri esempi.

model = tutorials_utils.get_uci_model()
model = CustomUnpackingMinDiffModel(model, min_diff.losses.MMDLoss())

model.compile(optimizer='adam', loss='binary_crossentropy')

_ = model.fit(customized_train_with_min_diff_ds, epochs=1)
77/77 [==============================] - 4s 30ms/step - loss: 0.6690 - min_diff_loss: 0.0395

Limitazioni di un personalizzato MinDiffModel

La creazione di un custom MinDiffModel fornisce una grande quantità di flessibilità per i casi d'uso più complessi. Tuttavia, ci sono ancora alcuni casi limite che non supporterà.

Preelaborazione o convalida di ingressi prima call

La limitazione maggiore per una sottoclasse di MinDiffModel è che richiede l' x componente dei dati di ingresso (cioè il primo o unico elemento nel batch restituita dal tf.data.Dataset ) da passare attraverso senza preelaborazione o della convalida call .

Questo è semplicemente perché il min_diff_data è confezionato nella x componente dei dati di ingresso. Qualsiasi pre-elaborazione o di convalida non si aspettano la struttura aggiuntiva contenente min_diff_data e probabilmente romperà.

Se la preelaborazione o la convalida è facilmente personalizzabile (ad es. scomposta nel proprio metodo), questo può essere facilmente risolto sovrascrivendolo per garantire che gestisca correttamente la struttura aggiuntiva.

Un esempio con la convalida potrebbe essere simile a questo:

class CustomMinDiffModel(min_diff.keras.MinDiffModel, CustomModel):

  # Override so that it correctly handles additional `min_diff_data`.
  def validate_inputs(self, inputs):
    original_inputs = self.unpack_original_inputs(inputs)
    ...  # Optionally also validate min_diff_data
    # Call original validate method with correct inputs
    return super(CustomMinDiffModel, self).validate(original_inputs)

Se la pre-elaborazione o la convalida non è facilmente personalizzabile, quindi utilizzando MinDiffModel non può funzionare per voi e sarà necessario integrare MinDiff senza di essa come descritto in questa guida .

Collisioni di nomi di metodi

E 'possibile che il modello dispone di metodi i cui nomi si scontrano con quelle attuate in MinDiffModel (vedi elenco completo dei metodi pubblici nella documentazione API ).

Questo è problematico solo se questi verranno chiamati su un'istanza del modello (piuttosto che internamente in qualche altro metodo). Mentre altamente improbabile, se si è in questa situazione sarà necessario sia override e rinomina alcuni metodi o, se non possibile, potrebbe essere necessario prendere in considerazione l'integrazione MinDiff senza MinDiffModel come descritto in questa guida sull'argomento .

Risorse addizionali