개요
케창딥 11장에 나오는 Transformer Encoder 코드 학습 내용을 정리 합니다.
TransformerDecoder 클래스 개요
TransformerDecoder 는 다음과 같은 주요 단계들로 구성되어 있습니다:
- Masked Self-Attention
- Position-wise Feedforward Network
- Layer Normalization
- Encoder-Decoder Attention
Transformer Decoder 의 하나의 블록을 구현하는 방식으로, 입력 시퀀스와 출력 시퀀스 각 위치 간의 관계를 학습하는 데 사용됩니다.
init 메서드
- embed_dim: 입력 임베딩 차원.
- dense_dim: 피드포워드 네트워크의 내부 레이어의 차원.
- num_heads: 멀티 헤드 어텐션의 헤드 수.
레이어 정의
- 멀티 헤드 어텐션 (attention_1, attention_2)
- attention_1: 첫 번째 멀티 헤드 어텐션 레이어로, 디코더의 입력에 대한 셀프 어텐션을 수행합니다.
- attention_2: 두 번째 멀티 헤드 어텐션 레이어로, 인코더의 출력(encoder_outputs)에 대한 Encoder-Decoder Attention 을 수행합니다.
- Position-wise Feedforward Network (dense_proj)
- 두 개의 Dense 레이어로 구성된 시퀀스:
- 첫 번째 Dense 레이어는 dense_dim 크기이며, 활성화 함수로 ReLU를 사용합니다.
- 두 번째 Dense 레이어는 임베딩 차원으로 출력을 매핑합니다.
- 두 개의 Dense 레이어로 구성된 시퀀스:
- Layer Normalization (layernorm_1, layernorm_2, layernorm_3)
- 각 Attention 출력 및 Feedforward Network 출력에 Layer Normalization을 적용하여 학습의 안정성을 높입니다.
- 마스킹 지원 (supports_masking = True)
- Decoder 에서 마스킹을 지원하도록 설정합니다. 이는 패딩 토큰이나 미래 시점 예측 방지를 위한 causal masking 을 처리할 수 있게 해줍니다.
- get_config 메서드
- 객체를 직렬화하기 위해 필요한 설정 정보를 반환합니다.
call 메서드
- Decoder 의 입력을 처리하는 핵심적인 메서드입니다.
- inputs: 디코더의 입력입니다 (보통 이전 단계의 출력을 사용).
- encoder_outputs: 인코더의 최종 출력입니다.
- mask: 어텐션에서 특정 위치를 무시하도록 하기 위한 마스크입니다.
- Masked Self-Attention (attention_1)
- 쿼리, 키, 값이 모두 inputs으로 설정되어 Self-Attention을 수행합니다.
- use_causal_mask=True: 현재 시점 이후의 토큰을 보지 않도록 causal mask 를 사용합니다. 이는 디코더에서 미래 정보를 참조하지 않도록 보장하는 역할을 합니다.
- Layer Normalization 1
- Residual Connection : inputs 과 attention_output_1 을 더합니다.
- Layer Normalization을 적용하여 정규화합니다.
- Encoder-Decoder Attention (attention_2)
- 쿼리는 디코더 어텐션의 출력(attention_output_1), 키와 값은 인코더의 출력(encoder_outputs)을 사용하여 Encoder-Decoder Attention 을 수행합니다.
- 디코더 입력과 인코더 출력 간의 연관성을 학습합니다.
- Layer Normalization 2
- Residual Connection 과 Layer Normalization을 통해 안정적으로 학습합니다.
- Position-wise Feedforward Network
- 두 개의 Dense 레이어로 구성된 Feedforward Network 를 통과시켜 각 위치의 표현을 변환합니다.
- Layer Normalization 3
- Residual Connection 과 Layer Normalization을 마지막으로 적용하여 최종 출력을 반환합니다.
class TransformerDecoder(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_1 = layers.MultiHeadAttention(
num_heads=num_heads, key_dim=embed_dim)
# 두 번째 멀티 헤드 어텐션 레이어 생성 (인코더-디코더 어텐션)
self.attention_2 = 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() # 두 번째 어텐션 후 정규화
self.layernorm_3 = layers.LayerNormalization() # 피드포워드 네트워크 후 정규화
# 마스킹 지원 설정 (패딩 마스킹 지원을 위한 설정)
self.supports_masking = True
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
def call(self, inputs, encoder_outputs, mask=None):
# 첫 번째 멀티 헤드 어텐션 적용 (셀프 어텐션, 인과적 마스크 사용)
attention_output_1 = self.attention_1(
query=inputs,
value=inputs,
key=inputs,
use_causal_mask=True) # 미래 정보를 보지 않도록 인과적 마스크 적용 (디코더의 셀프 어텐션)
# 첫 번째 어텐션 출력과 입력의 잔차 연결 후 Layer Normalization 적용
attention_output_1 = self.layernorm_1(inputs + attention_output_1) # 잔차 연결을 통해 원본 정보 보존 및 정규화
# 두 번째 멀티 헤드 어텐션 적용 (인코더-디코더 어텐션)
attention_output_2 = self.attention_2(
query=attention_output_1,
value=encoder_outputs,
key=encoder_outputs
) # 인코더의 출력과 디코더의 출력 간의 어텐션을 계산하여 상호 참조
# 두 번째 어텐션 출력과 이전 출력의 잔차 연결 후 Layer Normalization 적용
attention_output_2 = self.layernorm_2(
attention_output_1 + attention_output_2) # 잔차 연결을 통해 이전의 정보 보존 및 정규화
# 피드포워드 네트워크 적용 (Dense 레이어 시퀀스를 통해 출력 변환)
proj_output = self.dense_proj(attention_output_2)
# 피드포워드 출력과 이전 출력의 잔차 연결 후 Layer Normalization 적용
return self.layernorm_3(attention_output_2 + proj_output) # 최종 출력에 대해 잔차 연결 및 정규화 적용
TeansformerDcoder 시각화
┌──────────────┐
│ Output │
└──────▲───────┘
│
┌──────┴───────┐
│ Add & Norm 3 │
└──────▲───────┘
│
┌──────┴─────────────┐
│ Feedforward │
│ Dense Network │
│ [Dense (ReLU)] │
│ [Dense (embed_dim)]│
└──────▲─────────────┘
│
┌──────┴───────┐
│ Add & Norm 2 │
└──────▲───────┘
│
┌──────┴─────────────┐
│ Encoder-Decoder │
│ Attention (Attention 2) │
└──────▲─────────────┘
│
┌──────┴───────┐
│ Add & Norm 1 │
└──────▲───────┘
│
┌──────┴───────┐
│ Multi-Head │
│ Self-Attention│
│ (Attention 1)│
└──────▲───────┘
│
|
┌──────────────┐
│ Input │
└──────────────┘
각 블록의 설명
- Input Tensor
- Transformer 디코더 블록의 시작점입니다. 입력 데이터는 시퀀스 길이 N과 임베딩 차원 D를 가지는 텐서 형태로 들어옵니다.
- Multi-Head Self-Attention (Attention 1)
- 입력 텐서가 쿼리(Q), 키(K), 값(V)로 분리되어 멀티 헤드 셀프 어텐션 연산이 수행됩니다.
- 여러 어텐션 헤드를 사용하여 입력 시퀀스의 각 위치가 다른 위치와 어떻게 연관되는지를 학습합니다.
- causal mask 를 사용하여 미래 시점의 정보가 참조되지 않도록 합니다.
- Add & Layer Normalization 1
- 셀프 어텐션 출력에 원래 입력을 더한 뒤, 레이어 정규화를 수행합니다.
- 잔차 연결을 통해 원래의 정보를 보존하며 학습의 안정성을 높이고, Layer Normalization을 통해 학습 효율성을 높입니다.
- Encoder-Decoder Attention (Attention 2)
- 첫 번째 어텐션의 출력이 쿼리(Q)로 사용되고, 인코더의 출력이 키(K)와 값(V)으로 사용됩니다.
- 인코더-디코더 어텐션은 디코더 입력과 인코더 출력 간의 연관성을 학습하여, 인코더의 정보를 활용해 디코더의 출력을 생성하는 데 도움을 줍니다.
- Add & Layer Normalization 2
- 인코더-디코더 어텐션의 출력에 이전 단계의 입력을 더한 뒤, 다시 한 번 레이어 정규화를 수행합니다.
- 잔차 연결과 Layer Normalization을 통해 모델의 학습을 안정적으로 진행할 수 있도록 합니다.
- Feedforward Dense Network
- 정규화된 출력은 포지션-와이즈 피드포워드 네트워크로 전달됩니다.
- 이 네트워크는 두 개의 Dense 레이어로 구성됩니다:
- 첫 번째 Dense 레이어에서 dense_dim 차원으로 확장한 뒤 ReLU 활성화 함수가 적용됩니다.
- 두 번째 Dense 레이어에서 다시 임베딩 차원 (embed_dim)으로 축소합니다.
- Add & Layer Normalization 3
- 피드포워드 네트워크의 출력에 이전 단계의 입력을 더한 뒤, 마지막으로 레이어 정규화를 수행합니다.
- 잔차 연결과 Layer Normalization을 통해 모델의 학습을 안정적으로 진행하며, 출력의 품질을 높입니다.
- Output
- 최종 출력입니다. 이 출력은 다음 레이어로 전달되거나, Transformer 구조 내에서 디코더의 다음 단계 입력으로 사용될 수 있습니다.
'AI > 아이펠_리서치' 카테고리의 다른 글
Transformer 를 사용한 seq2seq 모델 실습 (4) | 2024.11.27 |
---|---|
Transformer Encoder 구현 및 학습 (2) | 2024.11.25 |
KerasTuner 와 Tensorboard 로 HyperParameter 시각화하기 (1) | 2024.11.23 |
TensorFlow 사용자 정의 metric 만들기 (1) | 2024.11.17 |
CNN 과 RNN 대표 모델 (3) | 2024.11.09 |