Власний оптимізатор TensorFlow Keras


30

Припустимо, я хочу написати спеціальний клас оптимізатора, який відповідає стандарту tf.keras API (використовуючи версію TensorFlow> = 2.0). Мене бентежить документально підтверджений спосіб зробити це проти того, що робиться в реалізаціях.

Документація для tf.keras.optimizers.Optimizer штатів ,

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

Однак, поточна tf.keras.optimizers.Optimizerреалізація не визначає resource_apply_denseметод, але він робить визначення приватного виду _resource_apply_denseметоду заглушки . Аналогічно, немає resource_apply_sparseабо create_slotsметодів, але є _resource_apply_sparseзаглушка методу та _create_slotsвиклик методу .

В офіційних tf.keras.optimizers.Optimizerпідкласах ( з використанням в tf.keras.optimizers.Adamякості прикладу), існує _resource_apply_dense, _resource_apply_sparseі _create_slotsметоди, і немає таких методів без ведучого підкреслення.

Є аналогічні методи вивідного підкреслення в злегка менш офіційних tf.keras.optimizers.Optimizerпідкласах (наприклад, tfa.optimizers.MovingAverageвід TensorFlow Addons: _resource_apply_dense, _resource_apply_sparse,_create_slots ).

Іншим заплутаним моментом для мене є те, що деякі оптимізатори TensorFlow Addons також перекривають apply_gradientsметод (наприклад, tfa.optimizers.MovingAverage), тоді як tf.keras.optimizersоптимізатори - ні.

Більше того, я помітив, що apply_gradientsметод tf.keras.optimizers.Optimizerметоду викликає_create_slots , але базовий tf.keras.optimizers.Optimizerклас не має _create_slotsметоду. Отже, видається, що _create_slotsметод повинен бути визначений у підкласі оптимізатора, якщо цей підклас не переосмислює apply_gradients.


Запитання

Який правильний спосіб підкласу a tf.keras.optimizers.Optimizer? Зокрема,

  1. Чи означає tf.keras.optimizers.Optimizerперелічена вгорі документація просто переосмислення версій підкреслення версій методів, про які вони згадують (наприклад, _resource_apply_denseзамістьresource_apply_dense )? Якщо так, чи існують якісь гарантії API щодо цих методів приватного вигляду, що не змінюють їх поведінку в майбутніх версіях TensorFlow? Які підписи цих методів?
  2. Коли apply_gradientsна додаток до _apply_resource_[dense|sparse]методів відмовились одне ?

Редагувати. Відкрито випуск на GitHub: # 36449


1
Це може бути щось, про що можна повідомити розробникам, як документацію. Найбільш виразно виглядає так, що ці способи перевизначення повинні включати початкову підкреслення в документацію, але в будь-якому випадку, як ви кажете, немає інформації про їх підпис та точну мету. Можливо також, що назви методів без підкреслення (і задокументовані) планується додавати (як і з get_config), але вони ще не повинні з'являтися в публічній документації .
jdehesa

Для підписів ви завжди можете переглянути декларацію _resource_apply_denseабо _resource_apply_sparseта побачити їх використання в реалізованих оптимізаторах. Хоча це може бути, я думаю, публічний API з гарантіями стабільності, я б сказав, що їх досить безпечно використовувати. Вони просто повинні дати кращі вказівки в цьому аспекті.
jdehesa

Я погоджуюся, що це проблема документації з TensorFlow. Чи ви створили проблему для цього в tf Github repo? Якщо так, ви могли б поділитися посиланням тут?
jpgard

Відповіді:


3

Я реалізував Keras AdamW у всіх основних версіях TF & Keras - я запрошую вас переглянути optimizers_v2.py . Кілька пунктів:

  • Ви повинні успадковувати OptimizerV2, що насправді те, що ви пов’язали; це останній та сучасний базовий клас для tf.kerasоптимізаторів
  • Ви маєте рацію (1) - це помилка в документації; методи приватні, оскільки вони не призначені для використання користувачем безпосередньо.
  • apply_gradients(або будь-який інший метод) перекривається лише в тому випадку, якщо за замовчуванням не виконано те, що потрібно для даного оптимізатора; у вашому зв'язаному прикладі це лише однолінійний аддон до оригіналу
  • "Отже, здається, що _create_slotsметод повинен бути визначений у підкласі оптимізатора, якщо цей підклас не переосмислює apply_gradients" - два не пов'язані між собою; це випадковість.

  • У чому різниця між _resource_apply_denseі _resource_apply_sparse?

Пізніші угоди з розрідженими шарами - наприклад, Embedding- і колишніми з усім іншим; приклад .

  • Коли я повинен використовувати _create_slots()?

При визначенні навчальних tf.Variable s; приклад: моменти першого та другого порядку зважування (наприклад, Адам). Він використовує add_slot().

  • Коли я повинен використовувати _set_hyper()?

Досить багато, коли не використовуючи _create_slots(); це як встановлення атрибутів класу, але з додатковими кроками попередньої обробки для забезпечення правильності використання. Так Python int, float, tf.Tensor, tf.Variable, та інші. (Я мав би більше використовувати його в Keras AdamW).


Примітка . Хоча мої пов'язані оптимізатори працюють правильно і приблизно так само швидко, як і оригінали, код дотримується найкращих практик TensorFlow і все ще може бути швидшим; Я не рекомендую це як "ідеальну орієнтир". Наприклад, деякі об'єкти Python (наприклад int) повинні бути тензорами; eta_tвизначається як tf.Variable, але негайно переосмислюється як tf.Tensorу _applyметодах. Це не обов'язково велика справа, просто не встигли оновитись.


2
  1. Так, це здається помилкою в документації. Попередні назви підкреслення - це правильні способи переоцінки. Пов’язаний не оптимізатор Keras, який має все це визначено, але не реалізовано в базовому класі 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. Я не знаю про це apply_dense. По-перше, якщо ви їх перекриєте, код зазначає, що розподіл на кожну репліку DistribuStrategy може бути "небезпечним"
    # 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.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.