문서 | 예
Sonnet은 기계 학습 연구를 위한 간단하고 구성 가능한 추상화를 제공하도록 설계된 TensorFlow 2를 기반으로 구축된 라이브러리입니다.
Sonnet은 DeepMind의 연구원들이 설계하고 구축했습니다. 다양한 목적(비지도 학습, 강화 학습 등)을 위해 신경망을 구성하는 데 사용할 수 있습니다. 우리는 이것이 우리 조직을 위한 성공적인 추상화라고 생각합니다. 여러분도 그럴 수도 있습니다!
보다 구체적으로 Sonnet은 단일 개념인 snt.Module
중심으로 하는 간단하지만 강력한 프로그래밍 모델을 제공합니다. 모듈은 사용자 입력에 일부 기능을 적용하는 매개변수, 기타 모듈 및 메소드에 대한 참조를 보유할 수 있습니다. Sonnet에는 미리 정의된 많은 모듈(예: snt.Linear
, snt.Conv2D
, snt.BatchNorm
)과 일부 미리 정의된 모듈 네트워크(예: snt.nets.MLP
)가 포함되어 있지만 사용자가 자신의 모듈을 구축하는 것도 권장됩니다.
많은 프레임워크와 달리 Sonnet은 모듈 사용 방법 에 대해 극도로 의견이 없습니다. 모듈은 독립적이고 서로 완전히 분리되도록 설계되었습니다. Sonnet은 교육 프레임워크와 함께 제공되지 않으며 사용자는 스스로 구축하거나 다른 사람이 구축한 프레임워크를 채택하도록 권장됩니다.
Sonnet은 또한 이해하기 쉽도록 설계되었으며, 우리의 코드는 (희망적으로!) 명확하고 집중되어 있습니다. 기본값(예: 초기 매개변수 값의 기본값)을 선택한 경우 그 이유를 지적하려고 합니다.
Sonnet을 사용해 보는 가장 쉬운 방법은 GPU 또는 TPU에 연결된 무료 Python 노트북을 제공하는 Google Colab을 사용하는 것입니다.
snt.distribute
사용한 분산 교육 시작하려면 TensorFlow 2.0 및 Sonnet 2를 설치하세요.
$ pip install tensorflow tensorflow-probability
$ pip install dm-sonnet
다음을 실행하여 항목이 올바르게 설치되었는지 확인할 수 있습니다.
import tensorflow as tf
import sonnet as snt
print ( "TensorFlow version {}" . format ( tf . __version__ ))
print ( "Sonnet version {}" . format ( snt . __version__ ))
Sonnet에는 간단하게 사용할 수 있는 여러 내장 모듈이 함께 제공됩니다. 예를 들어 MLP를 정의하기 위해 snt.Sequential
모듈을 사용하여 모듈 시퀀스를 호출하고 주어진 모듈의 출력을 다음 모듈의 입력으로 전달할 수 있습니다. 실제로 계산을 정의하기 위해 snt.Linear
및 tf.nn.relu
사용할 수 있습니다.
mlp = snt . Sequential ([
snt . Linear ( 1024 ),
tf . nn . relu ,
snt . Linear ( 10 ),
])
모듈을 사용하려면 모듈을 "호출"해야 합니다. Sequential
모듈(및 대부분의 모듈)은 이름으로 호출할 수 있음을 의미하는 __call__
메서드를 정의합니다.
logits = mlp ( tf . random . normal ([ batch_size , input_size ]))
모듈의 모든 매개변수를 요청하는 것도 매우 일반적입니다. Sonnet의 대부분의 모듈은 일부 입력으로 처음 호출될 때 매개변수를 생성합니다(대부분의 경우 매개변수의 모양은 입력의 함수이기 때문입니다). Sonnet 모듈은 매개변수에 액세스하기 위한 두 가지 속성을 제공합니다.
variables
속성은 주어진 모듈에서 참조하는 모든 tf.Variable
을 반환합니다:
all_variables = mlp . variables
tf.Variable
은 모델의 매개변수에만 사용되는 것이 아니라는 점은 주목할 가치가 있습니다. 예를 들어 snt.BatchNorm
에서 사용되는 측정항목의 상태를 유지하는 데 사용됩니다. 대부분의 경우 사용자는 업데이트할 최적화 프로그램에 전달하기 위해 모듈 변수를 검색합니다. 이 경우 훈련할 수 없는 변수는 다른 메커니즘을 통해 업데이트되므로 일반적으로 해당 목록에 없어야 합니다. TensorFlow에는 변수를 "훈련 가능"(모델의 매개변수) 또는 훈련 불가능한(기타 변수)으로 표시하는 메커니즘이 내장되어 있습니다. Sonnet은 모듈에서 최적화 프로그램에 전달하려는 모든 훈련 가능한 변수를 수집하는 메커니즘을 제공합니다.
model_parameters = mlp . trainable_variables
Sonnet은 사용자가 자신의 모듈을 정의하기 위해 snt.Module
하위 클래스로 분류할 것을 강력히 권장합니다. MyLinear
라는 간단한 Linear
레이어를 만들어 시작해 보겠습니다.
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
이 모듈을 사용하는 것은 간단합니다.
mod = MyLinear ( 32 )
mod ( tf . ones ([ batch_size , input_size ]))
snt.Module
서브클래싱하면 많은 멋진 속성을 무료로 얻을 수 있습니다. 예를 들어 생성자 인수를 표시하는 __repr__
의 기본 구현은 다음과 같습니다(디버깅 및 자체 검사에 매우 유용함).
>> > print ( repr ( mod ))
MyLinear ( output_size = 10 )
variables
및 trainable_variables
속성도 얻습니다.
>> > mod . variables
( < tf . Variable 'my_linear/b:0' shape = ( 10 ,) ...) > ,
< tf . Variable 'my_linear/w:0' shape = ( 1 , 10 ) ...) > )
위의 변수에 my_linear
접두사가 붙은 것을 볼 수 있습니다. 이는 메소드가 호출될 때마다 Sonnet 모듈도 모듈 이름 범위에 들어가기 때문입니다. 모듈 이름 범위를 입력하면 TensorBoard와 같은 도구에서 사용할 수 있는 훨씬 더 유용한 그래프가 제공됩니다(예: my_linear 내에서 발생하는 모든 작업은 my_linear라는 그룹에 속하게 됩니다).
또한 모듈은 이제 나중에 다루는 고급 기능인 TensorFlow 체크포인트 및 저장된 모델을 지원합니다.
Sonnet은 다양한 직렬화 형식을 지원합니다. 우리가 지원하는 가장 간단한 형식은 Python의 pickle
이며, 내장된 모든 모듈은 동일한 Python 프로세스에서 pickle을 통해 저장/로드될 수 있는지 테스트됩니다. 일반적으로 우리는 피클의 사용을 권장하지 않습니다. 피클은 TensorFlow의 많은 부분에서 잘 지원되지 않으며 우리 경험상 상당히 취약할 수 있습니다.
참조: https://www.tensorflow.org/alpha/guide/checkpoints
TensorFlow 체크포인트를 사용하면 훈련 중에 매개변수 값을 주기적으로 저장할 수 있습니다. 이는 프로그램이 충돌하거나 중지되는 경우 훈련 진행 상황을 저장하는 데 유용할 수 있습니다. Sonnet은 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 )
참조: https://www.tensorflow.org/alpha/guide/saved_model
TensorFlow 저장 모델을 사용하여 Python 소스에서 분리된 네트워크 복사본을 저장할 수 있습니다. 이는 계산을 설명하는 TensorFlow 그래프와 가중치 값이 포함된 체크포인트를 저장함으로써 가능해집니다.
저장된 모델을 생성하기 위해 가장 먼저 해야 할 일은 저장하려는 snt.Module
을 생성하는 것입니다.
my_module = snt . nets . MLP ([ 1024 , 1024 , 10 ])
my_module ( tf . ones ([ 1 , input_size ]))
다음으로, 내보내려는 모델의 특정 부분을 설명하는 또 다른 모듈을 만들어야 합니다. 실제로 내보낼 내용을 세밀하게 제어할 수 있도록 원본 모델을 내부에서 수정하는 대신 이 작업을 수행하는 것이 좋습니다. 이는 일반적으로 매우 큰 저장된 모델을 생성하지 않고 원하는 모델 부분만 공유하는 데 중요합니다(예: GAN에 대한 생성기만 공유하고 판별자는 비공개로 유지하려는 경우).
@ 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" )
이제 /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
이 모델을 로드하는 것은 간단하며 저장된 모델을 구축한 Python 코드 없이 다른 시스템에서 수행할 수 있습니다.
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
로드된 객체는 Sonnet 모듈이 아니며 이전 블록에서 추가한 특정 메서드(예: inference
)와 속성(예: all_variables
)을 가진 컨테이너 객체입니다.
예: https://github.com/deepmind/sonnet/blob/v2/examples/distributed_cifar10.ipynb
Sonnet은 맞춤형 TensorFlow 배포 전략을 사용한 분산 교육을 지원합니다.
Sonnet과 tf.keras
사용한 분산 교육의 주요 차이점은 Sonnet 모듈과 최적화 프로그램이 배포 전략에 따라 실행될 때 다르게 동작하지 않는다는 것입니다(예: 그라데이션의 평균을 계산하지 않거나 배치 표준 통계를 동기화하지 않음). 우리는 사용자가 교육의 이러한 측면을 완전히 제어해야 하며 라이브러리에 구워져서는 안 된다고 믿습니다. 여기서 절충점은 훈련 스크립트에서 이러한 기능을 구현해야 한다는 것입니다(일반적으로 최적화 프로그램을 적용하기 전에 기울기를 줄이는 코드는 단 두 줄입니다). 또는 명시적으로 배포를 인식하는 모듈(예: snt.distribute.CrossReplicaBatchNorm
).
분산 Cifar-10 예제에서는 Sonnet을 사용하여 다중 GPU 교육을 수행하는 방법을 안내합니다.