Ottimizzatore Keras TensorFlow personalizzato


30

Supponiamo di voler scrivere una classe di ottimizzazione personalizzata conforme tf.kerasall'API (utilizzando la versione TensorFlow> = 2.0). Sono confuso sul modo documentato di farlo rispetto a ciò che viene fatto nelle implementazioni.

La documentazione per gli tf.keras.optimizers.Optimizer stati ,

  ### Write a customized optimizer.
  If you intend to create your own optimization algorithm, simply inherit from
  this class and override the following methods:

    - resource_apply_dense (update variable given gradient tensor is dense)
    - resource_apply_sparse (update variable given gradient tensor is sparse)
    - create_slots (if your optimizer algorithm requires additional variables)

Tuttavia, l'attuale tf.keras.optimizers.Optimizerimplementazione non definisce un resource_apply_densemetodo, ma non definiscono un privato dall'aspetto _resource_apply_densestub . Allo stesso modo, non ci sono resource_apply_sparseo create_slotsmetodi, ma ci sono uno _resource_apply_sparsestub di metodo e una _create_slotschiamata di metodo .

In ufficiali tf.keras.optimizers.Optimizersottoclassi (utilizzando tf.keras.optimizers.Adamcome esempio), ci sono _resource_apply_dense, _resource_apply_sparsee _create_slotsmetodi, e non ci sono tali metodi senza la sottolineatura che porta.

Ci sono simili metodi leader di sottolineatura in leggermente meno ufficiali tf.keras.optimizers.Optimizersottoclassi (ad esempio, tfa.optimizers.MovingAverageda tensorflow Addons: _resource_apply_dense, _resource_apply_sparse, _create_slots).

Un altro punto di confusione per me è che alcuni degli ottimizzatori TensorFlow Addons hanno la precedenza sul apply_gradientsmetodo (ad es. tfa.optimizers.MovingAverage), Mentre gli tf.keras.optimizersottimizzatori no.

Inoltre, ho notato che il apply_gradientsmetodo di tf.keras.optimizers.Optimizermetodo chiama_create_slots , ma la tf.keras.optimizers.Optimizerclasse base non ha un _create_slotsmetodo. Quindi, sembra che un _create_slotsmetodo debba essere definito in una sottoclasse di ottimizzatore se quella sottoclasse non ha la precedenza apply_gradients.


Domande

Qual è il modo corretto di sottoclasse un tf.keras.optimizers.Optimizer? In particolare,

  1. La tf.keras.optimizers.Optimizerdocumentazione elencata in alto significa semplicemente sovrascrivere le versioni di sottolineatura dei metodi che menzionano (ad esempio, _resource_apply_denseinvece di resource_apply_dense)? In tal caso, esistono garanzie API su questi metodi dall'aspetto privato che non cambiano il loro comportamento nelle versioni future di TensorFlow? Quali sono le firme di questi metodi?
  2. Quando si scavalcherebbe apply_gradientsoltre ai _apply_resource_[dense|sparse]metodi?

Modificare. Problema aperto su GitHub: # 36449


1
Questo potrebbe essere qualcosa da segnalare come un problema di documentazione agli sviluppatori. Sembra sicuramente che quei metodi da sovrascrivere dovrebbero includere il carattere di sottolineatura iniziale nella documentazione, ma in ogni caso, come dici tu, non ci sono informazioni sulla loro firma e sul loro esatto scopo. Può anche darsi che i nomi dei metodi senza carattere di sottolineatura (e documentati) siano pianificati per essere aggiunti (come con get_config), ma non dovrebbero ancora apparire nella documentazione pubblica .
jdehesa,

Per le firme, puoi sempre guardare la dichiarazione di _resource_apply_denseo _resource_apply_sparsee vederne l'utilizzo negli ottimizzatori implementati. Sebbene possa non essere, penso, un'API pubblica con garanzie di stabilità, direi che è abbastanza sicuro usarli. Dovrebbero solo fornire una migliore guida in questo aspetto.
jdehesa,

Sono d'accordo che questo è un problema di documentazione con TensorFlow. Hai creato un problema per questo nel repository Github tf? In tal caso, potresti condividere il link qui?
jpgard,

Risposte:


3

Ho implementato Keras AdamW in tutte le principali versioni di TF & Keras: ti invito a esaminare optimizer_v2.py . Diversi punti:

  • Dovresti ereditare OptimizerV2, che è in realtà ciò che hai collegato; è la classe base più recente e attuale per gli tf.kerasottimizzatori
  • Hai ragione in (1) - questo è un errore di documentazione; i metodi sono privati, in quanto non sono pensati per essere utilizzati direttamente dall'utente.
  • apply_gradients(o qualsiasi altro metodo) viene ignorato solo se il valore predefinito non soddisfa ciò che è necessario per un determinato ottimizzatore; nell'esempio collegato, è solo un componente aggiuntivo di una riga dell'originale
  • "Quindi, sembra che un _create_slotsmetodo debba essere definito in una sottoclasse di ottimizzatori se quella sottoclasse non ha la precedenza apply_gradients" - i due non sono correlati; è una coincidenza.

  • Qual è la differenza tra _resource_apply_densee _resource_apply_sparse?

Gli ultimi si occupano di strati sparsi - ad es. Embedding- ed ex con tutto il resto; esempio .

  • Quando dovrei usare _create_slots()?

Quando si definiscono i trainable tf.Variable ; esempio: i momenti del primo e del secondo ordine dei pesi (ad es. Adam). Utilizza add_slot().

Praticamente, ogni volta che non si utilizza _create_slots(); è come impostare gli attributi di classe, ma con passaggi di preelaborazione aggiuntivi per garantire la correttezza nell'uso. Così Python int, float, tf.Tensor, tf.Variable, e altri. (Avrei dovuto usarlo di più in Keras AdamW).


Nota : mentre i miei ottimizzatori collegati funzionano correttamente e sono veloci quanto gli originali, il codice segue le migliori pratiche TensorFlow e può essere ancora più veloce; Non lo consiglio come "riferimento ideale". Ad esempio alcuni oggetti Python (ad esempio int) dovrebbero essere tensori; eta_tè definito come a tf.Variable, ma immediatamente sostituito come a tf.Tensorin _applymetodi. Non necessariamente un grosso problema, ma non ho avuto il tempo di rinnovare.


2
  1. Sì, questo sembra essere un errore di documentazione. I nomi di sottolineatura precedenti sono i metodi corretti da sovrascrivere. Correlato è l'ottimizzatore non Keras che li ha tutti definiti, ma non implementati nella classe base https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/training/optimizer.py
  def _create_slots(self, var_list):
    """Create all slots needed by the variables.
    Args:
      var_list: A list of `Variable` objects.
    """
    # No slots needed by default
    pass

  def _resource_apply_dense(self, grad, handle):
    """Add ops to apply dense gradients to the variable `handle`.
    Args:
      grad: a `Tensor` representing the gradient.
      handle: a `Tensor` of dtype `resource` which points to the variable
       to be updated.
    Returns:
      An `Operation` which updates the value of the variable.
    """
    raise NotImplementedError()

  def _resource_apply_sparse(self, grad, handle, indices):
    """Add ops to apply sparse gradients to the variable `handle`.
    Similar to `_apply_sparse`, the `indices` argument to this method has been
    de-duplicated. Optimizers which deal correctly with non-unique indices may
    instead override `_resource_apply_sparse_duplicate_indices` to avoid this
    overhead.
    Args:
      grad: a `Tensor` representing the gradient for the affected indices.
      handle: a `Tensor` of dtype `resource` which points to the variable
       to be updated.
      indices: a `Tensor` of integral type representing the indices for
       which the gradient is nonzero. Indices are unique.
    Returns:
      An `Operation` which updates the value of the variable.
    """
    raise NotImplementedError()
  1. Non lo so apply_dense. Per prima cosa, se lo sostituisci, il codice menziona che una DistributionStrategy per replica potrebbe essere "pericolosa"
    # TODO(isaprykin): When using a DistributionStrategy, and when an
    # optimizer is created in each replica, it might be dangerous to
    # rely on some Optimizer methods.  When such methods are called on a
    # per-replica optimizer, an exception needs to be thrown.  We do
    # allow creation per-replica optimizers however, because the
    # compute_gradients()->apply_gradients() sequence is safe.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.