본문 바로가기
AI/Transformer

Transformer_1(기초부터 심화까지)

by 전주혁 2023. 6. 28.

요즘 정말 인기많은 Transformer에 대해 여러분들은 잘 아시나요?

혹시라도 모르신다면 괜찮습니다.

 

이번에 스스로 Transformer에 대해 공부하고 있어

글을 작성하게 되었습니다.

 

이 글을 처음부터 끝까지 다 읽으신다면

여러분들도 Transformer 고수?!

 

 

 

 

먼저 요즘 Transformer에 대해 알아보아요!

 

 

Transformer란?

 

 

 

 

트랜스포머(Transformer)는 

자연어 처리(NLP)와 기계 번역 등 다양한 분야에서 높은 성능을 보이는 딥러닝 모델입니다. 

트랜스포머는 2017년에 Vaswani et al.의 논문 "Attention is All You Need"에서 처음 소개되었습니다.

 

트랜스포머의 핵심 개념은 셀프 어텐션(self-attention) 메커니즘입니다. 

셀프 어텐션은 입력 시퀀스의 각 단어에 대해 다른 단어들과의 관계를 계산하며, 

이를 통해 문장 내 단어 간의 의존성을 파악하고 문맥을 이해합니다. 

트랜스포머는 이러한 셀프 어텐션을 여러 층에 걸쳐 적용하며, 

이를 통해 문장에 대한 복잡한 패턴을 추출할 수 있습니다.

기존의 순환 신경망(RNN)과 달리 트랜스포머는 병렬 처리가 가능하며, 

긴 시퀀스를 처리할 때 발생하는 기울기 소실 문제를 해결하였습니다. 

이러한 이유로 트랜스포머는 RNN 및 LSTM을 대체하여 다양한 자연어 처리 작업에서 선호되는 모델이 되었습니다.

트랜스포머의 출현 이후, 이를 기반으로 한 다양한 모델이 개발되었습니다. 

대표적인 예로는 BERT, GPT, T5 등이 있습니다. 

이러한 모델들은 트랜스포머의 아키텍처를 활용하여 다양한 자연어 처리 작업에서 최첨단 성능을 달성하였습니다.

요약하면, 

트랜스포머는 셀프 어텐션 메커니즘을 기반으로 한 딥러닝 모델로, 2017년에 처음 소개되었습니다. 

이후 다양한 자연어 처리 작업에서 높은 성능을 보이며, RNN 및 LSTM을 대체하는 주요 모델이 되었습니다. 

트랜스포머를 기반으로 한 다양한 모델들이 개발되어 최첨단 성능을 달성하였습니다.

 

 

 

 

 

 

 

 

Transformer에 입문하신 분들은

Self-Attention(셀프 어텐션) 단어에 생소하실텐데요

Self-Attention(셀프 어텐션)에 대해 더 알아볼까요?

 

 

 

 

 

 

셀프 어텐션(self-attention) 

메커니즘은 트랜스포머의 핵심 개념으로, 

입력 시퀀스 내의 단어들 간의 관계와 문맥을 파악하는 데 사용됩니다. 

셀프 어텐션은 입력 시퀀스의 각 단어에 대해 다른 단어들과의 상대적인 중요도를 계산하고, 

이를 바탕으로 새로운 표현을 생성합니다.

 

 

 


셀프 어텐션을 계산하는 과정은 다음과 같습니다:

1. 입력 시퀀스의 각 단어를 쿼리(Query), 키(Key), 밸류(Value) 벡터로 변환합니다. 

이 벡터들은 입력 벡터에 가중치 행렬을 곱하여 얻을 수 있습니다.


2. 쿼리 벡터와 키 벡터를 점곱(dot product)하여 어텐션 점수를 구합니다. 

이 점수는 두 단어 간의 상호 작용을 나타냅니다.


3. 어텐션 점수를 스케일링하고 소프트맥스(softmax) 함수를 적용하여 정규화합니다. 

이를 어텐션 가중치라고 합니다.


4. 어텐션 가중치와 밸류 벡터를 곱하고, 

이들을 합산하여 새로운 표현(어텐션 출력)을 생성합니다.


이러한 셀프 어텐션 메커니즘은 멀티 헤드 어텐션(multi-head attention) 형태로 확장될 수 있습니다.

 멀티 헤드 어텐션은 셀프 어텐션을 여러 번 독립적으로 계산하고, 

이를 결합하여 더 풍부한 표현을 얻는 방식입니다.

 

 

 

 

셀프 어텐션의 장점은 음과 같습니다:

 

1. 문장 내 단어 간의 장거리 의존성을 잘 포착할 수 있습니다.

2. 병렬 처리가 가능하여 학습 및 추론 속도가 빠릅니다.

3. 여러 층에 걸쳐 적용함으로써 다양한 문맥 정보를 포착할 수 있습니다.


이러한 이유로 셀프 어텐션은 트랜스포머의 핵심 구성 요소로 작용하며, 

다양한 자연어 처리 작업에서 높은 성능을 보입니다.

 

 

 

 

 

 

 

또 여기서 궁금증이 들만한 요소인

쿼리(Query), 키(Key), 밸류(Value)

에 대해서 알아볼까요?

 

 

 


입력 시퀀스란 모델에 주어지는 연속적인 단어들의 나열입니다. 

예를 들어, "나는 오늘 학교에 간다"라는 문장이 주어진다면, 

이 문장은 "나는", "오늘", "학교에", "간다"라는 단어들로 이루어진 시퀀스로 간주됩니다. 

자연어 처리 모델은 이러한 입력 시퀀스를 벡터 형태로 변환하여 처리합니다.

쿼리(Query), 키(Key), 밸류(Value) 벡터로 변환하는 과정은 다음과 같습니다:

 


1. 먼저, 각 단어를 고정된 크기의 벡터로 변환합니다. 

이를 임베딩(embedding)이라고 하며, 단어와 관련된 의미 정보를 포함합니다. 

예를 들어, "나는" 이라는 단어의 임베딩 벡터는 [0.1, -0.2, 0.3, ...]와 같은 형태로 표현될 수 있습니다.


2. 그 다음, 각 단어의 임베딩 벡터에 세 개의 가중치 행렬(W_query, W_key, W_value)을 곱하여 

쿼리, 키, 밸류 벡터를 생성합니다. 이 가중치 행렬은 학습 과정에서 최적화되며, 

셀프 어텐션 메커니즘에 필요한 정보를 추출하는 역할을 합니다.

예시를 통해 이해해봅시다. "나는 오늘 학교에 간다"라는 문장이 주어졌다고 가정하겠습니다. 

이 문장을 처리하기 위해 쿼리, 키, 밸류 벡터로 변환해야 합니다.

1. 먼저, 각 단어를 임베딩 벡터로 변환합니다.

나는: [0.1, -0.2, 0.3, ...]
오늘: [0.5, 0.3, -0.1, ...]
학교에: [-0.2, 0.4, 0.6, ...]
간다: [0.3, -0.1, 0.2, ...]

2. 그 다음, 각 임베딩 벡터에 W_query, W_key, W_value 가중치 행렬을 곱하여

쿼리, 키, 밸류 벡터를 생성합니다.

나는_query: [0.2, -0.4, 0.1, ...]
나는_key: [-0.1, 0.3, 0.5, ...]
나는_value: [0.4, 0.1, -0.2, ...]

오늘_query: [0.6, 0.1, -0.3, ...]

오늘_key: [0.4, -0.2, 0.1, ...]
오늘_value: [-0.1, 0.3, 0.5, ...]

학교에_query: [-0.3, 0.5, 0.4, ...]
학교에_key: [0.1, -0.3, 0.2, ...]
학교에_value: [0.2, 0.4, -0.1, ...]

간다_query: [0.5, -0.2, 0.3, ...]
간다_key: [-0.4, 0.6, 0.1, ...]
간다_value: [0.3, -0.5, 0.2, ...]

 


쿼리, 키, 밸류 벡터로 변환하는 이유는 

셀프 어텐션 메커니즘을 통해 문장의 문맥을 이해하고 상호 작용을 파악하기 위함입니다. 

쿼리 벡터는 다른 단어와의 관계를 살펴보는 기준이 되는 단어를 나타내며, 

키 벡터는 쿼리 단어와 비교 대상이 되는 단어를 나타냅니다. 

밸류 벡터는 각 단어의 실질적인 정보를 포함하며, 어텐션 가중치와 곱해져 새로운 문맥 정보를 포함한 벡터를 생성합니다.

 


이렇게 생성된 쿼리, 키, 밸류 벡터를 사용하여 셀프 어텐션 메커니즘을 수행하게 되며, 

결과적으로 문장 내 단어들 간의 상호 작용과 문맥 정보를 포착한 새로운 벡터 표현을 얻게 됩니다. 

이를 통해 트랜스포머는 자연어 처리 작업에 필요한 다양한 패턴과 정보를 추출할 수 있습니다.

 

 

 

 

 

 

 

근데 쿼리, 키, 밸류에 들어가는 저 값들은 도대체

어디서 나오는지 궁금하시지 않나요??

 

 

 

쿼리(Query), 키(Key), 밸류(Value) 벡터에 값들을 부여하는 과정은 

입력 시퀀스의 단어 임베딩 벡터와 학습 가능한 가중치 행렬을 곱하는 것을 통해 이루어집니다. 

이 가중치 행렬은 학습 과정에서 업데이트되며, 

각 단어와 관련된 쿼리, 키, 밸류 정보를 추출하는 데 도움이 됩니다.

 

 


쿼리, 키, 밸류 벡터를 생성하는 과정은 다음과 같습니다:

 

 


1. 먼저 각 단어를 고정된 크기의 벡터로 변환합니다. 

이를 임베딩 벡터라고 하며, 단어와 관련된 의미 정보를 포함합니다.


2. 각 단어의 임베딩 벡터에 세 개의 가중치 행렬(W_query, W_key, W_value)을 곱하여 

쿼리, 키, 밸류 벡터를 생성합니다. 

 

이 가중치 행렬은 학습 과정에서 최적화되며, 

셀프 어텐션 메커니즘에 필요한 정보를 추출하는 역할을 합니다.
가중치 행렬은 무작위로 초기화되어 시작하며, 

모델이 학습되면서 데이터로부터 적절한 쿼리, 키, 밸류 정보를 추출할 수 있는 값으로 업데이트됩니다. 

최적화 알고리즘(예: 확률적 경사 하강법, Adam 등)을 사용하여 

손실 함수를 최소화하는 방향으로 가중치 행렬이 업데이트됩니다.

이 과정을 통해 각 단어의 임베딩 벡터는 쿼리, 키, 밸류 벡터로 변환되어 

셀프 어텐션 메커니즘을 수행할 수 있는 입력으로 사용됩니다. 

 

 

 

이렇게 생성된 쿼리, 키, 밸류 벡터들은 

단어 간의 상호 작용과 문맥 정보를 포착하기 위해 셀프 어텐션 메커니즘에 사용되며, 

최종적으로 문장의 의미를 이해하는 데 도움이 되는 출력 벡터를 얻게 됩니다.

 

 

 

 

쿼리, 키, 밸류를 이제 좀 이해하려니

임베딩이라는 또 생소한 단어가 튀어나오네요?

알아봅시다.

 

 

 

임베딩(Embedding)

이란, 자연어 처리에서 주로 사용되는 기법으로, 

범주형 변수(예: 단어, 문자)를 고정된 크기의 연속 벡터로 변환하는 것을 말합니다. 

임베딩을 사용하면 단어와 같은 범주형 데이터를 모델이 처리하기 쉽게 만들 수 있으며, 

단어 간의 의미적 관계를 나타낼 수 있습니다. 

임베딩 벡터는 단어나 문자의 의미, 문맥, 구문 정보 등을 포함하게 되며, 

이를 통해 모델은 문장이나 문서의 구조를 파악하는 데 도움을 받을 수 있습니다.

 

 


임베딩 레이어에서는 다음과 같은 일이 일어납니다.

1. 범주형 변수(예: 단어, 문자)에 고유한 정수 ID를 할당합니다.

이를 인덱싱(Indexing)이라고 합니다.


2. 각 정수 ID를 해당하는 고정된 크기의 벡터로 변환합니다.

이 과정에서 사용되는 행렬은 임베딩 행렬(Embedding Matrix)이며,

이 행렬의 각 행은 정수 ID에 대응하는 벡터를 나타냅니다.


3. 초기에는 임베딩 행렬이 무작위 값으로 채워져 있지만,

모델이 학습되면서 이 행렬은 데이터로부터 의미 정보를 포착하는 벡터로 업데이트됩니다.

 

 


임베딩 레이어를 사용하면 다음과 같은 효과를 얻을 수 있습니다!

1. 차원 축소: 범주형 변수는 원-핫 인코딩을 사용할 경우, 고차원의 희소 벡터로 표현됩니다.

이는 계산 비용이 높고, 단어 간의 의미적 관계를 나타내지 못하는 단점이 있습니다.

임베딩 레이어를 사용하면 이러한 단점을 극복할 수 있습니다.

고정된 크기의 밀집 벡터로 범주형 데이터를 변환하면,

계산 효율성이 높아지고 모델의 학습 속도가 개선됩니다.

2. 의미 정보 포착: 임베딩 벡터는 단어나 문자의 의미, 문맥, 구문 정보를 포함하게 됩니다.

이를 통해 모델은 문장이나 문서의 구조를 파악하는 데 도움을 받을 수 있습니다.

또한, 이러한 정보를 활용하여 단어 간의 유사도를 측정할 수 있어,

자연어 처리 작업에서 더욱 높은 성능을 달성할 수 있습니다.

3. 일반화 능력 향상: 임베딩을 사용하면 훈련 데이터에서 보지 못한 단어나 구조에 대해서도 더욱 잘 대응할 수 있습니다.

이는 임베딩이 비슷한 단어나 구문을 비슷한 벡터 공간에 배치하기 때문입니다.

따라서 모델은 이러한 패턴을 이용하여 새로운 문장이나 문서에 대한 예측을 보다 정확하게 수행할 수 있습니다.

 

 


요약하자면, 

임베딩 레이어는 범주형 데이터를 고정된 크기의 연속 벡터로 변환하여 차원 축소, 의미 정보 포착, 일반화 능력 향상 등의 효과를 얻을 수 있습니다. 

이를 통해 자연어 처리 작업에 높은 성능을 발휘할 수 있도록 도움을 줍니다.

 

 

 

 

 

 

 

 

정리를 해 봅시다.

 

Transformer의 핵심 원리는 Self-Attention 메커니즘이며,

이 메커니즘은 입력 시퀀스의 각 단어에 대해 다른 단어들과 관계를 계산해서 단어간의 의존성을 파악 + 문맥을 이해합니다.

또한 Transformer는 RNN과 달리 병렬처리가 가능하며

긴 시퀀스 기울기 소실 문제를 해결했습니다.

 

 

 

Self-Attention
입력 시퀀스의 각 단어에 대해 다른 단어들과의 상대적 중요도를 계산
입력 시퀀스의 각 단어를 쿼리, 키, 밸류 벡터로 변환
쿼리 벡터와 키 벡터를 점곱하여 어텐션 점수 구하기(이때 어텐션 점수는 단어간의 상호작용을 의미)
어텐션 점수를 스케일링 후 Soft-max 적용 후 정규화(어텐션 가중치)
어텐션 가중치와 밸류 벡터를 곱하고 합산하여 새 어텐션 생성

 

 

쿼리 : 다른 단어와의 관계를 살펴보는 기준이 되는 단어

: 쿼리 단어와 비교 대상이 되는 단어

밸류 : 각 단어의 실질적인 정보를 포함하며, 어텐션 가중치와 곱해져서 새로운 문맥정보를 포함한 출력 벡터 생성

 

 

 

 

오늘은 Transformer의 역사와

Self-Attention,

쿼리-키-밸류, 임베딩까지

알아보았어요!

 

 

 

혹시 모르는 부분이 있으면 댓글 주시면 함께 알아봐요!