web-dev-qa-db-fra.com

Optimiseur TensorFlow Keras personnalisé

Supposons que je veuille écrire une classe d'optimiseur personnalisée conforme à tf.keras API (en utilisant la version TensorFlow> = 2.0). Je suis confus quant à la manière documentée de le faire par rapport à ce qui est fait dans les implémentations.

La documentation de tf.keras.optimizers.Optimizerétats ,

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

Cependant, le tf.keras.optimizers.Optimizer l'implémentation ne définit pas un resource_apply_dense, mais elle le fait définit une apparence privée _resource_apply_dense stub de méthode . De même, il n'y a pas de resource_apply_sparse ou create_slots méthodes, mais il existe _resource_apply_sparse stub de méthode et un _create_slots appel de méthode .

En officiel tf.keras.optimizers.Optimizer sous-classes (en utilisant tf.keras.optimizers.Adam comme exemple), il y a _resource_apply_dense , _resource_apply_sparse et _create_slots méthodes, et il n'y a pas de telles méthodes sans le soulignement de tête.

Il existe des méthodes similaires de soulignement dans _ _ légèrement moins officielles tf.keras.optimizers.Optimizer sous-classes (par exemple, tfa.optimizers.MovingAverage des modules complémentaires TensorFlow: _resource_apply_dense , _resource_apply_sparse , _create_slots ).

Un autre point déconcertant pour moi est que certains des optimiseurs TensorFlow Addons aussi remplacent le apply_gradients méthode (par exemple, tfa.optimizers.MovingAverage ), tandis que le tf.keras.optimizers les optimiseurs ne le font pas.

De plus, j'ai remarqué que le apply_gradients méthode de tf.keras.optimizers.Optimizer méthode appelle _create_slots , mais la base tf.keras.optimizers.Optimizer la classe n'a pas de _create_slots méthode. Il semble donc qu'un _create_slots méthode doit être définie dans une sous-classe d'optimisation si cette sous-classe ne remplace pas apply_gradients.


Des questions

Quelle est la bonne façon de sous-classer un tf.keras.optimizers.Optimizer? Plus précisément,

  1. Est-ce que le tf.keras.optimizers.Optimizer la documentation répertoriée en haut signifie simplement remplacer les versions de soulignement principal des méthodes qu'elles mentionnent (par exemple, _resource_apply_dense au lieu de resource_apply_dense)? Dans l'affirmative, existe-t-il des garanties API quant à ces méthodes d'apparence privée qui ne changeront pas leur comportement dans les futures versions de TensorFlow? Quelles sont les signatures de ces méthodes?
  2. Quand remplacerait-on apply_gradients en plus de _apply_resource_[dense|sparse] méthodes?

Modifier. Problème ouvert sur GitHub: # 36449

30
Artem Mavrin
  1. Oui, cela semble être une erreur de documentation. Les noms de soulignement précédents sont les méthodes correctes à remplacer. L'optimiseur non Keras est associé à tous ces éléments, mais non implémenté dans la classe de 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. Je ne sais pas apply_dense. D'une part, si vous le remplacez, le code mentionne qu'une DistributionStrategy par réplique pourrait être "dangereuse"
    # 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.
1
Tyler