Transformer
RNN(Recurrent Neural Network)
- RNN의 장점
- 가변적인 길이의 Input Sequence를 처리할 수 있음.
- 입력이 많아져도 모델의 크기는 증가하지 않음.
- (이론적으로) t 시점에서 수행된 계산은 여러 단계 이전의 정보를 사용할 수 있음.
- 모든 단계에서 동일한 가중치가 적용됨.
- RNN의 단점
- Recurrent computation이 느림.
- Sequence output inference는 병렬화(parallelization)가 어려움.
- 바닐라(=기본) RNN은 훈련 중 기울기 소실(vanishing gradient) 문제를 겪음.
- 바닐라 RNN은 종종 시퀀스 내 장거리 의존성(long-rangedependence)를 모델링 하는데
실패함.- 가장 최근에 들어온 정보 위주로 기억하기 때문에 기존의 정보가 사라지는 문제가 발생
- 전체 sequence가 길이에 관계 없이 single embedding으로 encoding됨.
- 따라서, long sequences에서는 informationloss가 불가피함.
- 이전에 입력된 정보는 더 많이 잊혀지는 경향이 있음.
- 가장 최근에 들어온 정보 위주로 기억하기 때문에 기존의 정보가 사라지는 문제가 발생
- 실제로는 여러 단계 이전의 정보에 접근하기 어려움.
LSTM (Long Short Term Memory)
Seq2seq (Sequence-to-Sequence)
Implementation: Encoder
EncoderLSTM (nn. Module) :
class
def __init__(self, input_size, embedding_size, hidden_size, num_layers, p) :
super(EncoderLSTM, self).__init__()
self.input_size = input_size # one-hot input의 길이
self.embedding_size = embedding_size # input token (word embedding)차원
self.hidden_size = hidden_size # hidden representation 차원
self.num_layers = num_layers # LSTM 내 레이어 개수
self.**dropout** = **nn.Dropout(p)**
self.embedding = nn.Embedding(self.input_size, self.embedding_size) #벡터화
self.LSTM = nn.LSTM(self.embedding_size, hidden_size, num_layers, dropout=p)
def forward(self, x):
# shape: [sequence Length, batch size, embedding dims J
embedding = self.dropout(self.embedding(x))# x를 embedding 벡터화
# outputs shape: [sequence length, batch size, hidden_size]
# hs, cs shape: [num_layers, batch_size, hidden_size]
outputs, (hidden_state, cell_state) = self.LSTM(embedding)
# outputs => y1, y2 / hidden_state가 LSTM이기 때문에 cell_state도 같이
return hidden_state, cell_state
# seq2seq 모델은 encoder에서 hidden_state만 필요해서 outputs는 리턴하지 않음
Dropout
Dropout은 과적합(overfitting)을 방지하기 위해 사용되는 정규화 기법
학습 과정에서 특정 뉴런에 의존하지 않도록 일부 뉴런을 무작위로 비활성화(즉, 0으로 설정)함으로써 모델의 일반화 능력을 향상시킴
Encoder와 Decoder 모두 Dropout을 적용하여 임베딩 벡터에 노이즈를 추가함으로써 과적합을 방지하고, 모델이 더 일반화된 패턴을 학습하도록 함
더 나아가, Encoder와 Decoder 모두에 Dropout을 적용함으로써 임베딩 벡터에 동일한 정규화 기법을 일관되게 적용할 수 있음 → 모델 전체의 성능을 높이는 데 도움
→ 시퀀스를 임베딩 공간으로 전환하는 self.embedding()
Implementation: Decoder
class DecoderLSTM(nn.Module):
def __init__(self, input_size, embedding_size, hidden_size, num_layers, p, output_size):
super(DecoderLSTM, self).__init__()
self.input_size = input_size # one-hot input 의 길이
self.embedding_size = embedding_size # input token (word embedding) 차원
self.hidden_size = hidden_size # hidden representation 차원
self.num_layers = num_layers # LSTM 내 레이어 개수
self.output_size = output_size # one-hot output 길이 (output language vocab size)
self.dropout = nn.Dropout(p)
self.embedding = nn.Embedding(self.input_size, self.embedding_size)
self.LSTM = nn.LSTM( self.embedding_size, hidden_size, num_layers, dropout = p)
self.fc = nn.Linear( self.hidden_size, self.output_size)
def forward(self, x, hidden_state, cell_state):
x = x.unsqueeze(0) # shape of x: [1, batch_size]
embedding = self.dropout(self.embedding(x)) # shape: [1, batch size, embedding dims]
# outputs shape: [1, batch size, hidden_size]
# hs, cs shape: [num_layers, batch_size, hidden_size] ← hs, cs from Encoder
outputs, (hidden_state, cell_state) = self.LSTM(embedding, (hidden_state, cell_state))
predictions = self.fc(outputs) # shape: [1, batch_size, output_size]
predictions = predictions.squeeze(0) # shape: [batch_size, output_size]
return predictions, hidden_state, cell_state
Implementation: Seq2seq Interface
class Seq2Seq(nn.Module):
def __init__(self, Encoder_LSTM, Decoder_LSTM):
super(Seq2Seq, self).__init__()
self.Encoder_LSTM = Encoder_LSTM
self.Decoder_LSTM = Decoder_LSTM
def forward(self, source, target):
batch_size = source.shape[1] # source shape: [input language seq len, num_sentences]
# num_sentences = 한 배치(batch) 안에 있는 문장의 개수, 즉 배치 크기(batch size)를 나타냄
target_len = target.shape[0] # target shape: [output language seq len, num_sentences]
target_vocab_size = len(english.vocab)
outputs = torch.zeros(target_len, batch_size, target_vocab_size)
hs, cs = self.Encoder_LSTM(source)
#hs = hidden state, cs = cell state
x = target[0] # Trigger token <SOS>; shape: [batch_size]
# SOS token = Start Of Sentence
for i in range(1, target_len):
output, hs, cs = self.Decoder_LSTM(x, hs, cs)
outputs[i] = output
x = output.argmax(1)
return outputs # shape: [output language seq len, batch_size, target_vocab_size]
Attention
- Attention 함수: Attention (Q, K, V) = Attention 값
query(context)와 key-valuepairs(references)가 입력되면, attention 값은 value들의 가중치 평균이며, 여기서 각 weight는 relevance query와 corresponding key 간의 관련성에 비례함. - Q와 K는 비교 가능해야 함. (일반적으로 동일한 dimensionality를 가짐)
- V와 Attention value는 당연하게도 동일한 dimensionality를 가져야 함. (V와 Q&K는 달라도 OK)
- 많은 응용 사례에서 이 4가지 요소는 모두 동일한 dimensionality를 가짐.
Attention Is All You Need 논문 참고
'Study - AI > Machine Learning' 카테고리의 다른 글
선형 대수 (0) | 2025.01.06 |
---|---|
Machine Learning Life Cycle (0) | 2025.01.06 |