Dostosowywanie modelu MinDiff

Wstęp

W większości przypadków, przy użyciu MinDiffModel bezpośrednio, jak to opisano w „Integracja MinDiff z MinDiffModel” przewodnik jest wystarczająca. Możliwe jednak, że będziesz potrzebować niestandardowego zachowania. Dwa główne powody tego to:

  • keras.Model używasz ma niestandardowe zachowania, które chcesz zachować.
  • Chcesz MinDiffModel zachowywać się inaczej niż domyślny.

W obu przypadkach trzeba będzie podklasy MinDiffModel do osiągnięcia pożądanych rezultatów.

Ustawiać

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

Najpierw pobierz dane. Dla zwięzłości, logika przygotowanie wejścia zostały uwzględnione z pomocnikiem do funkcji opisanych w przewodniku przygotowania wejścia . Możesz przeczytać pełny przewodnik, aby uzyskać szczegółowe informacje na temat tego procesu.

# 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))

Zachowanie oryginalnych dostosowań modelu

tf.keras.Model jest zaprojektowany do być łatwo dostosowane poprzez instacji jak opisano tutaj . Jeśli model został dostosowany implementacje, które chcesz zachować przy stosowaniu MinDiff, trzeba będzie podklasy MinDiffModel .

Oryginalny niestandardowy model

Aby zobaczyć, jak można zachować dostosowania, utworzyć własny model, który ustawia atrybut na True gdy jego zwyczaj train_step jest tzw. Nie jest to przydatne dostosowanie, ale posłuży do zilustrowania zachowania.

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)

Szkolenie taki model będzie wyglądać tak samo jak normalny Sequential modelu.

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

Podklasa MinDiffModel

Jeśli było spróbować skorzystać MinDiffModel bezpośrednio, model nie będzie użyć niestandardowego 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

W celu skorzystania z prawidłową train_step metody, trzeba mieć klasę niestandardową podklasy zarówno MinDiffModel i CustomModel .

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

Szkolenie tego modelu użyje train_step z 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

Dostosowywanie domyślnych zachowań MinDiffModel

W innych przypadkach, może chcesz zmienić konkretnych zachowań domyślnych MinDiffModel . Najczęstszym przypadkiem użycia tego jest zmiana domyślnego rozpakowywania zachowanie prawidłowo obsługiwać swoje dane, jeśli nie używać pack_min_diff_data .

Podczas pakowania danych w niestandardowy format może to wyglądać następująco.

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)

W customized_train_with_min_diff_ds zestawu danych zwraca porcje składające się z krotki (x, y) , gdzie x jest dict zawierający min_diff_data i original_inputs i y jest 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'])

Ten format danych nie jest tym, co MinDiffModel spodziewa się domyślnie i przechodzącej customized_train_with_min_diff_ds do niego by spowodować nieoczekiwane zachowanie. Aby to naprawić, musisz stworzyć własną podklasę.

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

Z tą podklasą możesz trenować tak jak w przypadku innych przykładów.

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

Ograniczenia dostosowany MinDiffModel

Tworzenie niestandardowego MinDiffModel zapewnia ogromną ilość elastyczności dla bardziej skomplikowanych przypadków użycia. Jednak nadal istnieją pewne skrajne przypadki, których nie obsługuje.

Przerób lub walidacji wejść przed call

Największym ograniczeniem dla podklasy MinDiffModel jest to, że wymaga on x składową danych wejściowych (to znaczy pierwsza cyfra lub element wsadu zwróconego przez tf.data.Dataset ), aby przechodzić przez bez wstępnego lub walidacji call .

Jest to po prostu dlatego, że min_diff_data jest pakowany do x składnika danych wejściowych. Wszelkie przerób lub walidacja nie będzie oczekiwać dodatkowego strukturę zawierającą min_diff_data i prawdopodobnie pęknie.

Jeśli przetwarzanie wstępne lub walidację można łatwo dostosować (np. uwzględnić we własnej metodzie), można to łatwo rozwiązać, zastępując je, aby zapewnić prawidłowe działanie dodatkowej struktury.

Przykład z walidacją może wyglądać tak:

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)

Jeśli przerób lub walidacji nie jest łatwo konfigurowalny, a następnie za pomocą MinDiffModel nie może pracować dla Ciebie i trzeba zintegrować MinDiff bez niego w sposób opisany w niniejszym przewodniku .

Kolizje nazw metod

Jest możliwe, że dany model posiada metody, których nazwy sprzeczne z tymi, które zastosowano w MinDiffModel (zobacz pełną listę metod publicznych w dokumentacji API ).

Jest to problematyczne tylko wtedy, gdy zostaną one wywołane na instancji modelu (a nie wewnętrznie w jakiejś innej metodzie). Chociaż mało prawdopodobne, jeśli jesteś w tej sytuacji trzeba będzie albo ręcznym i zmienić niektóre metody lub, jeśli nie jest to możliwe, być może trzeba rozważyć włączenie MinDiff bez MinDiffModel w sposób opisany w niniejszym przewodniku na temat .

Dodatkowe zasoby