FUNDAMENTAL 19. TF2 API 개요
1. Tensorflow2의 구성과 특징
- Tensorflow V1의 특징과 문제점
1) 거대한 노드-엣지 사이의 유향 비순환 그래프(Directed Acyclic Graph, DAG)로 정의했다.
2) 이러면 노드와 노드를 연결하는 매 엣지마다 chain-rule을 기반으로 gradient가 역방향으로 전파될 수 있다는 간단하면서 강력한 아이디어이다.
3) 이런 방식을 Tensorflow의 Graph Mode라고 한다.
4) 이런 선계의 큰 다점이 하나 있는데, 딥러닝 모델을 구성하는 그래프를 그려나가는 부분과, 연상이 실제 진행되는 과정을 엄격히 분리해 놓았다는 점이다.
5) 여기에 가장 중요한 것이 session이라는 개념이였다. 이 방식이 대규모 분산환경에서의 확장성과 생산성이라는 장점도 있었지만, 기본적으로 사용하기가 어려웠다.
- Eager Mode를 수용하여 Tensorflow V2가 되었다.
1) PyTorch는 Eager Mode라는 것을 제안했는데, 이것은 딥러닝 그래프가 다 그려지지 않아도 부분 실행 및 오류검증이 가능했다.
2) 또한 코드도 간결하고 파이써닉한 설계를 가지고 있어서 개발자들이 훨씬 쉽게 다가갈 수 있었다.
3) Tensorflow도 이 Eager Mode를 수용했고, Keras라는 머신러닝 프레임워크를 수용하여 V2의 표준 API로 삼았다.
4) 덕분에 V2의 코드는 훨씬 직관적이고 간결해졌다. 또한 설계, 구현, 디버깅 전과정을 매우 쉽고 직관적으로 만들어줬다.
- V2가 V1에 대비해 차별화된 장점 : 사용 편의성, 즉시 실행, 설계 구현 용이성, 데이터 파이프라인 단순화
2. Tensorflow2 API로 모델 구성하기
- Tensorflow2에서 딥러닝 모델을 작성하는 방법에는 크게 3가지가 존재한다.
1) Sequential Model
1) 입력부터 출력까지 레이어를 seqiential하게 add하여 쌓아나가는 방식이다.
2) 초보자가 접근하기 매우 쉽다는 장점이 있다.
3) 이 모델은 반드시 1가지 입력, 1가지 출력을 전제로 한다. 입력과 출력이 여러 개인 경우에는 적합하지 않은 모델링 방식이다.
ex) model = keras.Sequential()
model.add(__넣고싶은 레이어__)
model.add(__넣고싶은 레이어__)
model.fit(x, y, epochs = , batch_size = )
2) Functional API
1) Seqiential의 보다 일반화된 개념이다.
2) 이 모델을 활용하는 것과 다른 점은 keras.Model을 사용한다는 점이다. 그래서 Sequential Model을 쓰는 것보다 더 일반적인 접근이다.
3) Sequential Model을 활용하는 것보다 더 자유로운 모델링을 진행할 수 있다.
4) 함수형으로 모델을 구성한다. 즉, 입력과 출력을 규정함으로써 모델 전체를 규정한다는 생각이다.
5) 다중입력과 다중출력을 가지는 모델을 구성할 수 있다.
ex) inputs = keras.Input(shape = (__원하는 입력값 모양__))
x = keras.layers.__넣고싶은 레이어__(관련 파라미터)(inputs)
x = keras.layers.__넣고싶은 레이어__(관련 파라미터)(x)
outputs = keras.layers.__넣고싶은 레이어__(관련 파라미터)(x)
model = keras.Model(inputs = inputs, outputs = outputs)
model.fit(x, y, epochs = , batch_size = )
3) Subclassing
1) 클래스로 구현된 기존의 모델을 상속받아 자신만의 모델을 만들어나가는 방식이다. 제일 자유로운 모델링을 진행할 수 있다.
2) 본질적으로 Functional한 접근과 차이가 없다.
3) __init__()이라는 메소드 안에서 레이어 구성을 정의하고, call()이라는 메소드 안에서 레이어간 forward propagation을 구현한다. 이것이 끝이다.
4) 다만, 각 레이어에 대한 깊은 이해가 필요하고 초심자에게 의도치 않은 버그를 유발할 수 있다.
ex) class CustomModel(keras.model):
def __init__(self):
super(CustomModel, self).__init__()
self.__정의하고자 하는 레이어__()
self.__정의하고자 하는 레이어__()
def call(self, x):
x = self.__정의하고자 하는 레이어__(x)
x = self.__정의하고자 하는 레이어__(x)
return x
model = CustomModel()
model.fit(x, y, epochs = , batch_size = )
3 ~ 5.MNIST를 이용하여 위에서 배운 3가지 모델 구현해보기 : 코드위주의 진행.
6 ~ 8.CIFAR-100을 이용하여 위에서 배운 3가지 모델 구현해보기 : 코드위주의 진행.
9. GradientTape의 활용
- 위에서 비슷한 테스크 2개를 본질적으로 큰 차이 없는 3개의 모델 구성 방법을 활용하여 딥러닝을 구현해봄.
- 이 과정에서 완전히 동일하게 구성한 부분이 model.compile(optimizer = , loss = , metrics = )과 model.fit(x, y, epochs = )이다.
- Numpy만 가지고 딥러닝을 구현해본 것을 회상하면 model.fit()라는 한줄로 수행 가능한 딥러닝 모델 훈련 과정은 실제로 아래의 과정이였다.
1) Forward Propagation 수행 및 중간 레이어값 저장
2) Loss 값 계산
3) 중간 레이어값 및 Loss를 활용한 체인룰(chain rule) 방식의 역전파(Backward Propagation) 수행
4) 학습 파라미터 업데이트
- Tensorflow에서 제공하는 tf.GradientTape은 위와 같이 순전파로 진행된 모든 연산의 중간 레이어값을 tape에 기록하고, 이를 이용해 gradient를 계산한 후 tape를 폐기하는 기능을 수행한다.
- tf.GradientTape()을 활용하면 model.compile()과 model.fit() 안에 감추어져 있던 한 스텝의 학습 단계를 끄집어내서 자유롭게 재구성할 수 있게 된다.
- 흔히 다루어 왔던 지도학습 방식과 다른 강화학습 또는 GAN(Generative Advasarial Network)의 학습을 위해서는 tf.GradientTape()의 활용법을 꼭 숙지해야 한다.