인공지능(Artificial Intelligence)/자연어 처리(natural language processing)

[tensorflow] 자연어처리(NLP) 2. 모델만들기(Model)

HAN_PY 2020. 11. 3. 20:25
반응형

tensorflow로 모델 만들기

 

0. 들어가면서 

우리는 전 단계에서 모델을 구성하는 layers에 대해 알아 보았다. 관련 내용은 아래의 링크를 따라가 보자.

han-py.tistory.com/269

 

[tensorflow] 자연어처리(NLP) 1. 기초다지기(layers)

0. 들어가면서  자연어처리, 즉 글자를 컴퓨터가 이해할 수 있게 만드는 것이다. CNN과 RNN의 차이도 모르고, 단 한번도 구현해 본 적이 없다면, 이곳은 오아시스 같은 해결책을 줄 수 있을 것이다.

han-py.tistory.com

이제는 layer로 구성된 model을 만들어 보자.

 

 

 

1. tensorflow 2.0

 나도 처음에 자연어처리 관련 구글링을 해서 tensorflow관련 코드를 찾아서 colab에서 진행해보면 안되는 경우가 있다. session.run()을 못알아 먹는다...... 그러한 이유는 옛날에 작성된 tensorflow 1.x 버전의 코드를 사용하고 있는거다. tensorflow 2버전으로 오르면서 먼저 API Cleanup이 되었다. 버전 1 때는 같은 기능을 수행하는 다양한 API가 다양한 패키지 속에 있었다. 이러한 동일한 기능을 하는 API를 통합하고 잘 사용하지 않는 API를 제거했다.

 

두번째로는 Eager execution이다. 버전 1에서는 텐서플로 API를 이용해 그래프를 만든 후 별도 세션을 통해 그래프를 실해해야 했다. 그래서 버전 1에서는 session.run()을 통해 그래프를 추가로 실행해야한 연산의 결과를 알 수 있었다. 그러나 버전2.0 부터는 파이썬과 동일한 eager 모드가 실행되기 때문에 세션을 불러올 필요없이 바로바로 값을 확인 할 수 있다.

 

 

2. 모델 구축

텐서플로우 2.0부터는 keras를 활용하여 모델을 구축하고 학습하는 것을 권장한다. keras를 활용해 모델을 구축하는 방법은 아래와 같다.

 

  1. Sequential API
  2. Funtional API
  3. Functional/Sequential API  + Custom Layer
  4. Subclassing( Custom Model )

우리는 이러한 방법 가운데 Subclassing을 주로 이용해 모델을 구축하게 될 것이다.

 

 

 

 

3. Sequential API

 tf.keras.Sequential은 케라스를 활용해 모델을 구축할 수 있는 가장 간단한 형태의 API이다. Sequential 모듈을 이용하면 간단한 순차적인 레이어의 스택을 구현할 수 있다. 다음은 Suquential 모듈을 이용하여 fully-connected layer를 구현한 것이다.

from tensorflow.keras import layers

model = tf.keras.Sequential()
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(10, activation='softmax'))

위의 예와 같이 Sequential 모듈의 경우 구현이 매우 쉽다. 단지, Sequential 인스턴스를 생성 후에 인스턴스에 순차적으로 layer를 더해주면 모델이 완성된다. 

+만약 relu함수와 sotfmax에 대한 간단한 정리를 보고 싶다면 아래의 사이트를 다녀오자.

han-py.tistory.com/266

 

이러한 쉬워보이는 Sequential 모듈의 경우에도 모델구현에 제약이 있는 경우가 있다. 예를들면 VQA(Visual Question Answering) 문제, 사진과 질문이 입력값으로 주어지고 질문에 답하는 문제의 경우는 특징을 뽑는 두 레이어가 각각 순차적으로 존재하기 때문에 Suquential 모듈이 사용 불가능하다. 즉, Suquential 모듈은 하나의 플로만 계산가능하다. 두 개의 플로를 계산하기 위해서는 아래의 다른 모델을 사용하도록 하자.

 

 

 

 

4. Functional API

 앞에서 본 Sequential 모듈은 간단한 레이어들의 스택 구조에 적합하다. 그러나 복잡한 모델의 경우에는 구현의 제약이 있다는 것을 보았다. 구현제약의 예는 아래와 같다.

  • 다중 입력값 모델(Multi-input models)
  • 다중 출력값 모델(Multi-output models)
  • 공유 층을 활용하는 모델(Models with shared layers)
  • 데이터 흐름이 순차적이지 않은 모델(Models with non-sequential data flows)

이러한 모델을 구현 시 Fuctional API를 사용하거나 Subclassing 방식을 사용하는 것이 적절하다. 이제 Functional API를 활용해서 앞에서 정의한 모델과 동일한 모델을 만들어 보자.

inputs = tf.keras.Input(shape=(32,))
x = layers.Dense(64, activation='relu')(inputs)
x = layers.Dense(64, activation='relu')(x)
predictions = layers.Dense(10, activation='softmax')(x)

Functional API를 활용하기 위해서는 입력값을 받는 Input 모듈을 선언해야한다. 그리고 input 모듈을 선언 시에 모델의 입력으로 받는 값의 형태(shape)를 정의해 줘야한다. 정의한 후에 입력값을 적용할 레이어를 호출할 때 인자로 전달하는 방식을 구현해 주면 된다.

 

 

 

 

5. Custom Layer(층)

 이 부분을 모델이 아니라 모델에 들어갈 수 있는 layer를 만드는 부분임을 인지하고 읽자. custom model은 6번에서 나올 예정이다.

 

위의 두 API는 케라스의 layers 패키지에 정의된 레이어로 구현했다. 그러나 새로운 연산을 하는 레이어나 여러 레이어를 하나로 묶은 레이어의 경우는 사용자 정의 층(custom layer)을 만들어 사용하면 된다. 즉, 위에서는 여러개의 dense 층이 사용된 신경망을 사용했지만, 이러한 신경망을 하나의 레이어로 묶어 사용하려면 다음과 같이 사용자 정의 층으로 정의하면 된다.

class CustomLayer(layers.Layer):
    def __init__(self, hidden_dimension, hidden_dimension2, output_dimension):
        self.hidden_dimension = hidden_dimension
        self.hidden_dimension2 = hidden_dimension2
        self.output_dimension = output_dimension
        super(CustomLayer, self).__init__() # super은 상속받은 Layer에서의 init를 여기서 실행하도록 한다.
        
    def build(self, input_shape):
        self.dense_layer1 = layers.Dense(self.hidden_dimension, activation= 'relu')
        self.dense_layer2 = layers.Dense(self.hidden_dimension2, activation= 'relu')
        self.dense_layer3 = layers.Dense(self.output_dimension, activation= 'softmax')
        
    def call(self, inputs):
        x = self.dense_layer1(inputs)
        x = self.dense_layer2(x)
        
        return self.dense_layer3(x)

 사용자 측을 정의 시 먼저 layers 패키지의 Layer 클래스를 상속받고, 위와 같이 3개의 메서드를 정의해주면 된다.

  • 하이퍼파라미터는 객체를 생성할 때 호출되도록 __init__ 메서드에서 정의한다.
  • 모델의 가중치와 관련된 값은 build 메서드에서 생성되도록 정의한다.
  • 위의 정의한 메서드를 이용해 call 메서드에서 해당 층의 로직을 정의하면 된다.

 

Custom Layer를 정의하면 Sequential API이나 Functional API를 활용 시 하나의 층으로 사용할 수 있다. 위에서 정의한 CustomLayer를 Sequential 모듈을 활용한다면 다음과 같다.

from tensorflow.keras import layers

model = tf.keras.Sequential()
model.add(CustomLayer(64, 64, 10))

 

 

 

 

 

6. Subclassing ( Custom Model )

 이 부분이 우리가 가장 많이 활용하는 방법이고, 자유도가 가장 높다. 이 경우는 tf.keras.Model을 상속받고 모델 내부 연산들을 직접 구현하면 된다. 모델 클래스를 구현 시 객체를 생성할 때 호출되는 __init__ 메서드와 생성된 인스턴스를 호출해여 모델 연산 시 호출되는 call 메서드만 구현해주면 된다. 

 

구현한 모델을 Model 클래스로 상속받아 구현해 보자.

class MyModel(tf.keras.Model):
    def __init__(self, hidden_dimension, hidden_dimension2, output_dimension):
        super(MyModel, self).__init__(name='my model')
        self.dense_layer1 = layers.Dense(hidden_dimension, activation= 'relu')
        self.dense_layer2 = layers.Dense(hidden_dimension2, activation= 'relu')
        self.dense_layer3 = layers.Dense(output_dimension, activation= 'softmax')
        
    def call(self, inputs):
        x = self.dense_layer1(inputs)
        x = self.dense_layer2(x)
        
        return self.dense_layer3(x)
  • __init__ 매서드를 통해 모델에 사용될 층과 변수를 정의한다.
  • call 메서드를 통해 정의한 내용을 활용해 모델 연산을 진행한다.
  • + 5번에서 배운 custom layer도  Sustom Model에 적용가능하다.

 

 

 

 

7. 정리

 지금까지 4가지 방법의 모델 구축 방법을 알아보았으니, 모델을 학습하러 가보자.

반응형