케라스를 사용한 분산 훈련
개요
tf.distribute.Strategy
: 훈련을 여러 처리 장치들로 분산시키는 것을 추상화 한것
기존의 모델이나 훈련 코드를 조금만 바꾸어 분산훈련을 할 수 있게 하는 것
tf.distribute.MirroredStrategy
를 사용: 동기화된 훈련 방식을 활용하여 한 장비에 있는 여러개의 GPU로 그래프 내 복제를 수행
모델의 모든 변수를 각 프로세서에 복사
각 프로세서의 그래디언트를 올 리듀스(all-reduce)를 사용하여 모음
모아서 계산한 값을 각 프로세서의 모델 복사본에 적용
참고 - 다른 분산 전략 가이드
필요한 패키지 가져오기
try :
%tensorflow_version 2. x
except Exception:
pass
from __future__ import absolute_import, division, print_function, unicode_literals
import tensorflow_datasets as tfds
import tensorflow as tf
tfds.disable_progress_bar()
import os
데이터셋 다운로드
MNIST 데이터셋을 TensorFlow Datasets
에서 다운로드
tf.data 형식을 반환
with_info=True로 설정: 전체 데이터에 대한 메타정보(훈련과 테스트 샘플수 등 정보)로 함께 불러옴
datasets, info = tfds.load(name='mnist' , with_info=True , as_supervised=True )
mnist_train, mnist_test = datasets['train' ], datasets['test' ]
info
tfds.core.DatasetInfo(
name='mnist' ,
version=1.0 .0 ,
description='The MNIST database of handwritten digits.' ,
homepage='http://yann.lecun.com/exdb/mnist/' ,
features=FeaturesDict({
'image' : Image(shape=(28 , 28 , 1 ), dtype=tf.uint8),
'label' : ClassLabel(shape=(), dtype=tf.int64, num_classes=10 ),
}),
total_num_examples=70000 ,
splits={
'test' : 10000 ,
'train' : 60000 ,
},
supervised_keys=('image' , 'label' ),
citation="""@article{lecun2010mnist,
title={MNIST handwritten digit database},
author={LeCun, Yann and Cortes, Corinna and Burges, CJ},
journal={ATT Labs [Online]. Available: http://yann. lecun. com/exdb/mnist},
volume={2},
year={2010}
}""" ,
redistribution_info=,
)
분산 전략 정의하기
MirroredStrategy
객체: 분산과 관련된 처리, 컨텍스트 관리자 제공
strategy = tf.distribute.MirroredStrategy()
INFO:tensorflow:Using MirroredStrategy with devices ('/job:localhost/replica:0/task:0/device:GPU:0' ,)
INFO:tensorflow:Using MirroredStrategy with devices ('/job:localhost/replica:0/task:0/device:GPU:0' ,)
print('장치의 수: {}' .format(strategy.num_replicas_in_sync))
장치의 수: 1
입력 파이프라인 구성하기
다중 GPU로 모델을 훈련할 때는 배치크기를 늘려야 컴퓨팅 자원을 효과적으로 사용가능
기본: GPU 메모리에 맞춰 가능한 큰 배치 크기 사용, 학습률 조정
print(info.splits.total_num_examples)
num_train_examples = info.splits['train' ].num_examples
num_test_examples = info.splits['test' ].num_examples
print(num_train_examples, num_test_examples)
BUFFER_SIZE = 10000
BATCH_SIZE_PER_REPLICA = 64
BATCH_SIZE = BATCH_SIZE_PER_REPLICA * strategy.num_replicas_in_sync
print('BATCH_SIZE: {}' .format(BATCH_SIZE))
70000
60000 10000
BATCH_SIZE: 64
픽셀의 값이 0~255 사이, 0-1범위로 정규화 필요
def scale (image, label) :
image = tf.cast(image, tf.float32)
image /= 255
return image, label
훈련 데이터 순서를 섞고 훈련을 위해 배치로 묶음
train_dataset = mnist_train.map(scale).shuffle(BATCH_SIZE).batch(BATCH_SIZE)
eval_dataset = mnist_test.map(scale).batch(BATCH_SIZE)
모델 만들기
strategy.scope
컨텍스트 안에서 케라스 모델을 만들고 컵파일 함
with strategy.scope():
model = tf.keras.Sequential([
tf.keras.layers.Conv2D(32 , 3 , activation='relu' , input_shape=(28 , 28 , 1 )),
tf.keras.layers.MaxPool2D(),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(64 , activation='relu' ),
tf.keras.layers.Dense(10 , activation='softmax' )
])
model.compile(loss='sparse_categorical_crossentropy' ,
optimizer=tf.keras.optimizers.Adam(),
metrics=['accuracy' ])
콜백 정의하기
텐서보드(TensorBoard): 텐서보드용 로그를 남김, 텐서보드에서 그래프를 그릴 수 있게 해줌
모델 체크포인트(Checkpoint): 에포크가 끝난 후 모델을 저장
학습률 스케줄러: 에포크 혹은 배치가 끝난 후 학습률을 바꿈
checkpoint_dir = './training_checkpoints'
checkpoint_prefix = os.path.join(checkpoint_dir, 'ckpt_{epoch}' )
def decay (epoch) :
if epoch < 3 :
return 1e-3
elif epoch >=3 and epoch < 7 :
return 1e-4
else :
return 1e-5
class PrintLR (tf.keras.callbacks.Callback) :
def on_epoch_end (self, epoch, logs=None) :
print('\n에포크 {}의 학습률은 {}입니다.' .format(epoch+1 , model.optimizer.lr.numpy()))
callbacks = [
tf.keras.callbacks.TensorBoard(log_dir='./logs' ),
tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_prefix,
save_weights_only=True ),
tf.keras.callbacks.LearningRateScheduler(decay),
PrintLR()
]
훈련과 평가
model.fit(train_dataset, epochs=12 , callbacks=callbacks)
Epoch 1 /12
938 /Unknown - 18 s 19 ms/step - loss: 0.1962 - accuracy: 0.9429
에포크 1 의 학습률은 0.0010000000474974513 입니다.
938 /938 [==============================] - 18 s 19 ms/step - loss: 0.1962 - accuracy: 0.9429
Epoch 2 /12
937 /938 [============================>.] - ETA: 0 s - loss: 0.0629 - accuracy: 0.9814
에포크 2 의 학습률은 0.0010000000474974513 입니다.
938 /938 [==============================] - 12 s 12 ms/step - loss: 0.0629 - accuracy: 0.9814
Epoch 3 /12
936 /938 [============================>.] - ETA: 0 s - loss: 0.0429 - accuracy: 0.9874
에포크 3 의 학습률은 0.0010000000474974513 입니다.
938 /938 [==============================] - 12 s 13 ms/step - loss: 0.0430 - accuracy: 0.9874
Epoch 4 /12
936 /938 [============================>.] - ETA: 0 s - loss: 0.0241 - accuracy: 0.9934
에포크 4 의 학습률은 9.999999747378752e-05 입니다.
938 /938 [==============================] - 12 s 13 ms/step - loss: 0.0240 - accuracy: 0.9934
Epoch 5 /12
936 /938 [============================>.] - ETA: 0 s - loss: 0.0206 - accuracy: 0.9948
에포크 5 의 학습률은 9.999999747378752e-05 입니다.
938 /938 [==============================] - 12 s 13 ms/step - loss: 0.0206 - accuracy: 0.9948
Epoch 6 /12
936 /938 [============================>.] - ETA: 0 s - loss: 0.0188 - accuracy: 0.9955
에포크 6 의 학습률은 9.999999747378752e-05 입니다.
938 /938 [==============================] - 13 s 13 ms/step - loss: 0.0187 - accuracy: 0.9955
Epoch 7 /12
935 /938 [============================>.] - ETA: 0 s - loss: 0.0172 - accuracy: 0.9961
에포크 7 의 학습률은 9.999999747378752e-05 입니다.
938 /938 [==============================] - 12 s 13 ms/step - loss: 0.0172 - accuracy: 0.9961
Epoch 8 /12
936 /938 [============================>.] - ETA: 0 s - loss: 0.0148 - accuracy: 0.9967
에포크 8 의 학습률은 9.999999747378752e-06 입니다.
938 /938 [==============================] - 12 s 13 ms/step - loss: 0.0148 - accuracy: 0.9967
Epoch 9 /12
936 /938 [============================>.] - ETA: 0 s - loss: 0.0146 - accuracy: 0.9968
에포크 9 의 학습률은 9.999999747378752e-06 입니다.
938 /938 [==============================] - 12 s 12 ms/step - loss: 0.0146 - accuracy: 0.9968
Epoch 10 /12
936 /938 [============================>.] - ETA: 0 s - loss: 0.0144 - accuracy: 0.9968
에포크 10 의 학습률은 9.999999747378752e-06 입니다.
938 /938 [==============================] - 12 s 12 ms/step - loss: 0.0144 - accuracy: 0.9968
Epoch 11 /12
936 /938 [============================>.] - ETA: 0 s - loss: 0.0142 - accuracy: 0.9969
에포크 11 의 학습률은 9.999999747378752e-06 입니다.
938 /938 [==============================] - 12 s 12 ms/step - loss: 0.0142 - accuracy: 0.9969
Epoch 12 /12
936 /938 [============================>.] - ETA: 0 s - loss: 0.0140 - accuracy: 0.9969
에포크 12 의 학습률은 9.999999747378752e-06 입니다.
938 /938 [==============================] - 12 s 13 ms/step - loss: 0.0140 - accuracy: 0.9969
<tensorflow.python.keras.callbacks.History at 0x7f1d34000c50 >
!ls {checkpoint_dir}
checkpoint ckpt_4 .data-00000-of-00002
ckpt_10 .data-00000-of-00002 ckpt_4 .data-00001-of-00002
ckpt_10 .data-00001-of-00002 ckpt_4 .index
ckpt_10 .index ckpt_5 .data-00000-of-00002
ckpt_11 .data-00000-of-00002 ckpt_5 .data-00001-of-00002
ckpt_11 .data-00001-of-00002 ckpt_5 .index
ckpt_11 .index ckpt_6 .data-00000-of-00002
ckpt_12 .data-00000-of-00002 ckpt_6 .data-00001-of-00002
ckpt_12 .data-00001-of-00002 ckpt_6 .index
ckpt_12 .index ckpt_7 .data-00000-of-00002
ckpt_1 .data-00000-of-00002 ckpt_7 .data-00001-of-00002
ckpt_1 .data-00001-of-00002 ckpt_7 .index
ckpt_1 .index ckpt_8 .data-00000-of-00002
ckpt_2 .data-00000-of-00002 ckpt_8 .data-00001-of-00002
ckpt_2 .data-00001-of-00002 ckpt_8 .index
ckpt_2 .index ckpt_9 .data-00000-of-00002
ckpt_3 .data-00000-of-00002 ckpt_9 .data-00001-of-00002
ckpt_3 .data-00001-of-00002 ckpt_9 .index
ckpt_3 .index
model.load_weights(tf.train.latest_checkpoint(checkpoint_dir))
eval_loss, eval_acc = model.evaluate(eval_dataset)
print('\n평가 손실: {}, 평가 정확도: {}' .format(eval_loss, eval_acc))
157/Unknown - 3s 20ms/step - loss: 0.0378 - accuracy: 0.9871
평가 손실: 0.037776678224067516, 평가 정확도: 0.9871000051498413
%load_ext tensorboard
The tensorboard extension is already loaded. To reload it, use :
%reload_ext tensorboard
%tensorboard --logdir logs
Output hidden; open in https:
!ls -sh ./logs
total 4.0K
4.0K train
SaveModel로 내보내기(지원중단됨)