Ch17. Custom Layer

Why Custom Layer?

  • Keras에 이미 많은 종류의 레이어가 정의되어 있지만, 모든 레이어가 정의되어 있지는 않다.
  • 추가로 필요한 레이어가 존재할 때, 우리는 직접 레이어를 정의하고 활용할 필요가 있다.
  • 혹은 레이어 하나로 반복되는 여러개의 레이어를 묶고 싶을 때도 활용할 수 있다.

Template

class LayerName(keras.layers.Layer): # Layer객체를 상속한다.
    def __init__(self, ...):
        super(LayerName, self).__init__()
        # 레이어에 필요한 가중치나 레이어를 정의할 수 있다.     

    def call(self, inputs):
        # 실제 데이터가 들어오고 나가는 흐름을 작성하면 된다.

        return 
  • 기본적인 템플릿은 다음과 같다.
  • 레이어 객체를 상속하고, init에는 필요한 레이어나 가중치를, call에는 실제 데이터의 흐름을 적으면 된다.

Example1: Linear

  • 다음은 실제 케라스에서 보여주는 Linear Layer의 예시이다.
    class Linear(keras.layers.Layer):
      def __init__(self, units=32, input_dim=32):
          super(Linear, self).__init__()
          w_init = tf.random_normal_initializer()
          self.w = tf.Variable(
              initial_value=w_init(shape=(input_dim, units), dtype="float32"),
              trainable=True,
          )
          b_init = tf.zeros_initializer()
          self.b = tf.Variable(
              initial_value=b_init(shape=(units,), dtype="float32"), trainable=True
          )
    
      def call(self, inputs):
          return tf.matmul(inputs, self.w) + self.b
    
  • init에서는 필요한 가중치를 정의합니다. 가중치는 tf.Variable로 선언할 수 있습니다. (넘파이처럼 활용가능)
  • call에는 데이터가 들어옵니다. 데이터가 들어와서 연산되는 과정을 보여줍니다. 가중치 갱신은 Layer객체가 자동으로 합니다.
  • call은 파이썬 자체의 객체 정의 방식으로
  • 다음과 같은 객체 정의시 hello(init)(call)에서 init에 처음 넣는 값은 init으로, 그 뒤에 붙은 정의된 객체 호출은 call입니다.

Example2: Attention

  • 어텐션은 케라스 2.7.0에 추가되었습니다. 그 전까지는 어텐션이 없었기 때문에 정의해서 사용해주었었습니다.
    class attention(Layer):
      def __init__(self,**kwargs):
          super(attention,self).__init__(**kwargs)
     
      def build(self,input_shape):
          self.W=self.add_weight(name='attention_weight', shape=(input_shape[-1],1), 
                                 initializer='random_normal', trainable=True)
          self.b=self.add_weight(name='attention_bias', shape=(input_shape[1],1), 
                                 initializer='zeros', trainable=True)        
          super(attention, self).build(input_shape)
     
      def call(self,x):
          e = K.tanh(K.dot(x,self.W)+self.b)
          e = K.squeeze(e, axis=-1)   
          alpha = K.softmax(e)
          alpha = K.expand_dims(alpha, axis=-1)
          context = x * alpha
          context = K.sum(context, axis=1)
          return context
    
  • build는 input_shape에 따라 가중치를 생성하는 것입니다.
  • 보통은 미리 input_shape을 알지 못하기 때문에, 다음처럼 작성하는 편이 권장됩니다.

Copyright © 2023 Junseo Ko. 본 내용은 모두 제가 작성한 도큐먼트입니다. 무단 퍼가기와 재생산을 금지합니다. 문의: piglets.frizzle0v@icloud.com