Transformer의 데이터 흐름을 따라 가기
이 기사에 대하여
이 기사는 필자가 Harvard NLP의 PyTorch 구현 을 참고로 Transformer를 구현했을 때 얻은 지견을 정리한 기사입니다.
Transformer의 논문 해설 기사가 아니라는 것을 양해 바랍니다.
Transformer 정보
Transformer란, 「Attention is All You Need」라고 하는 논문으로 등장한 Attention 베이스의 모델로, 아래의 그림과 같은 구조를 하고 있습니다.
모델의 구조를 이해하고 싶은 분은 다음 기사를 읽기 쉽고 추천합니다.
논문 해설 Attention Is All You Need (Transformer) (Ryobot씨)
만들어 이해하기 Transformer / Attention (halhorn씨)
데이터 흐름을 추적
스스로 구현해 본 후 모델 전체의 데이터 흐름을 알고 있으면 Transformer의 구조를 더 쉽게 이해할 수 있었을까 생각하고 모델의 각 시점에서 Tensor가 어떤 모양을 취하고 있는지 라는 것을 정리해 보았습니다.
그림 설명
다음과 같은 설정으로 다이어그램을 만들고 있습니다.
Transformer란, 「Attention is All You Need」라고 하는 논문으로 등장한 Attention 베이스의 모델로, 아래의 그림과 같은 구조를 하고 있습니다.
모델의 구조를 이해하고 싶은 분은 다음 기사를 읽기 쉽고 추천합니다.
논문 해설 Attention Is All You Need (Transformer) (Ryobot씨)
만들어 이해하기 Transformer / Attention (halhorn씨)
데이터 흐름을 추적
스스로 구현해 본 후 모델 전체의 데이터 흐름을 알고 있으면 Transformer의 구조를 더 쉽게 이해할 수 있었을까 생각하고 모델의 각 시점에서 Tensor가 어떤 모양을 취하고 있는지 라는 것을 정리해 보았습니다.
그림 설명
다음과 같은 설정으로 다이어그램을 만들고 있습니다.
또한 그림에서 사용되는 변수에 대한 설명은 표와 같습니다.
변수 이름
내용
batch_size
학습 시 배치 크기
src_len/tgt_len
Encoder/Decoder에 입력하는 문장의 길이
d_model
단어 벡터의 차원 수
h
Multi-Head Attention의 헤드 수
vocab_size
Decoder에서 사용되는 어휘 수
전체도
화상중의 「K」와 「V」가 반대로 되어 있습니다. 죄송합니다.
Attention의 Masking 구현에 대해
Attention의 마스크 구현에 대해 고민했으므로 Harvard NLP에서 Mask의 구현에 대해 정리해 둡니다.
Transformer에서는 아래 그림과 같이 3개소의 Multi-Head Attention(안의 Scaled Dot-Product Attention) 중에서 Masking이 등장합니다.
Harvard NLP 구현은 1과 3에서 사용하는 src_mask와 2에서 사용하는 tgt_mask의 두 가지 마스크를 제공합니다. 이하 각각의 설명입니다.
src_mask
src_mask 는 Encoder 에의 입력문의 패딩을 참조하지 않게 하기 위한 마스크로, 다음과 같이 구현되고 있습니다.
# srcは[batch_size, src_len]
# パディング箇所が0、それ以外が1のTensorを生成
self.src_mask = (src != pad).unsqueeze(-2) # [batch_size, 1, src_len]
src_mask는 [batch_size, 1, src_len]의 형태로 생성됩니다. 이렇게 하면 PyTorch의 브로드캐스트를 이용하여 Self-Attention, SourceTarget-Attention에서 각각 다른 크기의 Tensor에 마스크를 걸 수 있습니다.
(PyTorch1.1.0 브로드 캐스트 문서)
tgt_mask
tgt_mask에는 다음 두 가지 역할이 있습니다.
tgt_mask는 다음과 같이 구현됩니다.
# tgtは[batch_size, tgt_len]
# パディング箇所が0、それ以外が1のTensorを生成
tgt_mask = (tgt != pad).unsqueeze(-2) # [batch_size, 1, tgt_len]
# パディング用のマスクと未来の単語用のマスクを重ねる
tgt_mask = tgt_mask & Variable(
subsequent_mask(tgt.size(-1)).type_as(tgt_mask.data)) # [batch_size, tgt_len, tgt_len]
# 未来の単語を参照しないようにするマスクを作成する関数
def subsequent_mask(size):
attn_shape = (1, size, size) # [1, tgt_len, tgt_len]
# 三角行列の生成
subsequent_mask = np.triu(np.ones(attn_shape), k=1).astype('uint8') # [1, tgt_len, tgt_len]
# 1と0を反転する処理
return torch.from_numpy(subsequent_mask) == 0
tgt_mask는 [batch_size, tgt_len, tgt_len]의 형태로 생성됩니다. 작성할 때는 그림과 같이 패딩을 참조하지 않게 하는 마스크와 미래의 단어를 참조하지 않게 하는 마스크의 2개를 작성한 후 그들을 겹치고 있습니다.
마지막으로
Transformer 내부의 데이터 구조를 쫓는다는 틈새 내용이지만, 조금이라도 누군가의 도움이되면 다행입니다.
Reference
이 문제에 관하여(Transformer의 데이터 흐름을 따라 가기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/FuwaraMiyasaki/items/239f3528053889847825텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)