class PositionalEmbedding(nn.Module):
def __init__(self, n_embd, max_len=512):
super().__init__()
position = torch.arange(0, max_len).unsqueeze(1).float()
div_term = torch.exp(torch.arange(0, n_embd, 2).float() * -(math.log(10000.0) / n_embd))
pe = torch.zeros(max_len, n_embd)
pe[:, 0::2] = torch.sin(position * div_term)
pe[:, 1::2] = torch.cos(position * div_term)
self.pe = pe.unsqueeze(0)
self.register_buffer('pe', pe)
def forward(self, x):
return x + self.pe[:, :x.size(1)].detach()
# 언어 모델을 정의하는 함수
class LanguageModel(nn.Module):
def __init__(self, vocab_size):
super().__init__()
self.token_embedding_table = nn.Embedding(vocab_size, n_embd)
self.position_embedding = PositionalEmbedding(n_embd)
self.ln_f = nn.LayerNorm(n_embd)
self.head = nn.Linear(n_embd, vocab_size)
def forward(self, idx, targets=None):
tok_emb = self.token_embedding_table(idx)
pos_emb = self.position_embedding(torch.arange(idx.size(1), device=device))
x = tok_emb + pos_emb
logits = self.head(self.ln_f(x))
주어진 코드는 Transformer 기반의 언어 모델을 구현하는 파이썬 클래스 `PositionalEmbedding`과 `LanguageModel`을 포함하고 있습니다. 이 모델은 토큰 임베딩과 위치 임베딩을 조합하여 문장의 토큰들을 처리하고, 최종 출력(logits)을 생성하는 역할을 합니다.
#### `PositionalEmbedding` 클래스:
이 클래스는 위치 임베딩(Positional Embedding)을 생성하고 관리하는 역할을 합니다.
– `__init__(self, n_embd, max_len=512)`: 초기화 메서드에서는 위치 임베딩을 생성하는데 필요한 파라미터들을 받습니다. `n_embd`는 임베딩 벡터의 차원을 나타내며, `max_len`은 시퀀스의 최대 길이를 나타냅니다.
– 위치 임베딩은 사인(Sine)과 코사인(Cosine) 함수를 사용하여 생성됩니다. `position` 변수는 0부터 `max_len-1`까지의 숫자를 포함하는 벡터를 생성합니다.
– `div_term` 변수는 위치 임베딩에서 사용되는 분모 항(divisor term)으로, 특정 패턴을 생성하기 위해 계산됩니다.
– `pe` 변수는 위치 임베딩 행렬을 초기화합니다. 이 행렬의 크기는 `(max_len, n_embd)`이며, 모든 값은 초기에 0으로 설정됩니다. 그런 다음, 홀수 열(`[:, 1::2]`)에는 코사인 함수 값을 할당하고, 짝수 열(`[:, 0::2]`)에는 사인 함수 값을 할당하여 위치 임베딩을 생성합니다.
– `self.pe` 변수는 위치 임베딩을 담고 있는 텐서를 가리킵니다. 이 텐서는 모델 학습 중에 업데이트되지 않습니다.
– `forward(self, x)`: 이 메서드는 입력으로 받은 `x`에 위치 임베딩을 더한 결과를 반환합니다. 위치 임베딩을 더할 때 `.detach()`를 사용하여 위치 임베딩이 모델의 역전파(backpropagation)에 의해 업데이트되지 않도록 합니다. 따라서 위치 임베딩은 고정된 패턴을 나타냅니다.
#### `LanguageModel` 클래스:
이 클래스는 언어 모델을 나타내며, 토큰 임베딩과 위치 임베딩을 조합하여 최종 입력을 생성하고 출력(`logits`)을 반환합니다.
– `__init__(self, vocab_size)`: 초기화 메서드에서는 언어 모델을 초기화합니다. `vocab_size`는 어휘 사전의 크기를 나타냅니다.
– `self.token_embedding_table`은 토큰 임베딩 테이블로, 단어 인덱스를 임베딩 벡터로 매핑하는 역할을 합니다.
– `self.position_embedding`은 앞서 정의한 `PositionalEmbedding` 클래스의 인스턴스로, 위치 임베딩을 생성합니다.
– `self.ln_f`는 Layer Normalization을 수행하는 레이어를 초기화합니다. 이는 모델의 안정성과 학습 성능을 향상시키는데 사용됩니다.
– `self.head`는 선형 레이어(Linear Layer)로, 최종 출력을 생성하는 역할을 합니다. 입력으로부터 예측 값을 만들어냅니다.
– `forward(self, idx, targets=None)`: 이 메서드는 주어진 토큰 인덱스(`idx`)를 입력으로 받아, 토큰 임베딩과 위치 임베딩을 더하여 최종 입력(`x`)을 생성합니다. 그 후, `self.head`를 사용하여 최종 출력(logits)을 생성합니다. 최종 출력은 모델의 예측 값입니다.
코드에서 `PositionalEmbedding` 클래스는 Transformer 모델에서 위치 정보를 주입하기 위한 중요한 부분이며, `LanguageModel` 클래스는 토큰과 위치 임베딩을 결합하여 모델의 입력을 생성하고, Layer Normalization과 선형 레이어를 사용하여 모델의 출력을 생성하는 역할을 합니다.