공부/AIFFEL

FUNDAMENTAL 19. TF2 API 개요

dong_dong_2 2021. 2. 15. 19:54

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()의 활용법을 꼭 숙지해야 한다.