AI는 인간의 말을 어떻게 이해할까?
인간은 오랫동안 기계와 대화하는 것을 꿈꾸었다. 수많은 시행 착오 끝에 드디어 기계가 인간의 말(글)을 이해할 수 있게 되었다. 2022년 11월, 챗GPT라는 이름으로 등장한 LLM(Large Language Model: 거대 언어 모델)이 바로 그것이다. (그 이전에도 꽤 여러 모델이 그러한 기능을 발휘한 바 있다.) 초기에는 많은 오류들이 발생했으나 이제는 상당한 수준으로 모든 주제에 대해서 실시간 대화가 가능하게 되었다. 그런데 AI는 대체 어떻게 인간의 말과 글을 이해할까? 문송러로서 LLM 모델의 작동 원리를 한 번 추적해 보았다.
LLM 모델은 한 마디로 하자면 자동 완성 기능을 응용한 것이다.
컴퓨터나 모바일을 사용할 때, 유저가 입력창에 글자를 쓰기 시작하면 아직 완성되지 않은 나머지 글자를 컴퓨터가 확률적으로 계산해서 예측하여 이를 제안해 주는데 이것이 자동 완성 기능이다. 자동 완성 기능이 활성화되면 맨 위에 제시된 글자/단어가 확률이 가장 높다는 뜻이고 아래로 내려갈 수록 확률이 낮다는 뜻이다. LLM은 바로 이러한 자동 완성 기능을 응용한 것이다. 하지만 이것이 어떻게 인간과 대화가 가능한 수준으로 작동할 수 있을지가 참 의문이다.
LLM 모델을 만들기 위해서 가장 먼저 해야 할 일은 텍스트를 토큰화해야 한다. 컴퓨터는 책이나 논문에 있는 단어를 바로 이해하지 못한다. 컴퓨터는 오직 '숫자'만 이해한다. 따라서 책이나 논문에 있는 수만, 혹은 수십 만 단어들을 컴퓨터가 이해할 수 있는 '숫자'로 변환하는 작업이 필요하다. 이것이 토큰화와 임베딩이다. 먼저 토큰화하고 그 다음 임베딩을 해야 한다. 토큰화부터 알아보자. 토큰화는 텍스트를 토큰으로 바꾸는 작업이다. 토큰이란 무엇인가? 토큰은 기본적으로 단어와 유사하다. 대체로 한 단어는 한 토큰이다. 그러나 반드시 그런 것은 아니다. 특수문자도 하나의 토큰이고, 복합명사는 따로 떼어서 2-3개의 토큰으로 나눌 수 있다. 가령 스마트폰(smartphone)은 스마트(smart)와 폰(phone)으로 나누어 토큰화할 수 있다.
토큰이 단어와 비슷하다고 해서 컴퓨터가 토큰으로 '의미소'를 이해한다는 뜻은 아니다. 컴퓨터는 단어의 뜻을 알지 못한다. 그럼 왜 토큰화할까? 컴퓨터가 처리하기 용이한 단위로 분절하기 위함이다. 방대한 텍스트 데이터를 입력할 때의 입력 단위이자 학습이나 추론을 하기 용이한 단위가 바로 토큰이다. 다시 말하지만 AI는 단어의 뜻을 알지 못한다. AI 특히 LLM의 작동은 기본적으로 순수한 수학과 확률, 통계로 이루어진다. 그러나 방대한 학습을 통해서 임베딩이 이루어지고, 각 토큰의 행렬 벡터값이 만들어지면 각 토큰들 간의 관계를 통해서 맥락적으로 토큰을 이해(?)할 수 있다. 물론 이것은 수학적인 방식으로 이해하는 것이지 인간이 단어를 이해하는 방식과 같다고는 할 수 없다.
이렇게 토큰화한 뒤 다음 토큰을 예측하는(Next Token Prediction) 모델이 바로 LLM인 것이다. 챗GPT와 같은 모델들에게 질문을 하면 AI가 답을 할 때, 첫 번째 단어를 쓰고, 다시 그 다음 단어를 쓰고, 그 뒤 계속 순서대로 다음 단어를 쓰는 것은 이 때문이다. 첫 번째 단어 다음에 올 가장 최적의 단어를 예측하여 제시하고, 다시 그 다음 단어를 예측하여 제시하고, 다시 그 다음... 이렇게 차례로 그 다음에 올 단어들을 예측하여 제시한다. 그래서 AI가 차례로 단어를 나타내 보이면서 문장을 쓰는 것이다.
책이나 에세이의 수만, 수십 만 단어들을 토큰화했으면 이를 기계가 이해할 수 있는 '숫자'로 입력해야 한다. 이를 임베딩이라고 한다. 임베딩을 해야지 AI에게 학습을 시킬 수 있고(처음에는 랜덤한 값으로 시작한), AI 모델을 동작시킬 수 있다. 그럼 임베딩은 어떻게 하는가? 컴퓨터는 숫자만 이해할 수 있으니, 토큰들을 숫자화해야 한다. 그럼 어떻게 토큰을 숫자화시키는가?
임베딩 프로세스를 이해하기 쉽게 하기 위해서 다음의 예를 하나 들어보자. 축구 선수의 역량을 수학적으로 계산하는 프로그램이 있다고 해보자. 그런데 그동안 수백 번의 경기를 분석해서 메시는 공격력 99점, 수비력 30점, 체력 50점, 손흥민은 공격력 95점, 수비력 55점, 체력 60점, 김민재는 공격력 30점, 수비력 89점, 체력 75점이 나왔다고 해보자.
이때 이 데이터를 바탕으로 세 선수는 다음과 같은 행렬로 표시할 수 있다.
메 시(99, 30, 50)
손흥민(95, 35, 60)
김민재(30, 89, 75)
이를 3차원 그래프상에 점으로 표시할 수도 있을 것이다.
위의 그림에서 볼 수 있듯이 공격력, 수비력, 체력이라는 3가지 기준에 따른 점수를 행렬로 표시하고 이를 xyz 3차원 그래프상 공간에 떠 있는 점으로 표시할 때, 이를 (0, 0, 0)에서 출발하여 (x, y, z)값에 도달하는 벡터로 표시할 수 있다. 이렇게 표시하면 손흥민과 메시는 공격수로서 거리가 가깝다. 또 이 두 선수를 표시하는 벡터의 기울기가 사뭇 비슷하다는 사실을 알 수 있다. 반면에 김민재 벡터의 기울기는 메시나 손흥민과 상당히 다르다.
(0, 0, 0)에서 각 선수의 좌표(x, y, z)로 출발하는 벡터를 표시했을 때 유용성이 여기서 드러난다. 벡터는 기울기 혹은 다른 벡터와의 각도를 통해서 유사성과 차별성을 수학화할 수 있다. (이를 코사인 유사도라고 한다.) 즉 이러한 벡터 표시를 통해서 공격형 선수들끼리, 수비형 선수들끼리, 그리고 미드필더형 선수들끼리 클러스터링할 수 있는 것이다. 즉 토큰을 임베딩한다는 것은 행렬 벡터로 표시한다는 뜻인데, 바로 위와 같은 각 토큰들 간의 거리를 수학적으로 계산할 수 있게 된다는 뜻이다. 이를 통해서 각 선수들의 스타일, 장점, 단점.. 등 여러 가지 정보들과 그것들와 관계를 직관적으로 파악하고 분석할 수 있다. 즉 위의 그래프를 통해서 벡터의 각도는 스타일을 뜻하고, 벡터의 길이는 강도나 빈도 등을 뜻한다.
텍스트의 토큰도 이렇게 좌표상 벡터로 표시한다면 각 토큰들 간의 관계들을 파악할 수 있는 것이다. 그럼 텍스트의 토큰은 몇 가지 차원의 행렬 벡터로 표시될까? 위의 3차원과는 비교할 수 없을 정도의 차원으로 토큰들을 임베딩할 것이다. 텍스트의 토큰들을 임베딩할 때에는 문법적 차원(품사, 시제, 단수/복수), 의미적 차원(성별, 생물/무생물, 긍/부정), 관계적 차원(상하, 용도) 등... 수천 에서 수만 가지 차원이 사용된다. 이렇게 각 토큰들은 수천에서 수만 차원에 따라서 값을 배정받을 수 있을 것이다. (초기 챗GPT 모델의 경우, 행렬 벡터값은 1,536차원이 사용했다. 하지만 현재는 그보다 훨씬 더 크다. 1,536차원으로 행렬 벡터값을 구한다는 뜻은 1,536차원 그래프 공간상에 점을 찍고 이를 (0, 0. 0...0)에서 출발하는 벡터로 표시할 수 있다는 뜻이다.) 이렇게 해서 '사과'라는 토큰의 벡터값을 배정받을 수 있을 것이다.
사과: $$\text{사과} = [0.12, -0.45, 0.88, 0.01, -0.23, 0.54, \dots, -0.09]$$
그럼 어떻게 이러한 벡터값을 구할 수 있을까? 앞에서 축구 선수의 사례를 들었는데, 이때 수많은 경기를 분석한 결과로 각 선수의 행렬 벡터값(공격력, 수비력, 체력)을 구했다. 마찬가지로 LLM 모델의 경우, 수많은 토큰들의 행렬 벡터값 수백만 권의 책과 수억 개의 아티클을 학습해서 정한다. 이때의 학습을 기계학습이라고 한다. 즉 기존의 방대한 텍스트를 학습하면서 각 토큰들이 다른 토큰들과 어떤 관계 속에 위치하는지 그 통계와 확률을 바탕으로 벡터값을 구하게 되는 것이다. 이것이 의미하는 바는 벡터값이란 결국 각각의 토큰들이 다른 토큰들과 맺는 관계 속에서 구해질 수 있다는 것이다.
이렇게 구해진 각 토큰들은 (시각화할 수 없지만) 수천 수만 차원의 그래프상의 무수히 별들과 같이 많은 점들로 찍힐 수 있을 것이다. 물론 그 무수히 많은 점들은 (0, 0, 0....0)에서 출발한 화살표, 즉 벡터들이다. 이렇게 하는 것이 바로 임베딩하는 작업이다. 하지만 기계 학습을 하기 전에는 행렬 벡터의 숫자는 정확하지 않않다. 어마어마한 기계학습을 통해서 서서히 그 행렬 벡터값을 정교하게 정하게 되는 것이다.
이제부터 할 일은 '학습'이다. 기계에게 학습을 시킨다고 해서 '기계 학습'(machine learning: 머신러닝)이다. 기계 학습은 AI 발전에 있어서 혁명적인 발전이었다. 초기 AI 개발자들은 AI를 개발할 때, 사람이 일일이 규칙을 정해주었다. 가령 이미지 인식 AI를 개발할 때, '고양이는 귀가 뾰족하고, 수염이 있고, 눈동자가 세로야'라고 일일이 설명을 해주었던 것이다.
# 고양이 인식 알고리즘
입력값 = { '귀의_모양': '뾰족함', '수염': '있음', '눈동자': '세로' }
IF 입력값['귀의_모양'] == '뾰족함':
IF 입력값['수염'] == '있음':
IF 입력값['눈동자'] == '세로':
결론 = "이것은 고양이입니다!"
ELSE: 결론 = "눈동자가 다르니 고양이가 아닙니다."
ELSE: 결론 = "수염이 없으니 고양이가 아닙니다."
ELSE: 결론 = "귀가 안 뾰족하니 고양이가 아닙니다."
이것을 규칙 기반(rule based) AI라고 한다. 그러나 이러한 규칙 기반 AI로는 너무다 많은 변수를 일일이 설명을 할 수 없다는 문제에 봉착하게 된다. 가령 귀가 접힌 고양이, 수염이 가려진 고양이 사진, 눈을 감고 있는 고양이... 등 수많은 변수들을 일일이 설명할 수가 없다. 그러니 이미지 인식 AI의 정확도가 6-70% 정도 선에서 멈추고 그 이상 개선이 안 되는 것이다.
그런데 이 장벽을 무너뜨린 장본인이 바로 제프리 힌턴 교수이다. 그는 인간이 규칙을 입력하는 대신 AI가 스스로 규칙을 찾도록 주도권을 AI에게 넘겨주었다. 규칙 기반에서 데이터 기반으로의 혁신이 이루어진 것이다. 그는 고양이 사진 수십 만 장을 보여주면서 '얘가 고양이야'라고 알려주었다. 이것이 바로 '기계 학습' 즉 머신 러닝 작업이었다. 물론 머신 러닝의 개념은 매우 일찍부터 존재했는데, 힌턴 교수는 이 머신 러닝을 좀 더 정교하게 하기 위해서 딥러닝 알고리즘이 개발하고, 이를 이미지 인식 AI에 처음 활용했던 것이다.
그 사진에는 평범한 고양이 사진은 물론이고 귀가 접힌 고양이, 수염이 가려진 고양이 사진, 눈을 감고 있는 고양이... 등 수많은 변수들도 모두 포함되어 있었다. 그랬더니 AI가 고양이가 패턴을 스스로 찾아내기 시작했다. 그리고는 이제 고양이, 개, 사자, 사람... 둥 새로운 사진을 보여주었다. 이때 AI가 고양이 사진을 제대로 맞추지 못하면 파라미터의 가중치(weight)와 편향(bias)을 미세하게 조정했다. 그렇게 해서 고양이 사진을 제대로 인식할 때까지 각 노드들의 파라미터 가중치와 편향값을 지속적으로 조정했더니 어느 순간 오차율이 거의 없는 이미지 인식 AI가 출현하게 된 것이다.
AI 개발자들은 이러한 딥러닝 알고리즘을 llm 모델에도 적용했다. 그래서 방대한 텍스트를 토큰화하고, 대략의 값으로 행렬 벡터값을 정한 뒤 여러 레이어(챗GPT 초기 모델의 경우 96개층 레이어)가 겹쳐진 딥러닝 알고리즘을 활용하여 llm 모델을 만들었다.
llm 모델을 만들기 위해서 일단 방대한 텍스트를 입력하는 작업이 필요하다. 챗GPT의 경우 수조 개의 문서를 입력하여 학습했다고 한다. 이것이 사전 학습에 해당한다. 하지만 사전 학습만 해서는 AI와 대화할 수 없다. 대화할 수 있게 하기 위해서 AI를 모델링해야 한다. 모델링을 위해서는 각 토큰들의 임베딩을 통해서 행렬 벡터값을 정교화해야 하고, 파라미터(가중치, 편향)값도 구해야 한다. 그리고 이를 위해서 Q & A 작업을 수행해야 한다. 이 Q & A 작업은 96개 층의 심층 레이어를 오가며 전파(propagation)와 역전파(back propagation) 과정을 거쳐야 한다. 이렇게 전파와 역전파 과정을 반복하면서 토큰들의 임베딩과 파라미터값을 구할 수 있다. 이것을 미세 조정 과정이라고 한다.
레이어를 많이 쌓았다고 해서 심층 신경망이라고 하고, 이것을 통한 기계 학습을 딥러닝(deep learning)이라고 한다. 그런데 레이어를 많이 쌓는 이유는 무엇인가? 토큰의 의미를 정교하게 학습하게 만들기 위해서다. 낮은 레이어들에서는 문법, 형태 같은 표면적 특징을 파악하고, 높은 레이어들(출력에 가까운 층)으로 갈수록 문맥, 의도, 추상적 관념 같은 심층적 의미를 파악하게 한다.
Q & A라고 해서 이를 인간과 AI 간의 Q & A라고 생각하면 안 된다. 이 Q & A도 AI가 알아서 한다. 내가 Q & A라고 말한 이 프로세스가 바로 기계 학습 과정이다. 이때의 기계 학습은 기계 학습 중에서도 지도 학습에 속한다. (지도 학습은 정답을 알고 있는 상태에서 하는 학습을 말한다.) AI가 스스로 하는 학습이니 자기 지도 학습(Self-supervised Learning)이라고 한다. 이때 하는 학습, 곧 Q & A는 일종의 빈칸 채우기 작업인데, 이를 Masked Language Modeling이라고 한다. 예를 들어보자.
이런 문장에 들어갈 단어를 채우는 작업이 바로 Q & A 작업이다. 그리고 위의 문장은 llm 모델이 과거에 학습했던 데이터 안에 있는 문장이다. 그런데 llm 모델이 '돈'을 채워넣으면 맞을 가능성이 높고, '밥'을 채워넣으면 틀릴 가능성이 높다. Q & A를 하면서 빈 칸에 제대로 답을 하거나 틀린 답을 할 때마다 수천 억개의 파라미터값을 미세하게 변화시킨다. 그래서 틀린 답을 하면 파라미터를 크게 변화시키고 맞는 답을 하면 파라미터를 크게 변화시키지 않은 것이다. 이렇게 무수히 많은 Q & A를 하다보면 llm 모델이 서서히 수천 억, 수조 개의 파라미터를 찾을 수 있게 된다. 그리고 이 파라미터, 곧 가중치와 편향의 수치가 llm 모델의 핵심이다.
Q & A를 하는 중에 '돈'이라는 토큰과 '밥'이라는 토큰 간의 거리와 관계도 수학적으로 계산된다. 이렇게 '돈'과 '밥'의 계산된 거리는 '돈'과 '밥' 토큰의 행렬 벡터 값에 반영된다. 우리는 앞의 축구 선수의 비유에서 보았듯이 메시와 손흥민은 공격수로서 비슷한 그룹에 묶이고, 김민재는 수비수로서 떨어지게 배치된다는 사실을 본 바 있다. 이와 비슷하게 이러한 반복 학습을 통해서 각각의 단어들이 다른 단어들과의 거리가 수학적으로 지정되는 것이다. 이것이 바로 각 토큰들의 행렬 벡터 값이다. 이 작업을 무수히 반복한다. 그러면 점차 파라미터가 정교하게 최적화되는데 이를 '사전 학습'(pre training)이라고 한다. 동시에 각 토큰의 행렬 벡터값도 정교화되는데 이것이 임베딩이다. 그래서 점차 '철수는 직장에서 ( )을 벌어왔다'는 문장에서 '밥'은 멀어지고 '돈'이나 '월급' '임금'.. 과 같은 단어들이 근거리로 묶여서 클러스터링되는 것이다.
이렇게 토큰들을 임베딩하고, 파라미터값을 구했다고 해서 학습이 다 끝난 것이 아니다. 이제 진짜로 인간이 개입하는 과정이 필요하다. 소위 RLHF(Reinforcement Learning from Human Feedback, 인간 피드백을 통한 강화 학습) 과정이다. 여기에 동원되는 기계 학습은 강화 학습(reinforcement learning)이다. 강화 학습은 AI와 Q & A 과정을 통해서 괜찮은 답이 나오면 + 1과 같은 보상함수를 제공하고, 반대로 잘못된 답이 나오면 보상함수를 제공하지 않거나 도리어 감점을 시켜서 학습하는 것을 뜻한다. 가령,
질문: "나 오늘 기분이 너무 안 좋아."
답변 A: "그렇군요. 힘내세요." (좋음) -> 가점
답변 B: "어쩌라고요? 저는 기계입니다." (나쁨) -> 감점
이러한 RLHF 단계를 통해서 할루시네이션을 줄이고, 좀 더 예절바른 llm 모델이 만들어지게 된다. 최종 단계에서 이루어지는 RLHF는 AI가 내놓은 답이 인간의 윤리와 가치관에 부합하지 않는 답을 할 때, 이를 교정하는 기계 학습이다. 이 최종 단계의 학습이 끝나야 비로소 LLM 모델이 출시될 수 있는 것이다.
이렇게 llm 모델, 곧 AI가 만들어지면 이 모델로 다음 토큰을 예측하게 할 수 있다. 다음 토큰 예측을 하는 것이 바로 llm 모델이 인간과 대화를 할 수 있는 것 같은 착각(?)이 들도록 작동하는 방식이다. 가령 'Tom이 소년이냐, 소녀냐?'고 묻는 질문에 llm 모델은
토큰(Tom) -> 토큰(is) -> 토큰(a) -> 토큰(boy) -> 토큰(.)
을 순차적으로 예측할 수 있다. 이것은 다음과 같은 벡터로 표시될 수 있을 것이다.
그리고 모니터에는
"Tom is a boy."
와 같이 출력해 주는 것이다.
llm 모델에서 모든 텍스트는 토큰화된다. 그리고 토큰은 수천, 수만 차원의 행렬 벡터값으로 표시된다. 만일 수천 차원 그래프가 있다면 각 토큰은 (0, 0, 0....0)에서 각 행렬 벡터값으로 향하는 벡터(화살표)로 표시될 수 있을 것이다. 이때 토큰과 토큰의 거리도 역시 숫자로 표시될 수 있을 것이다. 가령 '철수는 직장에서 ( )을 벌어왔다'라는 문장의 ( )에 들어갈 단어들 중에 돈, 월급, 임금... 등의 토큰은 분명 거리가 가까워서 클러스터링될 수 있을 것이다. 그러나 '밥'이나 '자동차'는 거리가 멀 것이다. 이렇게 토큰이 수학화된다는 점은 흥미롭게도 다음과 같은 토큰 산수를 가능하게 한다.
가령
돈 + 돈 =?
답은 '떼돈'이다.
왕 - 남자 + 여자 =?
답은 '여왕'이다. 왜냐? 왕에서 남자의 값을 뺀 값에 여자의 값을 더하니까 여왕이 된다는 것이다. 그리고 만일 남자와 여자, 왕과 여왕의 토큰을 그래프에 그린다면 다음과 같은 사실을 알 수 있다. 남자 토큰에서 여자 토큰으로 가는 벡터의 길이와 기울기는 왕에서 여왕 토큰으로 가는 벡터의 길이 및 기울기, 그리고 벡터들 간의 각도가 같다는 사실을 말이다.
'왕과 여왕의 관계는 남자와 여자의 관계와 같다'를 문학적으로 유비(analogy)라고 한다. llm 모델의 임베딩은 문학적으로 '유비'(analogy)라고 부르는 것을 수학적으로 평행하는 벡터로 표시될 수 있다는 사실을 보여준다. 물론 이러한 토큰 산수는 현대의 LLM 모델에서는 거의 잘 되지 않는다. 왜냐? 토큰의 행렬 벡터 값이 고정되어 있지 않기 때문이다. 문맥에 따라서 미세하게 변동된다. 거대한 토큰들이 대화를 하는 중에 맥락에 따라서 미세하게 값을 변화하는 것은 마치 살아 있는 유기체와 같이 놀랍고 신비롭다. 따라서 위의 토큰 산수는 아주 초기의 LLM 모델에서 나타났던 현상이라는 사실을 기억할 필요가 있다.