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
.
Quelle est la bonne façon de sous-classer un tf.keras.optimizers.Optimizer
? Plus précisément,
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?apply_gradients
en plus de _apply_resource_[dense|sparse]
méthodes?Modifier. Problème ouvert sur GitHub: # 36449
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()
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.