1. 들어가며
요즈음 가장 핫한 모델인 ChatGPT는 Transformer를 기반으로 만들어진 딥러닝 모델입니다. 이 Transformer의 핵심 기능은 단연 Self Attention이라고 할 수 있죠. Transformer를 기점으로 Self Attention은 대부분의 딥러닝 모델이 갖추어야 하는 필수 기능이 되어가고 있습니다. 이미지 데이터를 처리하는 Vision Model들 조차도 기존의 CNN 기반에서 Self Attention 기반의 방법으로 전환되는 추세이죠. Attention, 더 나아가 Self Attention은 무엇일까요? Self Attention이 무엇이길래 딥러닝 모델에서의 필수 기능이라고 얘기하는 걸까요?
이번 글에서는 딥러닝 모델에서 말하는 Attention과 Self Attention에 대해 알아봅니다. 이번 글의 구성은 다음과 같습니다. 먼저 딥러닝 모델로 들어가기 전, 일상 생활속에서 사용되는 Attention 예시를 살펴봅니다. 이어서 이와 동일한 철학과 방법으로 구현되어 있는 딥러닝 모델에서의 Attention 예시를 살펴봅니다. 다음으로 Self Attention을 알아볼 차례인데요. Self Attention을 설명할 때 꼭 등장하는 개념인 Query, Key, Value의 의미에 대해 살펴봅니다. 이제 이번 글의 메인 주제인 Self Attention의 정의와 Language Model, Vision Model 에서의 예시를 살펴보겠습니다.
이번 글의 목표는 다음과 같습니다.
- 딥러닝에서의 Attention과 Self Attention의 개념을 이해한다.
- 딥러닝에서의 Attention과 Self Attention을 수식으로 이해한다.
- Attention과 Self Attention을 사용하는 대표적인 딥러닝 모델들을 이해한다.
- Self Attention을 파이썬 코드로 구현한다.
2. 일상 생활속 Attention
딥러닝에서의 Attention에 대해 알아보기 전에 우리가 일상생활에서 사용하는 Attention의 예시를 먼저 생각해보겠습니다.
Attention이란 ‘집중’ 이라는 뜻인데요. 말 그대로 무언가에 더 집중하겠다, 즉 더 높은 가중치를 부여하겠다는 의미입니다. 일상생활에서도 항목별로 다른 가중치를 적용하는 사례가 많이 있는데요. 수능 시험 볼 때를 생각해보죠. 수능 시험의 총점은 500점입니다. 국어, 영어, 수학이 각각 100점씩이죠. 과학/사회 탐구 영역은 과목당 50점씩이 만점입니다. 따라서 총점은 세 개 과목의 100점과 네 개 과목의 50점을 모두 더해 구합니다.
지금은 ‘국영수 과목의 만점은 100점이고 탐구 과목의 만점은 50점이다.’ 라고 표현했는데요. 이 말은 다시 말하면 ‘국영수 과목의 가중치는 탐구 과목 가중치의 2배이다.’ 라고 말할 수 있습니다. 만점의 기준이 두배이니까요. 그럼 다음과 같이 각 과목별 가중치를 표현할 수 있겠네요.
그럼 만약 수능 점수의 총점이 아닌, 평균 점수를 구하려면 어떻게 해야 할까요? 100점 만점인 국영수 점수와 50점 만점인 탐구 점수를 그대로 더해서 나눠주면 곤란하죠. 만점의 기준이, 즉 가중치가 다르니까요. 이런 경우에는 과목별 점수에 해당 가중치를 곱해준 뒤 총 개수로 나눠줘야 할 겁니다.
이렇게 Attention은 크게 두 가지 과정으로 구성되어 있습니다.
첫 번째는 항목별 가중치를 구하는 과정입니다. 위 예시에서는 과목별 가중치에 해당하겠네요. 이때는 과목의 난이도와 중요도에 의해 가중치를 정해주었죠.
두 번째는 과목별 가중치를 반영하여 종합 점수를 구하는 과정입니다. 위 예시에서는 과목별 가중치를 곱한 뒤 모든 점수를 더해 가중 평균을 구하는 과정에 해당합니다.
3. 딥러닝에서의 Attention
네, 이게 Attention이에요. 딥러닝 모델에서 사용하는 Attention과 Self Attention도 위의 예시와 동일한 방법을 사용합니다. Language Model과 Vision Model로 나누어 하나씩 자세히 살펴보겠습니다.
3-1. Language Model
먼저 Language Model에서 사용하는 Attention을 살펴보겠습니다.
2015년 ICLR에서 발표된 NEURAL MACHINE TRANSLATION BY JOINTLY LEARNING TO ALIGN AND TRANSLATE 모델을 살펴보겠습니다. 이 논문에서는 seq2seq 모델에 Attention을 적용했습니다. 모델의 동작 구성은 다음과 같습니다.
번역을 위한 seq2seq 모델로서 입력을 받는 Encoder와 출력을 담당하는 Decoder로 구성된 모습을 볼 수 있습니다. 다만 기존 seq2seq 모델과 한 가지 다른 특이한 점이 있는데요. 바로 Attention Score 𝛼의 존재입니다. 위 그림에서 빨간색 표시 부분에 해당합니다. Attention Score는 어떻게 구하고, 이 Score는 정보에 어떻게 반영했을까요?
3-1-1. 쉽게 생각해보기
먼저 쉽게 생각해 볼게요. seq2seq 모델을 사용하여 ABC라는 문장을 WXYZ 라는 문장으로 번역한다고 가정해보겠습니다.
기존의 seq2seq 모델을 사용한다면 다음과 같은 과정을 따를 겁니다.
먼저 Decoder에 번역할 정보인 ABC와 직전 출력값인 <SOS>가 입력되겠죠. 그럼 첫 번째 번역 단어인 W를 출력해 줄겁니다. 다시 이어서 ABC와 직전 출력값인 W를 입력으로 받아 다음 출력값인 X를 출력해주겠죠. 이러한 과정을 반복하며 순차적으로 WXYZ를 출력해 줄겁니다.
이러한 seq2seq 모델에 Attention을 적용하자는 아이디어는 이러한 의문점에서 시작 했을거에요. “한 단어를 번역할때마다 참고해야 하는 번역할 정보 ABC는 그때 그때 달라야 하지 않을까?” 예를 들어 W를 번역하기 위해서는 B 정보를 많이 참고해야 하고, X를 번역하기 위해서는 C를 많이 참고하는 식으로 말이죠. 그 말은 번역할 정보인 ABC에 Attention을 적용하자는 말 인거죠. 그럼 위의 seq2seq 번역 과정은 다음과 같이 변형될 겁니다.
기존 seq2seq 방식과 달리 번역할때 마다 번역할 정보의 가중치가 다르게 반영되는 모습을 볼 수 있습니다.
그럼 자연스럽게 이런 의문이 떠오르는데요. 번역할 정보 ABC 마다에 적용해줘야 하는 가중치 (Attention Score)는 어떻게 구한 걸까요? 수능 점수 예시에서는 과목별 난이도와 중요도에 따라 정부에서 정한 가중치를 사용했잖아요. seq2seq 모델에서는 이렇게 가중치를 미리 정해줄 수는 없으니 우리가 ‘타당한 이유’를 만들어 계산해줘야 합니다.
해당 논문에서는 다음과 같이 Attention Score를 구합니다.
번역할 정보의 각 단어별로 직전 번역 정보와의 ‘유사도’를 측정 하는 거에요. 즉 직전 번역 정보와 비슷한 정보일 수록 더 중요하게 생각하겠다는 의미인 거죠. 위 그림을 보면 A,B,C 각각이 직전 출력값인 <SOS>와의 유사도를 구하는 모습을 볼 수 있습니다. (그림의 표현과 달리 직전 출력값이 아닌 직전 Decoder Hidden State와의 유사도를 측정합니다.) 이때의 연산은 내적 (Dot Product)를 사용하고 있죠. 각 단어는 벡터로 표현됩니다. 따라서 단어 벡터 끼리의 내적값은 유사한 정도에 비례하는 크기를 갖죠. 참고로 위 그림에서는 Softmax 함수를 표현하지 않았습니다. 실제 연산에서는 Attention Score의 표준화를 위해 Softmax 함수를 적용해주어야 합니다.
그럼 이제 이렇게 구한 Attention Score는 어떻게 최종 정보에 반영해 줄까요?
수능 점수 예시와 마찬가지로 각 단어 벡터에 해당하는 Attention Score를 곱해주는 방식을 사용합니다. 수능 과목 점수별 가중치를 곱해 모두 더해주는 과정과 동일하죠?
3-1-2. 수식으로 확인하기
위의 내용이 seq2seq 모델에 Attention을 적용하는 방법의 골자입니다. 핵심 원리는 다 이해했으니, 수식으로 한번만 확인하고 넘어가겠습니다.
먼저 Decoder에서 번역하는 각 단어들은 다음과 같이 구합니다.
세 가지 정보를 고려하여 번역하는 모습인데요.
첫 번째는 직전 번역한 정보입니다. 위 수식에서는 주황색 y에 해당합니다.
두 번째는 직전 Decoder의 Hidden State입니다. 이번 글에서는 Attention을 이해 하는게 주 목표이니, 이 부분은 이전 Decoder에서 넘어온 정보 라고만 이해하고 넘어가겠습니다. 위 수식에서는 빨간색 s에 해당합니다.
세 번째는 Context 입니다. 이는 Encoder에서 압축한 번역할 정보, 즉 위 예시에서 ABC에 해당하는 부분입니다. 그런데 Context라고 표현하는 이유는 번역할 단어의 문맥에 맞게 Attention을 반영해주었기 때문이죠. 위 수식에서는 파란색 c에 해당합니다.
결국 이때의 핵심은 Context c를 구하는 과정인데요. 이는 수식으로 다음과 같습니다.
Encoder의 Hidden State들, 즉 번역할 단어 벡터들 마다에 가중치 𝛼를 적용해주는 모습을 볼 수 있죠. 이때의 가중치 𝛼는 다음과 같이 구합니다.
e들의 Softmax를 통해 구하는데요. 이때의 e는 번역할 정보와 Decoder의 직전 Hidden State와의 ‘유사도’를 기준으로 측정하는 모습입니다.
3-2. Vision Model
지금까지 Language Model에서 구현된 Attention에 대해 살펴봤습니다.
이번에는 Vision Model에 적용된 Attention에 대해 살펴보겠습니다.
3-2-1. Squeeze and Excitation Network
먼저 Squeeze and Excitation Network (SENet) 를 살펴보겠습니다. SENet은 2018년 CVPR에 발표된 논문인데요. Vision Model에 Attention을 적용한 대표적인 방법입니다.
SENet의 핵심 아이디어는 이렇습니다. CNN에서 추출한 Feature Map은 채널별로 특정한 정보를 포함하고 있다고 하죠. 그럼 채널별 중요도가 다를테니, 채널별로 가중치를 다르게 반영해주자는 것이 SENet의 핵심 아이디어입니다. 이를 그림으로 표현하면 이렇습니다.
채널 별 중요도를 구해 곱해주는 모습을 볼 수 있습니다. 그림에서는 채널 별 중요도가 표준화되지 않은 모습이지만 실제 적용할 때는 Softmax를 통해 정규화해준 뒤 적용합니다.
채널 별 중요도를 구하는 과정은 단순합니다. 먼저 채널 별 중요도를 계산하기 위해 채널 별 정보를 하나의 값으로 압축해야 하는데요. SENet에서는 채널 별 평균을 사용합니다.
그럼 채널 별 하나의 값으로 표현이 되는데요. 이 값들에 Multi Layer Perceptron을 연결해줍니다.
이렇게 나오는 값이 채널 별 중요도 값이 되는 것이죠. 이렇게 나온 채널 별 가중치는 다시 전체 Feature Map에 반영해줍니다. 이 과정을 전체적으로 표현하면 다음과 같습니다.
지금까지 살펴본 바와 마찬가지로 가중치를 계산하는 과정과 이렇게 구한 가중치를 반영해주는 과정으로 구성된 모습을 볼 수 있습니다. 자세한 내용은 SENet 리뷰글을 참고해주세요.
3-2-2. BAM
다음으로 살펴볼 논문은 BAM입니다. BAM은 2018년 BMVC Oral로 발표된 논문으로 제목은 BAM: Bottleneck Attention Module 입니다. BAM은 SENet의 아이디어를 좀 더 구체화한 방법입니다. SENet에서는 채널 별 가중치만 계산해주었는데요, BAM에서는 채널 별 가중치 뿐만 아니라 위치 별 가중치도 적용합니다. 아래 그림 처럼요.
Feature Map에 대해 Channel Attention과 Spatial Attention을 병렬로 적용해주는 모습을 볼 수 있습니다. Channel Attention은 SENet과 동일한 방법으로 계산해줍니다.
Spatial Attention은 Dilated Convolution 연산을 사용하여 구해주죠.
이렇게 Channel Attention과 Spatial Attention이 병렬로 적용되는 전체 과정을 그림으로 표현하면 이렇습니다.
채널 별 가중치와 위치 별 가중치를 동시에 고려하여 더욱 다채로운 정보를 표현하는 모습을 볼 수 있습니다. 자세한 내용은 BAM 리뷰글을 참고해주세요.
4. Query, Key, Value
지금까지 Attention을 적용한 딥러닝 모델들을 살펴봤습니다. 이제 Self Attention에 대해 살펴볼 차례인데요. Self Attention을 설명할때 항상 나오는 용어가 있습니다. 바로 Query, Key, Value 인데요. 이에 대해 먼저 정리하고 Self Attention으로 넘어가도록 하겠습니다.
Query, Key, Value는 모두 Attention을 적용하기 위해 사용되는 정보를 의미합니다. 수능 점수 예시에서는 각 과목별 점수가 이에 해당하고요. Language Model의 예시에서는 각 단어 Embedding 벡터가 이에 해당합니다. Vision Model에서는 Feature Map 또는 입력 이미지가 이에 해당하죠.
그럼 Query, Key, Value는 각각 어떤 차이가 있을까요?
Language Model의 예시로 다시 넘어가보죠. Language Model 예시에서 Attention Score는 어떻게 구했었나요? 번역할 정보와 직전 출력값(또는 Decoder Hidden State)와의 유사도를 기준으로 점수를 측정 했었죠. 그리고 이렇게 구한 Attention Score를 번역할 정보에 곱해 반영해주었습니다. 이를 그림으로 표현하면 다음과 같죠.
이때 번역할 정보는 Query에 해당합니다. Query란 ‘문의’라는 사전적 의미를 갖고 있는데요. Attention Score를 계산하기 위해 ‘문의’ 해야 하는 정보라고 생각하면 됩니다.
직전 출력값 (또는 Decoder Hidden State)는 Key에 해당합니다. Key는 ‘핵심’ 이라는 뜻이잖아요. Attention Score를 계산하기 위한 ‘핵심’ 정보라고 생각하면 됩니다.
이렇게 구해진 Attention Score를 반영해주는 정보, 즉 위의 예시에서는 번역할 정보는 Value에 해당합니다. Value는 ‘가치’라는 의미 잖아요. 계산된 Attention Score가 적용될 ‘가치’ 있는 정보라고 생각하면 됩니다.
위의 예시에서 알 수 있듯이 Query, Key, Value에 해당하는 정보는 고정되어 있지 않습니다. 설계해주기 나름이죠. 설계자의 의도에 맞게 정보를 선택하게 됩니다. 일반적인 딥러닝 모델의 Attention에서는 Value와 동일한 Query에 Key와의 Attention Score를 계산해줍니다. 이렇게 계산된 Attention Score는 최종적으로 Value에 반영됩니다.
5. Self Attention
이제 드디어 Self Attention에 대해 알아보겠습니다.
5-1. 정의
Self Attention을 말 그대로 해석해보면 ‘스스로 수행하는 Attention’ 이라는 의미 일텐데요. Self Attention은 정말 그렇습니다. 위에서 살펴본 일반적인 Attention에서는 서로 다른 정보인 Query와 Key로부터 Attention Score를 계산해주었죠. 반면 Self Attention은 Query와 Key 정보가 동일합니다. 뿐만 아니라 Value 정보까지 동일하죠. 이 Query, Key, Value는 전부 ‘스스로의 정보’를 사용합니다. (정확히 말해서 완벽하게 동일한 정보는 아니고 동일한 정보로부터 Linear Projection된 정보를 Query, Key, Value로 사용합니다.) 이 과정을 그림으로 표현하면 다음과 같습니다.
동일한 정보가 Query, Key,Value로 사용되는 모습을 볼 수 있습니다. Attention과 비교해보면 이렇습니다.
Attention Score가 Map 형태로 더 다양하게 표현되는 모습을 볼 수 있습니다.
Language Model에서 Attention Score를 적용하는 원리에 대해서는 납득이 됐었죠. 직전 번역 정보와 관련된 정보에 더 큰 가중치를 주겠다는 의도였잖아요. 그럼 Self Attention에서의 Attention Score는 어떻게 이해해야 할까요? 위 그림에서 Self Attention Score의 계산 과정을 다시 한번 보죠. Matrix Multiplication 연산을 통해 ABC 정보를 모두 참고하여 Attention Score를 계산하는 모습입니다. 즉 ABC라는 정보 전체의 ‘문맥’을 고려하여 가중치를 계산한다는 점을 알 수 있습니다.
5-2. Language Model
Self Attention이 딥러닝에서 유명해진 계기는 단연 Transformer를 꼽을 수 있습니다. Transformer는 2017년 NIPS에서 발표된 Attention is all you need 이라는 논문입니다. 기존 seq2seq 방식과 달리 입출력을 순차적으로 받지 않고 하나의 덩어리로 표현해주었죠. 이렇게 들어온 입출력 정보에 Self Attention을 적용한 방법이 바로 Transformer입니다.
위 그림을 보면 Encoder로부터 나온 ABC 정보에 Self Attention이 적용되어 정보별로 가중치가 반영된 모습을 볼 수 있습니다. Decoder에서도 마찬가지죠. Self Attention이 적용되어 정보별로 세세하게 가중치가 반영된 모습을 볼 수 있습니다. Transformer의 구조를 조금 더 구체적으로 살펴보면 이렇습니다.
입력 정보가 Encoder와 Decoder를 거쳐 Output으로 나가는 모습입니다. Encoder와 Decoder에는 각각의 Self Attention과 Attention 모듈이 포함되어 있죠. Transformer에는 다양한 아이디어들이 구현되었지만 그중 핵심은 단연 Self Attention Module이라고 할 수 있습니다.
5-3. Vision Model
Transformer가 등장한 뒤로 Language Model의 성능은 비약적으로 향상되었습니다. Language Model은 Transformer 전과 후로 나뉜다고 말할 수 있을 정도죠. 이렇게 Self Attention의 우수성이 입증되자 Vision Model에서도 Self Attention을 적용한 모델들이 등장하기 시작했습니다.
5-3-1. Stand Alone Self Attention in Vision Model
Self Attention을 Vision Model에 최초로 적용한 유의미한 방법은 SASA라는 모델입니다. SASA는 2019년 NIPS에서 발표된 Stand Alone Self Attention in vision models 라는 논문입니다. SASA는 기존 CNN 모델의 중간에 Self Attention 모듈을 삽입하는 방법을 사용했습니다. SASA에서 Self Attention을 적용한 방식은 이렇습니다.
위 그림은 SASA에서 Self Attention을 사용하여 Feature Map을 추출하는 연산 과정을 나타낸 그림입니다. Convolution 연산과 비교해 보면 의미를 이해할 수 있는데요. 입력 정보인 X로부터 최종 출력 정보(초록색)가 나오는 과정을 표현하고 있습니다. Convolution 연산에서는 입력 정보 X에 Convolution Filter와의 Convolution 연산을 통해 최종 정보를 출력하죠. 반면 SASA의 연산 방식은 다릅니다. Query, Key, Value를 만들어 Output을 만들어 내는 모습을 볼 수 있습니다. 이때의 Query, Key, Value는 입력 정보인 X로부터 Linear Projection을 통해 만들어내고 있습니다.
5-3-2. Vision Transformer
SASA는 Vision Model에도 Self Attention을 적용하여 CNN에 필적하는 성능을 낼 수 있음을 보였습니다. 하지만 Self Attention만으로 구성된 Vision Model이라고는 할 수 없었죠. 기존 CNN에 Self Attention Module을 추가한 방식이었으니까요.
Transformer와 마찬가지로 Self Attention만으로 Vision Model을 구성한 가장 유의미한 방법은 Vision Transformer라고 할 수 있습니다. Vision Transformer는 2021년 ICLR에 발표된 AN IMAGE IS WORTH 16X16 WORDS: TRANSFORMERS FOR IMAGE RECOGNITION AT SCALE 라는 논문입니다. 제목부터 재미있는 모습인데요. Image는 16×16개의 단어와 같다고 말하고 있죠. 이미지나 언어나 모두 여러개의 단어로 구성된 정보이니 Transformer로 처리할 수 있다는 말을 하고 있네요. Vision Transformer의 구조는 다음과 같습니다.
입력 이미지를 여러개의 Patch로 나눠 Token화 해주는 모습을 볼 수 있습니다. 그 결과 모델 입장에서는 이미지 Patch가 단어 Embedding과 동일하게 보이게 되겠죠. 이렇게 만들어준 이미지 Patch 정보를 Transformer를 사용하여 처리해주는 모습을 볼 수 있습니다. Vision Transformer는 이러한 구조를 사용하여 기존 CNN을 능가하는 성능을 보였습니다. 이후 Vision Model은 아주 빠른 속도로 Transformer 기반으로 바뀌어 가고 있습니다.
6. 파이썬 구현
이번 챕터에서는 가장 일반적인 방식의 Self Attention을 파이썬 코드로 구현해보겠습니다. 수식으로 보는것과 코드로 직접 구성해보는건 전혀 다른 경험인데요. 직접 코드를 구성해보며 개념을 더욱 정확하게 이해할 수 있습니다. Self Attention을 파이썬으로 구현하면 아래와 같습니다.
import torch
import torch.nn as nn
import torch.nn.functional as F
class SimpleSelfAttention(nn.Module):
def __init__(self, embed_size):
super(SimpleSelfAttention, self).__init__()
self.embed_size = embed_size
self.values = nn.Linear(self.embed_size, self.embed_size, bias=False)
self.keys = nn.Linear(self.embed_size, self.embed_size, bias=False)
self.queries = nn.Linear(self.embed_size, self.embed_size, bias=False)
self.fc_out = nn.Linear(self.embed_size, self.embed_size)
def forward(self, values, keys, query):
values = self.values(values)
keys = self.keys(keys)
queries = self.queries(query)
# Self attention
energy = torch.matmul(queries, keys.transpose(0, 1))
attention = F.softmax(energy, dim=1)
out = torch.matmul(attention, values)
out = self.fc_out(out)
return out
forwar 함수에서는 먼저 Query, Key, Value를 각각 Projection을 통해 원하는 차원으로 변환해주고 있습니다. 그리고 나서 본적적인 Self Attention을 계산해주고 있는데요. Query와 Key의 Matrix Multiplication 결과는 Energy라고 표현하고 있고, 이 Energy의 Softmax 결과를 Attention 이라고 표현했습니다. 최종적으로 이 Attention 값은 Value에 곱해져서 Self Attention 의 결과물로 나오게 됩니다.
7. 마치며
이번 글에서는 딥러닝 모델에서의 Self Attention에 대해 살펴봤습니다.
쉽게 이해하기 위해 먼저 일상 생활에서의 Attention에 대해 알아봤습니다. 이 과정에서 Attention을 적용하기 위해서는 Attention Score를 계산하는 과정과 이를 정보에 반영하는 과정이 필요함을 보았죠. 그리고 나서 Attention이 적용된 딥러닝 모델들을 살펴봤습니다. Language Model과 Vision Model로 나누어 살펴봤지만 정보의 형태만 다를 뿐 핵심 아이디어는 동일했죠.
마지막으로 Self Attention에 대해 살펴봤습니다. Self Attention은 Query, Key, Value에 동일한 정보를 사용했습니다. 이를 적용한 Transformer와 SASA, Vision Transformer 모델을 간략하게 살펴봤습니다.
좋은 정리글 감사합니다!….
넵 좋은 하루 되세요!
이해가 너무 잘돼요 대박스..
ㅎㅎㅎ 감사합니다! 좋은 하루 되세요!!
좋은 글 항상 감사드립니다♡
좋은 하루 되세요!
정리 정말 잘하셨네요 이해에 많은 도움이 되었습니다 감사합니다
감사합니다! 좋은 하루 되세요!