Dokumentasi | Contoh
Sonnet adalah perpustakaan yang dibangun di atas TensorFlow 2 yang dirancang untuk menyediakan abstraksi sederhana dan dapat disusun untuk penelitian pembelajaran mesin.
Soneta telah dirancang dan dibangun oleh para peneliti di DeepMind. Ini dapat digunakan untuk membangun jaringan saraf untuk berbagai tujuan (pembelajaran tanpa pengawasan, pembelajaran penguatan, ...). Kami merasa ini adalah abstraksi yang sukses untuk organisasi kami, Anda mungkin juga!
Lebih khusus lagi, Sonnet menyediakan model pemrograman sederhana namun kuat yang berpusat pada satu konsep: snt.Module
. Modul dapat menyimpan referensi ke parameter, modul lain, dan metode yang menerapkan beberapa fungsi pada input pengguna. Sonnet dikirimkan dengan banyak modul yang telah ditentukan sebelumnya (misalnya snt.Linear
, snt.Conv2D
, snt.BatchNorm
) dan beberapa jaringan modul yang telah ditentukan sebelumnya (misalnya snt.nets.MLP
) tetapi pengguna juga didorong untuk membuat modul mereka sendiri.
Tidak seperti banyak kerangka kerja, Sonnet sangat tidak beropini tentang bagaimana Anda akan menggunakan modul Anda. Modul dirancang untuk berdiri sendiri dan sepenuhnya terpisah satu sama lain. Soneta tidak dilengkapi dengan kerangka pelatihan dan pengguna didorong untuk membuat kerangka kerja mereka sendiri atau mengadopsi kerangka kerja yang dibuat oleh orang lain.
Soneta juga dirancang agar mudah dipahami, kode kita (semoga!) jelas dan fokus. Jika kami memilih default (misalnya default untuk nilai parameter awal), kami mencoba menunjukkan alasannya.
Cara termudah untuk mencoba Sonnet adalah dengan menggunakan Google Colab yang menawarkan notebook Python gratis yang terpasang pada GPU atau TPU.
snt.distribute
Untuk memulai, instal TensorFlow 2.0 dan Sonnet 2:
$ pip install tensorflow tensorflow-probability
$ pip install dm-sonnet
Anda dapat menjalankan perintah berikut untuk memverifikasi semuanya terpasang dengan benar:
import tensorflow as tf
import sonnet as snt
print ( "TensorFlow version {}" . format ( tf . __version__ ))
print ( "Sonnet version {}" . format ( snt . __version__ ))
Soneta dikirimkan dengan sejumlah modul bawaan yang dapat Anda gunakan dengan mudah. Misalnya untuk mendefinisikan MLP kita dapat menggunakan modul snt.Sequential
untuk memanggil rangkaian modul, meneruskan output dari modul tertentu sebagai input untuk modul berikutnya. Kita dapat menggunakan snt.Linear
dan tf.nn.relu
untuk mendefinisikan perhitungan kita:
mlp = snt . Sequential ([
snt . Linear ( 1024 ),
tf . nn . relu ,
snt . Linear ( 10 ),
])
Untuk menggunakan modul kita, kita perlu "memanggilnya". Modul Sequential
(dan sebagian besar modul) mendefinisikan metode __call__
yang berarti Anda dapat memanggilnya dengan nama:
logits = mlp ( tf . random . normal ([ batch_size , input_size ]))
Meminta semua parameter untuk modul Anda juga sangat umum. Sebagian besar modul di Soneta membuat parameternya saat pertama kali dipanggil dengan beberapa masukan (karena dalam banyak kasus, bentuk parameter adalah fungsi dari masukan). Modul soneta menyediakan dua properti untuk mengakses parameter.
Properti variables
mengembalikan semua tf.Variable
yang direferensikan oleh modul yang diberikan:
all_variables = mlp . variables
Perlu dicatat bahwa tf.Variable
s tidak hanya digunakan untuk parameter model Anda. Misalnya mereka digunakan untuk menahan status dalam metrik yang digunakan di snt.BatchNorm
. Dalam kebanyakan kasus, pengguna mengambil variabel modul untuk meneruskannya ke pengoptimal untuk diperbarui. Dalam hal ini variabel yang tidak dapat dilatih biasanya tidak ada dalam daftar tersebut karena variabel tersebut diperbarui melalui mekanisme yang berbeda. TensorFlow memiliki mekanisme bawaan untuk menandai variabel sebagai "dapat dilatih" (parameter model Anda) vs. tidak dapat dilatih (variabel lain). Sonnet menyediakan mekanisme untuk mengumpulkan semua variabel yang dapat dilatih dari modul Anda yang mungkin ingin Anda teruskan ke pengoptimal:
model_parameters = mlp . trainable_variables
Sonnet sangat menganjurkan pengguna untuk membuat subkelas snt.Module
untuk mendefinisikan modul mereka sendiri. Mari kita mulai dengan membuat layer Linear
sederhana bernama MyLinear
:
class MyLinear ( snt . Module ):
def __init__ ( self , output_size , name = None ):
super ( MyLinear , self ). __init__ ( name = name )
self . output_size = output_size
@ snt . once
def _initialize ( self , x ):
initial_w = tf . random . normal ([ x . shape [ 1 ], self . output_size ])
self . w = tf . Variable ( initial_w , name = "w" )
self . b = tf . Variable ( tf . zeros ([ self . output_size ]), name = "b" )
def __call__ ( self , x ):
self . _initialize ( x )
return tf . matmul ( x , self . w ) + self . b
Menggunakan modul ini adalah hal yang sepele:
mod = MyLinear ( 32 )
mod ( tf . ones ([ batch_size , input_size ]))
Dengan membuat subkelas snt.Module
Anda mendapatkan banyak properti bagus secara gratis. Misalnya implementasi default __repr__
yang menampilkan argumen konstruktor (sangat berguna untuk debugging dan introspeksi):
>> > print ( repr ( mod ))
MyLinear ( output_size = 10 )
Anda juga mendapatkan properti variables
dan trainable_variables
:
>> > mod . variables
( < tf . Variable 'my_linear/b:0' shape = ( 10 ,) ...) > ,
< tf . Variable 'my_linear/w:0' shape = ( 1 , 10 ) ...) > )
Anda mungkin memperhatikan awalan my_linear
pada variabel di atas. Hal ini karena modul Sonnet juga memasukkan lingkup nama modul setiap kali metode dipanggil. Dengan memasukkan cakupan nama modul, kami menyediakan grafik yang jauh lebih berguna untuk digunakan oleh alat seperti TensorBoard (misalnya, semua operasi yang terjadi di dalam my_linear akan berada dalam grup yang disebut my_linear).
Selain itu, modul Anda sekarang akan mendukung pos pemeriksaan TensorFlow dan model tersimpan yang merupakan fitur lanjutan yang akan dibahas nanti.
Soneta mendukung berbagai format serialisasi. Format paling sederhana yang kami dukung adalah pickle
Python, dan semua modul bawaan diuji untuk memastikan modul tersebut dapat disimpan/dimuat melalui acar dalam proses Python yang sama. Secara umum kami tidak menyarankan penggunaan acar, ini tidak didukung dengan baik oleh banyak bagian TensorFlow dan menurut pengalaman kami bisa sangat rapuh.
Referensi: https://www.tensorflow.org/alpha/guide/checkpoints
Pos pemeriksaan TensorFlow dapat digunakan untuk menyimpan nilai parameter secara berkala selama pelatihan. Ini berguna untuk menyimpan kemajuan pelatihan jika program Anda mogok atau dihentikan. Sonnet dirancang untuk berfungsi dengan baik dengan pos pemeriksaan TensorFlow:
checkpoint_root = "/tmp/checkpoints"
checkpoint_name = "example"
save_prefix = os . path . join ( checkpoint_root , checkpoint_name )
my_module = create_my_sonnet_module () # Can be anything extending snt.Module.
# A `Checkpoint` object manages checkpointing of the TensorFlow state associated
# with the objects passed to it's constructor. Note that Checkpoint supports
# restore on create, meaning that the variables of `my_module` do **not** need
# to be created before you restore from a checkpoint (their value will be
# restored when they are created).
checkpoint = tf . train . Checkpoint ( module = my_module )
# Most training scripts will want to restore from a checkpoint if one exists. This
# would be the case if you interrupted your training (e.g. to use your GPU for
# something else, or in a cloud environment if your instance is preempted).
latest = tf . train . latest_checkpoint ( checkpoint_root )
if latest is not None :
checkpoint . restore ( latest )
for step_num in range ( num_steps ):
train ( my_module )
# During training we will occasionally save the values of weights. Note that
# this is a blocking call and can be slow (typically we are writing to the
# slowest storage on the machine). If you have a more reliable setup it might be
# appropriate to save less frequently.
if step_num and not step_num % 1000 :
checkpoint . save ( save_prefix )
# Make sure to save your final values!!
checkpoint . save ( save_prefix )
Referensi: https://www.tensorflow.org/alpha/guide/saved_model
Model TensorFlow yang disimpan dapat digunakan untuk menyimpan salinan jaringan Anda yang dipisahkan dari sumber Python. Hal ini diaktifkan dengan menyimpan grafik TensorFlow yang menjelaskan komputasi dan pos pemeriksaan yang berisi nilai bobot.
Hal pertama yang harus dilakukan untuk membuat model tersimpan adalah membuat snt.Module
yang ingin Anda simpan:
my_module = snt . nets . MLP ([ 1024 , 1024 , 10 ])
my_module ( tf . ones ([ 1 , input_size ]))
Selanjutnya, kita perlu membuat modul lain yang menjelaskan bagian spesifik dari model yang ingin kita ekspor. Kami menyarankan untuk melakukan hal ini (daripada memodifikasi model asli di tempat) sehingga Anda memiliki kontrol yang baik atas apa yang sebenarnya diekspor. Hal ini biasanya penting untuk menghindari pembuatan model tersimpan yang sangat besar, sehingga Anda hanya membagikan bagian dari model yang Anda inginkan (misalnya, Anda hanya ingin membagikan generator untuk GAN tetapi merahasiakan diskriminatornya).
@ tf . function ( input_signature = [ tf . TensorSpec ([ None , input_size ])])
def inference ( x ):
return my_module ( x )
to_save = snt . Module ()
to_save . inference = inference
to_save . all_variables = list ( my_module . variables )
tf . saved_model . save ( to_save , "/tmp/example_saved_model" )
Kami sekarang memiliki model tersimpan di folder /tmp/example_saved_model
:
$ ls -lh /tmp/example_saved_model
total 24K
drwxrwsr-t 2 tomhennigan 154432098 4.0K Apr 28 00:14 assets
-rw-rw-r-- 1 tomhennigan 154432098 14K Apr 28 00:15 saved_model.pb
drwxrwsr-t 2 tomhennigan 154432098 4.0K Apr 28 00:15 variables
Memuat model ini sederhana dan dapat dilakukan di mesin lain tanpa kode Python apa pun yang membuat model tersimpan:
loaded = tf . saved_model . load ( "/tmp/example_saved_model" )
# Use the inference method. Note this doesn't run the Python code from `to_save`
# but instead uses the TensorFlow Graph that is part of the saved model.
loaded . inference ( tf . ones ([ 1 , input_size ]))
# The all_variables property can be used to retrieve the restored variables.
assert len ( loaded . all_variables ) > 0
Perhatikan bahwa objek yang dimuat bukanlah modul Sonnet, melainkan objek kontainer yang memiliki metode spesifik (misalnya inference
) dan properti (misalnya all_variables
) yang kita tambahkan di blok sebelumnya.
Contoh: https://github.com/deepmind/sonnet/blob/v2/examples/distributed_cifar10.ipynb
Sonnet memiliki dukungan untuk pelatihan terdistribusi menggunakan strategi distribusi TensorFlow khusus.
Perbedaan utama antara Sonnet dan pelatihan terdistribusi menggunakan tf.keras
adalah modul dan pengoptimal Sonnet tidak berperilaku berbeda saat dijalankan dalam strategi distribusi (misalnya, kami tidak menghitung rata-rata gradien atau menyinkronkan statistik norma batch Anda). Kami percaya bahwa pengguna harus memiliki kendali penuh atas aspek-aspek pelatihan mereka dan mereka tidak boleh dimasukkan ke dalam perpustakaan. Keuntungannya di sini adalah Anda perlu menerapkan fitur-fitur ini dalam skrip pelatihan Anda (biasanya ini hanya 2 baris kode untuk mengurangi gradien sebelum menerapkan pengoptimal) atau menukar modul yang secara eksplisit sadar akan distribusi (misalnya snt.distribute.CrossReplicaBatchNorm
).
Contoh Cifar-10 kami yang terdistribusi menjelaskan pelatihan multi-GPU dengan Soneta.