수식 없이 이해하는 트랜스포머 아키텍처
트랜스포머는 보통 방정식의 벽으로 그려집니다. 그것을 걷어내면 하나의 우아한 아이디어가 남습니다. 모든 단어가 어떤 다른 단어가 중요한지 스스로 정하게 하는 것입니다.
트랜스포머는 거의 모든 현대 언어 모델의 밑바탕에 깔린 아키텍처인데, 보통 행렬과 소프트맥스, 그리스 문자가 빽빽하게 들어찬 도식으로 소개됩니다. 그런 설명 방식은 핵심 아이디어가 얼마나 단순한지를 가려 버립니다. 단 하나의 방정식도 적지 않고서, 트랜스포머가 무엇을 하는지, 그리고 왜 그렇게 잘 작동하는지를 이해할 수 있습니다. 수식은 그것이 어떻게 구현되는가의 문제일 뿐입니다. 정작 중요한 것은 아이디어입니다.
핵심 아이디어를 한 문장으로 말하면 이렇습니다. 트랜스포머는 시퀀스 전체를 한 번에 처리하며, 그 시퀀스의 모든 위치가 다른 모든 위치를 들여다보면서 자신이 무엇을 의미하는지 결정하게 합니다. 나머지는 전부 이 아이디어를 떠받치는 세부 사항입니다.
트랜스포머가 풀려고 만들어진 문제
트랜스포머 이전에 텍스트를 다루는 지배적인 방식은 단어를 왼쪽에서 오른쪽으로 한 번에 하나씩 읽으며, 지금까지의 요약을 앞으로 끌고 가는 것이었습니다. 이 방식은 작동하긴 했지만 두 가지 끈질긴 약점이 있었습니다.
첫 번째는 거리였습니다. 어떤 단어의 의미가 스무 단어 앞의 무언가에 달려 있다면, 그 정보는 진행되는 요약을 따라 여정 전체를 살아남아야 했고, 매 단계마다 희석되었습니다. 멀리 떨어진 연결은 취약했습니다.
두 번째는 속도였습니다. 순서대로만 읽는다는 것은 아홉 번째 단어를 끝내기 전에는 열 번째 단어를 시작할 수 없다는 뜻입니다. 연산이 사슬처럼 이어지고, 사슬은 병렬화할 수 없습니다. 하드웨어가 자기 자신의 이전 단계를 기다리며 멈춰 있었기에 학습이 느렸습니다.
트랜스포머는 이 사슬을 통째로 버렸습니다. 순서대로 읽는 대신, 문장 전체를 한꺼번에 테이블 위에 올려놓고 모든 단어가 다른 모든 단어를 직접 참조하게 합니다. 거리는 더 이상 문제가 되지 않고, 작업은 여러 프로세서에 동시에 분산될 수 있습니다.
이 모든 것을 작동하게 하는 단 하나의 동작
핵심 연산은 **어텐션(attention)**이며, 그 직관은 일상적입니다. 문장에서 "그것"이라는 단어를 읽을 때, 우리 머릿속은 관련된 앞 단어들을 슬쩍 돌아보고 무관한 단어들은 무시하면서, "그것"이 무엇을 가리키는지 즉각 알아냅니다. 어텐션은 바로 그 흘끗 보는 행위를 기계적으로 옮긴 것입니다.
각 단어에 대해 트랜스포머는 이렇게 묻습니다. 여기 있는 다른 모든 단어 중에서, 나 자신을 이해하기 위해 어디에 주의를 기울여야 할까? 그런 다음 그 단어들로부터 정보를 끌어와, 각각이 얼마나 관련 있는지에 따라 가중치를 두고 섞습니다. 문장 속 한 단어는 홀로 이해되지 않습니다. 그 단어 자신과, 그 단어가 주목하기로 택한 단어들의 혼합으로서 이해됩니다.
결정적으로, 모든 단어가 이 작업을 동시에 수행하며, 각 단어는 무엇을 들여다볼지 스스로 결정합니다. "bank"라는 단어는 한 문장에서는 "river"에 주목하고 다른 문장에서는 "money"에 주목하여, 각각 다른 의미로 귀결될 수 있습니다. 단 한 번의 훑기로 계산되는 이 문맥 민감성이야말로 아키텍처 전체를 움직이는 엔진입니다.
아이디어를 층으로 쌓기
한 차례의 어텐션은 각 단어가 이웃들로부터 문맥을 모으게 해 줍니다. 하지만 한 차례는 얕습니다. 트랜스포머는 이 동작을 레이어(layer) 단위로 반복하며, 하나 위에 또 하나를 쌓아 올립니다.
첫 번째 레이어를 거치면 모든 단어의 표현은 자신이 주목한 단어들로 인해 풍부해집니다. 그러면 두 번째 레이어가 다시 어텐션을 수행합니다. 다만 이번에는 이렇게 풍부해진 표현들 위에서 수행되므로, 단어들은 이미 문맥을 담고 있는 문맥에 주목할 수 있습니다. 의미는 단계적으로 쌓여 갑니다. 초기 레이어는 국소적이고 표면적인 관계를 포착하는 경향이 있고, 후기 레이어는 그것들을 조합해 더 추상적인 구조를 만들어 냅니다. 이런 레이어를 여러 겹 쌓는 것이 대규모 모델에 깊이 있는 이해를 부여합니다.
어텐션 단계 사이에서, 각 위치는 자기 자신을 변환하는 작은 처리 블록도 통과합니다. 어텐션을 단어들이 서로 대화하는 단계로, 이 블록을 각 단어가 방금 들은 것에 대해 혼자 생각하는 단계로 떠올려 보세요. 이 둘이 레이어를 거듭하며 번갈아 작동합니다.
그래도 순서는 중요하고, 어떻게 지켜지는가
모든 단어를 한 번에 들여다보는 데에는 함정이 있습니다. 모든 단어를 테이블 위에 동시에 던져 놓으면 그 순서를 놓치게 됩니다. "개가 사람을 문다"와 "사람이 개를 문다"는 같은 단어들로 이루어져 있고, 순수한 어텐션 메커니즘은 둘을 동일하게 볼 것입니다.
트랜스포머는 어텐션이 작동하기 전에 각 단어에 시퀀스 내 위치 정보를 태그로 붙여 이 문제를 해결합니다. 모든 단어는 자신의 의미와 더불어 자신이 어디에 자리하는지를 알리는 표식을 함께 지니고 도착합니다. 그러면 어텐션은 무엇에 주목할지 결정할 때 순서를 고려할 수 있습니다. 모델은 모든 곳을 한 번에 들여다보는 자유를 누리면서도, 순서가 의미를 담고 있다는 사실을 잃지 않습니다.
여러 방식으로 동시에 들여다보기
단 한 번의 어텐션은 모든 단어가 무엇이 관련 있는지에 대한 단 하나의 혼합으로 귀결되도록 강제합니다. 하지만 관련성에는 여러 갈래가 있습니다. 한 단어를 이해하려면 그것의 문법적 주어, 그것의 어조, 그것이 속한 주제를 동시에 신경 써야 할 수 있는데, 이것들은 서로 다른 질문입니다.
트랜스포머는 여러 어텐션 연산을 병렬로 수행하며, 각각이 서로 다른 종류의 관계에 자유롭게 집중하게 합니다. 하나는 동사가 어떤 명사에 속하는지를 추적할 수 있고, 또 하나는 한 문단을 가로지르는 주제의 흐름을 따라갈 수 있습니다. 그 결과들이 결합되어, 각 단어는 하나가 아니라 여러 관점이 동시에 반영된 정보를 갖게 됩니다. 이것이 바로 이 아키텍처가 "관련 있다"라는 단일하고 납작한 개념 대신, 실제 언어의 겹겹이 포개진 구조를 포착할 수 있는 이유입니다.
이 설계가 그토록 잘 확장된 이유
트랜스포머가 승리한 것은 단지 언어를 더 잘 이해했기 때문만은 아닙니다. 우리가 모델을 학습시키는 하드웨어에 놀랍도록 잘 맞았기 때문에 승리했습니다. 모든 위치가 사슬이 아니라 병렬로 처리되기에, 트랜스포머는 엄청난 수의 연산을 한 번에 수행하도록 만들어진 프로세서를 온전히 활용합니다.
그 효율성은 심대한 결과를 낳았습니다. 이전보다 훨씬 큰 모델을 훨씬 많은 데이터로 학습시키는 일이 현실적으로 가능해진 것입니다. 이 아키텍처는 더 크게 만들고 더 많은 텍스트를 먹일수록 계속 좋아졌으며, 뚜렷한 천장도 보이지 않았습니다. 부분적으로는 공학적 편의 때문에 선택된 설계가, 정확히 이전 설계들이 흡수하지 못한 규모를 흡수할 수 있었기에, 대규모 모델 시대 전체의 토대가 되었습니다.
트랜스포머가 스스로 하지 못하는 것
한계를 분명히 해 두는 것이 도움이 됩니다. 트랜스포머는 아키텍처, 즉 연산을 배치하는 방식입니다. 그 자체로는 아무것도 알지 못합니다. 모델이 "아는" 모든 것은 데이터로 학습시킨 데서 나옵니다. 트랜스포머는 그 학습이 일어나기에 유독 효과적인 틀을 제공할 뿐입니다.
또한 트랜스포머는 그 안에 내장된 어떤 방식으로도 추론하거나 계획하거나 검증하지 않습니다. 그것은 시퀀스의 문맥 인식 표현을 만들어 내고, 언어 모델에서는 다음에 무엇이 올지 예측합니다. 그 위에서 떠오르는 놀라운 능력들은 규모와 데이터, 학습에서 비롯된 것이지, 아키텍처가 논리를 발명해서가 아닙니다. 이 점을 이해하면 기대를 정직하게 유지할 수 있습니다. 트랜스포머는 무대이지, 공연이 아닙니다.
정리
잠시 방정식은 잊으세요. 트랜스포머는 시퀀스 전체를 한 번에 처리하고, 모든 단어가 다른 어떤 단어가 자신에게 중요한지 스스로 결정하게 하는 규율입니다. 어텐션이 그 결정이고, 레이어가 그것을 깊게 하며, 위치 태그가 순서를 보존하고, 병렬 어텐션이 여러 관계를 한 번에 포착합니다. 수식은 이것이 어떻게 만들어지는가이고, 아이디어는 그것이 왜 작동하는가입니다. 직접적이고, 모두가 모두를 향하며, 단 한 번의 훑기로 계산되는 그 단 하나의 동작이야말로, 이 아키텍처를 이전의 모든 것보다 더 유능하고 더 확장 가능하게 만든 것입니다.
