Keras는 딥러닝 모델을 빠르고 간편하게 개발할 수 있도록 다양한 기본 레이어를 제공한다. 하지만 모든 경우에 기본 레이어만으로는 원하는 모델을 구현하기 어려울 수 있다. 예를 들어, 특정 계산이 포함된 복잡한 레이어나, 데이터의 특징에 맞춘 맞춤형 레이어가 필요할 때가 있다. 이럴 때 tf.keras.layers.Layer를 상속받아 자신만의 레이어를 구현할 수 있다.
사용자 정의 레이어는 다음과 같은 경우 유용하다.
1. 특수한 계산이 필요한 경우: 기존 레이어로 구현하기 어려운 복잡한 연산을 수행할 때
2. 학습 가능한 파라미터 추가: 원하는 방식으로 학습 가능한 가중치와 편향을 정의할 수 있음
3. 재사용 가능한 컴포넌트: 여러 모델에서 사용할 수 있는 모듈형 레이어를 설계할 때
4. 연산 최적화: 특정 연산을 GPU 또는 TPU에 최적화하려는 경우
기본적으로 사용자 정의 레이어는 tf.keras.layers.Layer를 상속받아 만들며, Keras의 Functional API 또는 Sequential API와 호환된다. 사용자 정의 레이어를 설계할 때는 크게 다음 세 가지 메서드가 중요하다.
1. __init__: 초기화 메서드로, 레이어에서 사용할 주요 파라미터 정의
2. build: 입력 텐서의 크기에 따라 가중치 등 상태 초기화
3. call: 레이어의 순전파(Forward) 계산 정의
Keras에서 사용자 정의 레이어를 구현하려면 tf.keras.layers.Layer 클래스를 상속받아 다음 주요 메서드들을 정의해야 한다.
__init__ 메서드__init__ 메서드 호출 import tensorflow as tf
class CustomDenseLayer(tf.keras.layers.Layer):
def __init__(self, units, **kwargs):
super(CustomDenseLayer, self).__init__(**kwargs)
self.units = units
build 메서드self.add_weight 메서드를 사용해 변수 추가 def build(self, input_shape):
self.w = self.add_weight(shape=(input_shape[-1], self.units),
initializer="random_normal",
trainable=True)
self.b = self.add_weight(shape=(self.units,),
initializer="zeros",
trainable=True)
call 메서드 def call(self, inputs):
return tf.matmul(inputs, self.w) + self.b
위의 내용을 바탕으로 완성된 사용자 정의 Dense 레이어는 다음과 같다.
class CustomDenseLayer(tf.keras.layers.Layer):
def __init__(self, units, **kwargs):
super(CustomDenseLayer, self).__init__(**kwargs)
self.units = units
def build(self, input_shape):
self.w = self.add_weight(shape=(input_shape[-1], self.units),
initializer="random_normal",
trainable=True)
self.b = self.add_weight(shape=(self.units,),
initializer="zeros",
trainable=True)
def call(self, inputs):
return tf.matmul(inputs, self.w) + self.b
사용자 정의 레이어를 구현한 후, 이를 실제 모델에 적용하는 방법을 알아보자. Keras의 Functional API를 활용하면 더욱 유연하고 직관적인 모델 설계가 가능하다.
import tensorflow as tf
from tensorflow.keras import Model, Input
# 사용자 정의 레이어
class CustomDenseLayer(tf.keras.layers.Layer):
def __init__(self, units, **kwargs):
super(CustomDenseLayer, self).__init__(**kwargs)
self.units = units
def build(self, input_shape):
self.w = self.add_weight(shape=(input_shape[-1], self.units),
initializer="random_normal",
trainable=True)
self.b = self.add_weight(shape=(self.units,),
initializer="zeros",
trainable=True)
def call(self, inputs):
return tf.matmul(inputs, self.w) + self.b
# 모델 설계
inputs = Input(shape=(4,))
x = CustomDenseLayer(8)(inputs)
x = tf.keras.layers.ReLU()(x)
outputs = tf.ekras.layers.Dense(1, activation='sigmoid')(x)
model = Model(inputs=inputs, outputs=outputs)
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
model.fit(x_train, y_train, epochs=10, batch_size=8)
사용자 정의 레이어를 포함한 모델을 저장하고 로드하는 과정은 일반적인 Keras 모델과 크게 다르지 않다. 그러나 사용자 정의 객체를 처리하기 위해 custom_objects를 등록하거나, get_config 메서드를 구현하는 것이 중요하다. 모델 저장 시 get_config 메서드를 정의하면, 사용자 정의 레이어의 매개변수 정보가 함께 저장된다. 이를 통해 로드 시 추가적인 사용자 정의 객체 등록 없이도 레이어를 복원할 수 있다.
class CustomDenseLayer(tf.keras.layers.Layer):
def __init__(self, units, **kwargs):
super(CustomDenseLayer, self).__init__(**kwargs)
self.units = units
def build(self, input_shape):
self.w = self.add_weight(shape=(input_shape[-1], self.units),
initializer="random_normal",
trainable=True)
self.b = self.add_weight(shape=(self.units,),
initializer="zeros",
trainable=True)
def call(self, inputs):
return tf.matmul(inputs, self.w) + self.b
def get_config(self):
config = super(CustomDenseLayer, self).get_config()
config.update({"units": self.units})
return config
# 저장 및 로드 시 get_config 활용
model.save("custom_layer_model_with_config.h5")
loaded_model = load_model("custom_layer_model_with_config.h5",
custom_objects={"CustomDenseLayer": CustomDenseLayer})
Keras에서 사용자 정의 레이어를 구현하고 활용하는 과정은 딥러닝 모델에 있어 유연성과 확장성을 더해준다. 이를 통해 기존의 기본 레이어로는 해결하기 어려운 복잡한 연산이나 특화된 요구사항을 만족시킬 수 있다.