Pengoptimal Kustom TensorFlow Keras

30

Misalkan saya ingin menulis kelas pengoptimal khusus yang sesuai dengan tf.kerasAPI (menggunakan versi TensorFlow> = 2.0). Saya bingung tentang cara yang terdokumentasi untuk melakukan ini versus apa yang dilakukan dalam implementasi.

Dokumentasi untuk tf.keras.optimizers.Optimizer negara ,

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

Namun, tf.keras.optimizers.Optimizerimplementasi saat ini tidak mendefinisikan resource_apply_densemetode, tetapi tidak menentukan _resource_apply_densemetode rintisan yang tampak pribadi . Demikian pula, tidak ada resource_apply_sparseatau create_slotsmetode, tetapi ada _resource_apply_sparsemetode rintisan dan _create_slotspemanggilan metode .

Dalam resmi tf.keras.optimizers.Optimizersubclass (menggunakan tf.keras.optimizers.Adamsebagai contoh), ada _resource_apply_dense, _resource_apply_sparsedan _create_slotsmetode, dan tidak ada metode tersebut tanpa awalan garis bawah.

Ada metode yang serupa terkemuka-bawah di sedikit-kurang-resmi tf.keras.optimizers.Optimizersubclass (misalnya, tfa.optimizers.MovingAveragedari TensorFlow Addons: _resource_apply_dense, _resource_apply_sparse, _create_slots).

Poin perancu lain bagi saya adalah bahwa beberapa pengoptimal TensorFlow Addons juga menimpa apply_gradientsmetode (misalnya, tfa.optimizers.MovingAverage), sedangkan tf.keras.optimizerspengoptimal tidak.

Selain itu, saya melihat bahwa apply_gradientsmetode tf.keras.optimizers.Optimizermetode panggilan_create_slots , tapi dasar tf.keras.optimizers.Optimizerkelas tidak memiliki _create_slotsmetode. Jadi, tampaknya _create_slotsmetode harus didefinisikan dalam subkelas pengoptimal jika subkelas itu tidak menimpanya apply_gradients.


Pertanyaan

Apa cara yang benar untuk subkelas a tf.keras.optimizers.Optimizer? Secara khusus,

  1. Apakah tf.keras.optimizers.Optimizerdokumentasi yang tercantum di atas hanya bermaksud untuk menimpa versi terdepan-garis bawah dari metode yang mereka sebutkan (misalnya, _resource_apply_densebukan resource_apply_dense)? Jika demikian, apakah ada jaminan API tentang metode yang tampak pribadi ini tidak mengubah perilaku mereka di versi TensorFlow yang akan datang? Apa saja tanda tangan dari metode ini?
  2. Kapan satu menimpa apply_gradientsselain _apply_resource_[dense|sparse]metode?

Edit. Masalah yang terbuka pada GitHub: # 36449

Artem Mavrin
sumber
1
Ini mungkin sesuatu untuk dilaporkan sebagai masalah dokumentasi kepada para devs. Tampaknya metode-metode yang harus ditimpa harus menyertakan garis bawah awal dalam dokumentasi, tetapi dalam kasus apa pun, seperti yang Anda katakan, tidak ada informasi tentang tanda tangan dan tujuan yang sebenarnya. Mungkin juga bahwa nama metode tanpa garis bawah (dan didokumentasikan) direncanakan akan ditambahkan (seperti dengan get_config), tetapi kemudian mereka belum muncul di dokumentasi publik .
jdehesa
Untuk tanda tangan, Anda selalu dapat melihat deklarasi _resource_apply_denseatau _resource_apply_sparse, dan melihat penggunaannya dalam pengoptimal yang diterapkan. Meskipun mungkin tidak, saya pikir, API publik dengan jaminan stabilitas, saya akan mengatakan itu cukup aman untuk menggunakannya. Mereka hanya harus memberikan panduan yang lebih baik dalam aspek ini.
jdehesa
Saya setuju bahwa ini adalah masalah dokumentasi dengan TensorFlow. Apakah Anda membuat masalah untuk ini di repo Github? Jika demikian, dapatkah Anda membagikan tautan di sini?
jpgard

Jawaban:

3

Saya telah menerapkan Keras AdamW di semua versi TF & Keras utama - Saya mengundang Anda untuk memeriksa optimizers_v2.py . Beberapa poin:

  • Anda harus mewarisi OptimizerV2, yang sebenarnya adalah yang Anda tautkan; ini adalah kelas dasar terbaru dan terkini untuk tf.keraspengoptimal
  • Anda benar dalam (1) - ini adalah kesalahan dokumentasi; metode ini bersifat pribadi, karena tidak dimaksudkan untuk digunakan oleh pengguna secara langsung.
  • apply_gradients(atau metode lain apa pun) hanya berlebihan jika default tidak memenuhi apa yang diperlukan untuk pengoptimal yang diberikan; dalam contoh yang ditautkan, itu hanya tambahan satu-liner ke aslinya
  • "Jadi, tampaknya suatu _create_slotsmetode harus didefinisikan dalam subkelas pengoptimal jika subkelas itu tidak menimpa apply_gradients" - keduanya tidak terkait; ini kebetulan.

  • Apa perbedaan antara _resource_apply_densedan _resource_apply_sparse?

Penawaran akhir dengan lapisan jarang - misalnya Embedding- dan sebelumnya dengan yang lainnya; contoh .

  • Kapan saya harus menggunakan _create_slots()?

Saat mendefinisikan latih tf.Variable ; contoh: momen urutan pertama dan kedua bobot (misalnya Adam). Itu menggunakan add_slot().

Cukup banyak, setiap kali tidak menggunakan _create_slots(); itu seperti mengatur atribut kelas, tetapi dengan langkah-langkah preprocessing tambahan untuk memastikan kebenaran dalam penggunaan. Jadi Python int, float, tf.Tensor, tf.Variable, & lain-lain. (Seharusnya saya lebih sering menggunakannya di Keras AdamW).


Catatan : sementara pengoptimalisasi tertaut saya berfungsi dengan benar dan hampir secepat aslinya, kode mengikuti praktik TensorFlow terbaik dan masih bisa lebih cepat; Saya tidak merekomendasikan ini sebagai "referensi ideal." Misalnya beberapa objek Python (misalnya int) harus tensor; eta_tdidefinisikan sebagai tf.Variable, tetapi segera diganti sebagai metode tf.Tensorin _apply. Belum tentu masalah besar, hanya belum punya waktu untuk renovasi.

OverLordGoldDragon
sumber
2
  1. Ya, ini terlihat sebagai kesalahan dokumentasi. Nama garis bawah sebelumnya adalah metode yang benar untuk menggantikan. Terkait adalah Pengoptimal non-Keras yang semuanya telah ditentukan, tetapi tidak diterapkan di kelas dasar 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. Saya tidak tahu apply_dense. Untuk satu hal, jika Anda menimpanya, kode menyebutkan bahwa DistributionStrategy per-replika bisa "berbahaya"
    # 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.
Tyler
sumber