일반적 질문들
멀티GPU에서 케라스 모델을 학습시키는 방법
- 원 질문 : How can I train a Keras model on multiple GPUs (on a single machine)?
- 참고) 이 질문은 분산된 기기의 GPU를 함께 활용하는 방법(=device parallelism)이 아닌 단일 머신에 있는 멀티GPU를 활용하는 방식에 관한 질문으로 보인다.
- 케라스는 하나의 모델을 다수 GPU에서 실행시키는 두 가지 방법인 data parallelism과 device parallelism을 모두 다룬다.
- data parallelism을 위해서 케라스는 백엔드 프레임워크인 JAX, TensorFlow, PyTorch의 내장된 데이터 분산 API(data parallel distribution APIs)를 지원한다. 대응되는 각 문서는 아래에서 참고한다.
- model parallelism을 위해서는 케라스는 자체의 분산 API를 가지고 있는데, (문서를 옮기고 있는 현재기준) JAX 백엔드에서만 지원된다.
- 참고) 위에서 언급된 분산 학습 방법으로서의 데이터 병렬화(data parelleism)와 모델 병렬화(model parallelism)는 각 문서에서 설명되어 있으며, 간단하게 차이를 적으면 다음과 같다.
- 데이터 병렬화(data parallelism) : 각 GPU에 모델 복사본을 보내어, 처리할 데이터를 나누어 각각 처리한다.
- 모델 병렬화(model parallelism) : 모델의 각 부분을 다른 GPU에 나누어서, 하나의 데이터(배치)를 함께 연산한다.
- 이상의 내용에 관한 좋은 소개글이 있어서 링크를 함께 남긴다.
TPU에서 케라스 모델의 학습 방법
- 원 질문 : How Can I train a Keras model on TPU?
- TPU(Tensor Processing Unit)는 딥러닝을 위한 빠르고 효율적인 하드웨어 가속장치(hardware accelerator)로서 구글 클라우드에서 누구나 이용할 수 있다.
- GCP(Google Cloud Platform)의 딥러닝 가상머신(Deep Learning VMs) 뿐만 아니라 구글 코랩(Colab)이나 캐글 노트북(Kaggle Notebooks)을 통해서도 TPU를 사용할 수 있다.
- 모든 케라스 백엔드 프레임워크에서 TPU 사용을 지원하지만, 케라스 문서에서는 TPU를 사용할 때 JAX 또는 TensorFlow 사용을 권한다.
- JAX에서의 TPU 사용
- TPU 런타임에 연결할 때, 모델 구성 전에 다음의 코드를 추가한다.
import jax
distribution = keras.distribution.DataParallel(device=jax.devices())
keras.distribution.set_distribution(distribution)
- TensorFlow에서 TPU 사용
- TPU 런타임에 연결할 때, 우선 TPUClusterResolver를 사용하여 TPU를 탐지한다.
- 이후 TPUStrategy를 생성하고, 이 스코프(scope) 안에서모델을 구성한다.
try:
tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect()
print("Device:", tpu.master())
strategy = tf.distribute.TPUStrategy(tpu)
except:
strategy = tf.distribute.get_strategy()
print("Number of replicas:", strategy.num_replicas_in_sync)
with strategy.scope():
# Create your model here
...
- TPU 사용시 유념할 사항들은 다음과 같다.
- TPU 사용률을 유지할 수 있을만큼, 데이터를 빠르게 불러올 수 있을 지를 확인해야 한다.
- 그래프 실행 마다 여러 단계의 경사 하강(gradient descent) 연산을 실행하는 것을 고려한다. 이는
compile()
의 experimental_steps_per_execution
매개변수를 통해 설정할 수 있는데, 작은 모델의 경우에는 확실한 속도 향상을 볼 수 있다.
- 참고) 비록 원문에서는
experimental_steps_per_execution
으로 나와있지만, 케라스 3 문서에서 Model training APIs의 compile()
method를 살펴보면, 이제는 steps_per_execution
으로 쓰는 것이 맞아 보인다. 이는 2020년 9월의 텐서플로 레포의 이슈처럼 더이상 experimental이 아닌 기본 기능으로 제공되어 지면서 변한것으로 생각된다.
케라스 설정 파일의 저장 위치
- 원 질문 : Where is the Keras configuration file stored?
- 모든 케라스 데이터가 저장되는 기본 위치는
$HOME/.keras/
다.
- 특정한 계정명(예-fchollet)에 대해서 대응되는 위치는 다음과 같다.
- 리눅스는 홈 디렉토리가
/home/fchollet/
이므로 /home/fchollet/.keras
- 맥OS는 홈 디렉토리가
/Users/fchellet/
이므로 /Users/fchollet/.keras
- Windows에서는
$HOME
대신에 %USERPROFILE%
을 사용하며, 보통 C:\Users\fchollet\
와 같으므로 C:\Users\fchollet\.keras\
- 만약 권한 문제 등으로 인하여, 기본 위치에 생성되지 못할 경우에는 /tmp/.keras/ 를 사용한다.
- 케라스의 설정파일은 저장 위치의
JSON
파일로서 $HOME/.keras/keras.json
이며, 아래와 같은 형식이다.
image_data_format
은 이미지를 처리하는 레이어나 기능들을 사용할 때, 기본 설정이며 channels_last
또는 channels_first
중의 하나다.
epsilon
은 일부 연산에서 0으로 나누는 것을 방지하기 위한 수치적 오차 허용 범위(fuzz factor)다.
floatx
는 기본 실수 데이터 타입이다.
backend
는 기본으로 지정된 백엔드 프레임워크로서 "jax"
, "tensorflow"
, "torch"
, "numpy"
중의 하나다.
{
"image_data_format": "channels_last",
"epsilon": 1e-07,
"floatx": "float32",
"backend': "tensorflow"
}
get_file()
등을 이용해서 다운로드된 데이터셋은 $HOME/.keras/datasets/
에 캐시(=저장)되어, 다음 번 사용할 때 다시 받을 필요 없이 빠르게 사용할 수 있다.
- 마찬가지로 활용된 모델 가중치도
$HOME/.keras/models/
에 캐시된다.
케라스에서 하이퍼 파라미터를 튜닝하는 방법
케라스 개발 과정에서 결과를 재현하기 위한 방법
- 원 질문 : How can I obtain reproducible results using Keras during development?
- 무작위성(randomness)에 관여하는 요소로는 다음의 네가지를 고려할 수 있다.
- 1. 케라스 자체 ( 예-
keras.random
연산이나 keras.layers
의 랜덤 레이어 사용)
- 2. 사용하는 백엔드 프레임워크(JAX, TensorFlow, PyTorch)
- 3. 파이썬 런타임
- 4. CUDA 런타임
- GPU에서 특정 연산이 실행될 때, 출력값은 결정적이지 않은(non-deterministic) 값을 갖게 된다. 이는 GPU에서 실행되는 많은 연산이 병렬적으로 수행되기 때문이며, 이로 인해 실행 순서는 항상 같은 것이 아니다.
- 또한 실수 표현이나 정밀도의 한계로 인하여, 때때로 몇 개의 수치를 단순히 더하는 과정에서도, 더하는 순서가 보장되지 않기 때문에 결과가 약간씩 다를 수 있다.
- 케라스와 현재 사용중인 백엔드를 결정적(deterministic)으로 만들어, 무작위 값을 고정하는 방법은 다음과 같다.
keras.utils.set_random_seed(1337)
- 파이썬의 무작위 결과를 제어하기 위해서는 환경변수
PYTHONHASHSEED
를 0으로 설정할 필요가 있다.
- 이는 프로그램 안에서가 아니라 프로그램을 시작하기 전에 설정해야 한다.
- 파이썬 3.2.3 이후로 도입된 값으로, set이나 dict의 순서와 같은 해시 기반의 연산의 재현성을 위하여 도입되었다.
- 텐서플로 백엔드를 사용할 때, CUDA 런타임을 결정적으로 만들 때에는
tf.config.experimental.enable_op_determinism
을 사용할 수 있다.(TensorFlow 2.16.1 문서에서 참조)
- 참고) 파이토치 백엔드를 사용할 때, CUDA 런타임을 결정적으로 만들기 위해서는, 다음의 두 가지를 설정할 수 있다.
torch.backends.cudnn.benchmark = False
torch.use_deterministic_algorithms(True)
- CUDA 런타임을 결정적이게 만들어서 결과를 재현할 때에는, 실행 속도의 저하 같은 성능 상의 문제가 있을 수 있음을 주의한다.
모델 저장을 위한 선택 사항
- 원 질문 : What are my options for saving models?
- 참고) 케라스 모델을 저장하기 위해서
pickle
모듈이나 cPickle
을 사용하는 것은 추천되지 않는다.
- 1) 전체 모델의 저장 ( 모델의 설정과 가중치를 모두 저장)
- 전체 모델이 저장되면 다음의 내용들이 저장 파일에 포함된다.
- 모델의 아키텍쳐가 저장되어, 모델을 재 생성할 수 있게 해준다.
- 모델의 가중치
- 손실함수나 옵티마이저와 같은 훈련 설정
- 옵티마이저의 상태가 저장되어, 저장 시의 시점에 바로 이어서 학습을 다시 시작하는 것이 가능하다.
- 전체 모델 저장 방법 :
model.save(your_file_path.keras)
- 저장된 모델을 불러오는 방법 :
model = keras.models.load_model(your_file_path.keras)
from keras.saving import load_model
model.save('my_model.keras')
del model
# 삭제된 모델과 동일한 모델을 불러올 수 있다.
model = load_model('my_model.keras')
- 2) 가중치만 저장
- 모델의 가중치만을 저장할 필요가 있을 때에는
.weights.h5
확장자를 사용해서 HDF5
형식으로 저장할 수 있다.
- 모델의 가중치 저장 :
model.save_weights('my_model.weights.h5')
- 모델의 아키텍쳐를 기술한 코드로부터 모델을 생성할 수 있다면, 같은 구조의 모델로 저장된 가중치를 불러올 수 있다. :
model.load_weights('my_model.weights.h5')
- 한편, 파인튜닝이나 전이학습을 위해, 다른 구조의 모델로 공통적으로 사용된 레이어의 가중치만을 불러오고 싶다면,
layer name
으로 불러올 수 있다. model.load_weights('my_model.weights.h5', by_name=True)
- 이 때, 새로 선언된 모델에 저장된 가중치와 대응되는 레이어 이름이 없다면, 해당값들은 불러오지 않는다.
"""
원래 모델의 정의가 다음과 같다고 가정한다.
model = Sequential()
model.add(Dense(2, input_dim=3, name='dense_1'))
model.add(Dense(3, name='dense_2')
...
model.save_weight(fname)
"""
# 새로운 모델
model = Sequential()
model.add(Dense(2, input_dim=3, name='dense_1')) # 가중치가 로드된다.
model.add(Dense(10, name='new_dense')) # 가중치가 로드되지 않는다.
# 저장된 첫번째 모델 가중치를 불러오면, 새로운 모델의 첫번째 레이어인
# dense_1 에만 영향을 미친다.
model.load_weights(fname, by_name=True)
- 3) 모델의 설정만을 저장(직렬화 serialization)
- 모델의 훈련된 가중치나 훈련 설정은 저장하지 않고, 오직 모델의 아키텍쳐만 저장하고 싶다면
json_string = model.to_json()
처럼 사용할 수 있다.
- 저장된
JSON
파일은 인간이 읽을 수 있으며, 필요시 직접 수정할 수 있는 파일이다.
- JSON파일로부터 새로운 모델을 만드는 것이 가능한다.
from keras.models import model_from_json
model = model_from_json(json_string)
- 4) 저장된 모델에 커스텀 레이어 또는 커스텀 객체가 있는 경우
- 불러오려는 모델에, 케라스에서 제공하는 것이 아닌 직접 작성한 커스텀 레이어나 클래스, 함수 등이 포함된 경우에는
custom_object
매개변수를 통해 모델을 불러올 때 이를 명시해준다.
- 아래의 예시들은 AttentionLayer 라는 커스텀 클래스를 포함할 때이다.
- 커스텀 객체의 범위(=스코프)를 사용하거나
model_from_json()
명령어에서도 같은 방식으로 사용할 수 있다.
from keras.models import load_model
model = load_model('my_model.h5', custom_objects={'AttentionLayer': AttentionLayer})
from keras.utils import CustomObjectScope
with CustomObjectScope({'AttentionLayer': AttentionLayer}):
model = load_model('my_model.h5')
from keras.models import model_from_json
model = model_from_json(json_string, custom_objects={'AttentionLayer': AttentionLayer})
모델 저장을 위한 HDF5 설치
- 대용량 데이터 저장을 위한 고성능 파일형식인 HDF5로 케라스 모델을 저장하기 위해서는, 케라스에서는 h5py 파이썬 패키지를 사용한다.
- 이 패키지는 케라스의 의존성(dependency)로서, 기본적으로 설치되어야 한다.
- 데비안 계열의 리눅스 배포판에서는 추가로 libhdf5 패키지를 설치해야한다.
- 설치 후 정상적으로 h5py 모듈이 임포트되지 않으면, 설치 상세 문서를 참조할 수 있다.
케라스를 논문에 인용하는 방법
@misc{chollet2015keras,
title={Keras},
author={Chollet, Fran\c{c}ois and others},
year={2015},
howpublished={\url{https://keras.io}},
}
댓글