본문 바로가기

AI/아이펠_리서치

Transformer Encoder 구현 및 학습

개요

케창딥 11장에 나오는 Transformer Encoder 코드 학습 내용을 정리 합니다.

https://github.com/gilbutITbook/080315/blob/main/chapter11_part04_sequence-to-sequence-learning.ipynb

 

080315/chapter11_part04_sequence-to-sequence-learning.ipynb at main · gilbutITbook/080315

<케라스 창시자에게 배우는 딥러닝 2판> 도서의 코드 저장소. Contribute to gilbutITbook/080315 development by creating an account on GitHub.

github.com

 

TransformerEncoder  클래스 개요

출처 : https://wikidocs.net/31379

 

TransformerEncoder 는 다음과 같은 주요 단계들로 구성되어 있습니다:

  1. MultiHeadAttention
  2. Residual Connection 및 LayerNormalization
  3. Position-wise Feedforward Network
  4. 다시 Residual Connection 과 LayerNormalization

Transformer Encoder 의 하나의 블록을 구현하는 방식으로, 입력 시퀀스의 각 위치 간의 관계를 학습하는 데 사용됩니다.

 

__init__ 메서드

이 메서드는 클래스의 초기화 단계에서 필요한 하위 모듈들을 설정합니다.

  • embed_dim: 입력의 임베딩 차원.
  • dense_dim: 피드포워드 네트워크의 내부 레이어의 차원.
  • num_heads: 멀티 헤드 어텐션의 헤드 수.

주요 하위 레이어 정의

  1. Multi-Head Attention (MultiHeadAttention)
    • 입력 텐서의 다양한 부분 간의 관계를 동시에 모델링하기 위해 멀티 헤드 어텐션을 사용합니다.
    • key_dim은 각 어텐션 헤드의 차원을 나타내며, 입력의 embed_dim과 동일합니다.
  2. Position-wise Feedforward Network (dense_proj)
    • 첫 번째 Dense 레이어는 dense_dim 크기를 가지며, 비선형 활성화 함수 ReLU를 사용합니다.
    • 두 번째 Dense 레이어는 다시 임베딩 차원 (embed_dim)으로 줄어듭니다.
    • 이 네트워크는 시퀀스의 각 위치에 대해 독립적으로 작용합니다.
  3. Layer Normalization (layernorm_1과 layernorm_2)
    • Normalization 를 통해 학습이 더 안정적으로 진행되도록 합니다.
    • 각각 잔차 연결 후의 출력에 적용됩니다.
class TransformerEncoder(layers.Layer):
    def __init__(self, embed_dim, dense_dim, num_heads, **kwargs):
        super().__init__(**kwargs)
        # 임베딩 차원, 피드포워드 네트워크 차원, 멀티 헤드 수 초기화
        self.embed_dim = embed_dim
        self.dense_dim = dense_dim
        self.num_heads = num_heads

        # 멀티 헤드 어텐션 레이어 생성
        self.attention = layers.MultiHeadAttention(
            num_heads=num_heads, key_dim=embed_dim)

        # 피드포워드 네트워크로 구성된 Dense 레이어 시퀀스 생성
        self.dense_proj = keras.Sequential(
            [layers.Dense(dense_dim, activation="relu"),  # 첫 번째 Dense 레이어 (ReLU 활성화 함수 사용)
             layers.Dense(embed_dim),]  # 두 번째 Dense 레이어 (출력 크기는 embed_dim)
        )

        # 두 개의 Layer Normalization 레이어 생성
        self.layernorm_1 = layers.LayerNormalization()
        self.layernorm_2 = layers.LayerNormalization()

    def call(self, inputs, mask=None):
        # 마스크가 주어진 경우 차원을 확장하여 어텐션 레이어에 맞게 변환
        if mask is not None:
            mask = mask[:, tf.newaxis, :]

        # 멀티 헤드 어텐션 적용 (쿼리, 키, 값은 모두 입력으로 사용)
        attention_output = self.attention(
            inputs, inputs, attention_mask=mask)

        # 어텐션 출력과 입력의 잔차 연결 후 Layer Normalization 적용
        proj_input = self.layernorm_1(inputs + attention_output)

        # 피드포워드 네트워크 적용
        proj_output = self.dense_proj(proj_input)

        # 피드포워드 출력과 이전 결과의 잔차 연결 후 Layer Normalization 적용
        return self.layernorm_2(proj_input + proj_output)

    def get_config(self):
        # 객체를 직렬화하기 위해 필요한 구성 정보 반환
        config = super().get_config()
        config.update({
            "embed_dim": self.embed_dim,
            "num_heads": self.num_heads,
            "dense_dim": self.dense_dim,
        })
        return config

 

TransformerEncoder 시각화

      ┌──────────┐
      │  Output  │
      └─────▲────┘
            │
      ┌─────┴────┐
      │ Add &    │
      │ LayerNorm│  (Layer Normalization 2)
      └─────▲────┘
            │
      ┌─────┴────────────┐
      │ Feedforward      │
      │ Dense Network    │
      │ [Dense (embed_dim)] │
      │ [Dense (ReLU)]   │
      └─────▲────────────┘
            │
      ┌─────┴────┐
      │ Add &    │
      │ LayerNorm│  (Layer Normalization 1)
      └─────▲────┘
            │
      ┌─────┴──────────────┐
      │ Multi-Head Attention│
      │ [inputs -> Q, K, V] │
      │ (Attention Weights) │
      └─────▲──────────────┘
            │
      ┌─────┴────┐
      │  Input   │
      │ Tensor   │
      └──────────┘

각 블록의 설명

  1. Input Tensor
    • Transformer 인코더 블록의 시작점입니다. 입력 데이터는 시퀀스 길이 N과 임베딩 차원 D를 가지는 텐서 형태로 들어옵니다.
  2. Multi-Head Attention
    • 입력 텐서가 쿼리(Q), 키(K), 값(V)로 분리되어 멀티 헤드 어텐션 연산이 수행됩니다.
    • 여러 헤드를 사용하여 서로 다른 관계를 학습하고, 어텐션 가중치를 통해 시퀀스 내 다른 위치 간의 연관성을 모델링합니다.
  3. Add & Layer Normalization 1
    • 어텐션 출력에 원래 입력을 더한 뒤, 레이어 정규화를 수행합니다.
    • 잔차 연결을 통해 정보가 보존되며 학습 안정성이 높아지고, Layer Normalization은 모델의 학습 효율성을 높입니다.
  4. Feedforward Dense Network
    • 정규화된 출력은 포지션-와이즈 피드포워드 네트워크로 전달됩니다.
    • 이 네트워크는 두 개의 Dense 레이어로 구성되며:
      • 첫 번째 Dense 레이어에서 dense_dim 차원으로 확장한 뒤 ReLU 활성화 함수가 적용됩니다.
      • 두 번째 Dense 레이어에서 다시 임베딩 차원 (embed_dim)으로 축소합니다.
  5. Add & Layer Normalization 2
    • 피드포워드 네트워크의 출력에 이전 단계의 입력을 더한 뒤, 다시 한 번 레이어 정규화를 수행합니다.
    • 잔차 연결Layer Normalization은 학습의 안정성을 보장하고, 더 깊이 있는 특징을 효과적으로 학습할 수 있도록 합니다.
  6. Output
    • 최종 출력입니다. 이 출력은 다음 레이어로 전달될 수 있거나, 여러 인코더 블록이 쌓여 있을 경우 다음 인코더 블록의 입력으로 사용됩니다.