1장 AI는 데이터를 어떻게 이해할까: 특징량화의 원리
생성형 AI 모델에만 국한되어 있지 않고 머신러닝 모델 전반에서 입력을 다룰 때는 아래 그림처럼 우리가 다루고 싶은 대상을 컴퓨터가 처리할 수 있는 형태로 데이터화하고 그 다음에 머신러닝 모델이 다룰 수 있도록 적절한 변환을 거쳐 특징량(특징 벡터)으로 만드는 과정이 필요합니다.
여기서 '머신러닝 모델에서 다룬다'라는 말은 행렬연산이나 지수/로그/시그모이드 같은 기초적인 수학함수등을 적용해 더 유용한 특징량을 구성한다는 뜻입니다.
이렇게 구성된 특징량은
어떤 값을 예측하는데 쓰이거나,
새로운 데이터를 생성하는데 사용됩니다.
이미지의 경우에는, 데이터화와 특징량화 사이에 큰 간극이 없어서 본질적인 어려움이 크게 발생하지 않습니다.
이미지의 각 픽셀값을 예를 들어,
으로 표현하면, 그 자체로 컴퓨터에서 다룰 수 있고, 기본적으로는 거의 그대로 머신러닝 모델의 입력으로 사용할 수 있습니다. 물론 여러 관점에서 처리 방식을 바꾸는 경우가 있습니다. 예를 들면,
(R, G, B)를 {0, 1, ..., 255}의 정수값으로 표현한다거나,
알파채널(투명도)을 추가한다거나
다른 색 공간 (예: YUV, Lab등)으로 변환한다거나,
입력 이미지 크기가 너무 작거나 크다면, 신형 보간 등을 이용해 크기를 맞춘다거나
하지만, 이런 조정들은, 초기 데이터화 단계에서 큰 개념적 도약을 요구하는 수준은 아니며, 복잡한 개념을 새로 도입하지 않고도 처리할 수 있습니다.
이미지 자체가 애초에 연속적인 값으로 자연스럽게 표현 가능하기 때문에, 특징량화 역시 상대적으로 단순하게 수행되며 머신러닝 관점에서는 비교적 다루기 쉬운 유형의 데이터라고 할 수 있습니다.
음성 데이터의 경우에도, WAV나 MP3처럼 저장포맷의 차이가 존재하고, 특징량화 시에는 주파수 영역으로 변환하여 처리하는 등 전문적으로 접근하면 다양한 요소가 개입합니다. 그럼에도 본질적으로는
"음성이라는 물리현상을 표현한 파형(time series) 데이터"
가 대상이며, 그 데이터에 내재된 성질을 잘 끌어내기 위해 추가적인 처리를 하는 것이라는 점에서, 이미지 데이터와 근본적으로 크게 다르지 않습니다.
이 역시 연속값으로 자연스럽게 표현 가능한 데이터이기 때문에, 머신러닝 관점에서 다루는 것은 비교적 수월한 편에 속합니다.
반면, 텍스트의 경우에는 머신러닝 모델에서 다루기 위해 반드시 넘어야 하는 본질적인 난관이 존재합니다.
먼저 데이터화 측면에서 보면, 텍스트는 음성처럼 물리현상으로 그대로 정식화할 수 있는 것이 아니며 이산적인 기호(symbol)로서 다룰 수밖에 없습니다.
ASCII코드만 대상으로 한다면, 각 문자를 1바이트 정보로 표현할 수 있어 비교적 간단한 세계에서 끝납니다.
그러나 필자가 이 글을 한국어로 쓰고 있듯이, 현실 세계에서 인간이 사용하는 다양하고 풍부한 자연어를 다루고 싶어집니다. 모든 문자를 다루기 위해 Unicode 15.04를 사용하며 문자수는 149,186자에 달합니다. 이를 컴퓨터가 다룰 수 있는 바이트 시퀀스로 변환하기 위해 UTF-8 같은 문자 인코딩 방식을 사용해야 합니다.
이러한 데이터화 문제는 머신러닝이 등장하기 훨씬 전부터 존재했던 주제이기 때문에 그 자체는 머신러닝과 독립된 어려움입니다. 하지만 이처럼 구조가 복잡하고, 시간이 지날수록 계속 확장될 수 있는 문자체계와 계속 함께 살아가야 한다는 점은 변하지 않습니다.
특징량화 측면에서는, 머신러닝에서 유용하게 쓰일 특징량을 어떻게 만들 것인가가 전혀 자명하지 않습니다. 머신러닝에서는 보통 오차역전파(Backpropagation)로 모델을 학습하는 것이 강력한 방법인데 자연어는 이산적인 기호이기 대문에, 연속적인 변형 연산(즉, 미분가능한 연산)을 그대로 적용할 수 없습니다.
그리고,
"미분 연산을 할 수 없다."
는 것은, 수학적으로나 머신러닝적으로나 상당히 치명적인 제약입니다. 그래서 텍스트 데이터도 어떤 방법을 통해서든 연속적인 특징량으로 변환해, 미분 연산이 가능하도록 만드는 것이 필수적입니다.
이 부분이 텍스트 처리에서 반드시 넘어야 하는 핵심적인 어려움입니다. 물론 "연속값을 만들 수만 있으면 아무거나 상관없습니다."는 것은 아닙니다. 사람이 이해하기에 의미있는 특징량일수록 바람직합니다.
여기서 "의미있는" 이라는 말을 명확히 수식으로 정의하기는 힘들지만, 예를 들면,
사람이 봤을 때 비슷하다고 느끼는 단어들은 임베딩 공간에서도 가까운 벡터로 표현되었으면 좋겠다.
와 같은 요구를 떠올릴 수 있습니다.
설령 운좋게 그런 특징량으로의 변환 방법을 잘 설계했다하더라도,
"주어진 텍스트 데이터를 어떤 단위로 나누어 특징량화할 것인가?"
라는 문제 역시 전혀 자명하지 않습니다.
사람이 관심을 가지는 것은 문장 전체와 같은 큰 단위뿐만 아니라,
단어
문자
같은 더 작은 구성요소에도 관심이 있습니다. 그래서 텍스트 데이터를 단어 단위로 나누고자 하면, 한국어처럼 띄어쓰기만으로 단어 경계를 명확히 구분하기 어려운 언어에서는 형태소 분석이나 토큰화 과정이 복잡해 집니다. 예를 들어, "밥먹었다"라는 문장은 "밥/먹/었/다"처럼 여러 형태소로 나눠야 의미를 제대로 파악할 수 있습니다. 중국어나 일본어의 경우에는 띄어쓰기가 명확하지 않은 단어에서는 형태소 분석이나 분절(분할)처리에 매우 복잡한 절차가 필요해 집니다.
원래부터 이산적인 기호로 이뤄진 텍스트를 머신러닝에서 잘 활용할 수 있도록 특징량화하는 작업은 다시 생각해 보면 꽤 어려운 처리라는 점을 실감하게 됩니다.
지금까지 이야기한 이런 어려움들을 고려하면, 텍스트 데이터를 좋은 특징량으로 변환하는 문제는 자연어처리(NLP)의 한 분과로 자리 잡아왔습니다. 그 중에서도 중심적인 역할을 하는 것이 바로,
토큰(token)에서 연속적인 특징량을 얻는 임베딩(embedding)과
텍스트를 토큰 단위로 분할하는 토큰화(tokenization)입니다.
이후에서는, 임베딩과 토큰화 가운데서도 특히 생성형 AI에서 중요한 부분에 초점을 맞춰 설명해 나갈 것입니다. 덧붙여 이 강좌에서는 텍스트 데이터를 머신러닝에서 다룰 때의 최소 구성단위를 토큰(token)이라고 부릅니다. 이 토큰을 가리키는 대상은 문맥에 따라 달라질 수 있으며, 예를 들면,
바이트 시퀀스
문자
단어
이후에 설명할 서브워드(subword)
등을 의미할 수 있습니다.
앞에서 텍스트의 경우, 데이터를 어떻게 특징량으로 만들 것인지를 고민해야한다고 말했습니다. 머신러닝에서 텍스트를 다루는 가장 단순한 방법 중 하나로, 국소 표현(local representation)이라 불리는 원-핫(one-hot) 벡터가 있습니다.
이는 어휘 집합 V에 대해 |V|차원 벡터를 준비하고, 해당 토큰에 대응하는 성분만 1, 나머지는 0으로 두는 방식입니다. 여기서는 예시로
V = {물리학, 수학, 인문학, 사회학}
을 생각해 봅시다.
각 토큰의 원-핫 벡터는 다음처럼 쓸 수 있습니다.
이들은 벡터이기 때문에 연속값으로 취급할 수 있다고 가정하면 선형 변환이나 각종 함수 적용 등을 통해 머신러닝 모델에서 다룰 수 있습니다. 하지만 이 방식으 아래와 같은 이유로 그다지 효과적이라고 보기 어렵습니다.
토큰 수가 늘어날수록 차원이 커져 계산 비용이 폭증합니다.
토큰이 N개 있을 때, 이를 선형 변환하면 계산량은
이 됩니다. 일부 토큰만 실제로 사용하더라도, 어휘 크기의 제곱에 비례해 비용이 증가하는 셈입니다.
토큰 간의 유사성이나 관계성 같은 언어 정보가 전혀 반영되지 않습니다.
그래서 특징량으로서 쓸모가 거의 없습니다. 예를 들어, 어떤 두 토큰을 골라도 그 원-핫 벡터들의 유클리드 거리(Euclidean distance)는 항상
가 됩니다. 보통 거리 개념을 기반으로 유사도를 정의하면 모든 토큰 쌍의 유사도가 똑같이 나와 버리는 문제가 생깁니다.
연습문제1: 토큰의 원-핫 표현에서 서로 다른 두 토큰의 거리가 항상 같지 않게 되는 거리 정의 방법을 하나 생각해 보세요.
이 문제를 해결하기 위한 방향으로 분산표현(distrubuted representation)이라는 개념이 등장합니다. 이는 각 차원에 정보가 연속적으로 분포된 벡터로 토큰을 표현하는 방식입니다. 예를 들어, 토큰 정보를 표현하는데 필요한 차원이 대략
정도라고 가정해 봅시다.
(지금 예시에서는 |V| = 4이므로
) 그때 다음과 같은 분산 표현을 생각해 볼 수 있습니다.
이 경우, d물리학과 d수학사이의 거리는 d인문학과 d사회학 사이의 거리보다 더 작습니다.
즉 분산 표현 상에서
물리학과 수학이 인문학보다 더 비슷하다.
는 정보를 반영할 수 있는 셈입니다. 이처럼 분산. 표현을 잘 구성할 수 있다면,
국소 표현(원-핫)과 비교해 더 낮은 차원으로 토큰 정보를 다룰 수 있고,
토큰 간의 유사성 및 관계성을 표현하기 쉬워지므로
훨씬 효율적입니다.
위 예시는 다소 극단적으로 "필요한 차원이 어휘 크기에 비해 지수적으로 작다"는 상황을 상정했지만, 원-핫 벡터와 비교할 때 더 낮은 차원에서 의미를 표현할 수 있다는 점에서 이견이 없을 것입니다.
이처럼 토큰을 분산표현으로 변환하여 특징량으로 사용하는 작업을 임베딩(embedding)이라고 부릅니다. 임베딩은, 머신러닝에서 텍스트 데이터를 다루기 위해 사실상 필수적인 연산이며, 풀고자 하는 태스크에 알맞은 임베딩을 학습하는 것은 성능을 끌어올리는 핵심요소 중 하나입니다.
문제는 "그런 임베딩을 어떻게 학습할 것인가?"라는 점입니다. 생성형 AI는 보통, 여러 언어를, 여러 목적으로 다루고 싶어하는 경우가 많습니다. 이럴 때는 가능한 한 사람이 설계한 외부지식에 의존하지 않고, 데이터로부터 언어의 특정을 학습해 임베딩을 얻는 편이 더 유리한 경우가 많습니다.
그렇다면, "데이터로부터 언어특성을 학습한다."라는 것은 구체적으로 무엇을 의미할까?
널리 쓰이는 접근법으로 아래 그림처럼 주어진 텍스트에서 스스로 문제를 만들어 내고, 그 문제를 푸는 과정에서 언어 특성을 학습하는 방법이 있습니다.
예를 들어,
토큰 빈칸 채우기(cloze)문제를 풀게 한다든지,
다음에 올 토큰을 예측하게 한다든지,
어떤 문장 A 다음에 문장 B가 왔을 때, 두 문장이 연속된 문장인지 아닌지를 맞히게 한다든지...
이러한 학습 문제들은 원래 가지고 있는 텍스트 데이터만 있다면, 그 안에서 자동으로 생성할 수 있습니다. 그래서 학습용 태스크를 만들어 내기 쉽다는 장점이 있습니다.
학습 방법은 다음과 같습니다.
각 토큰마다 랜덤 초기화된 분산표현(임베딩)을 준비합니다.
위에서 말한 문제들에 대해 손실(loss)이 작아지도록 분산 표현들을 학습합니다.
대표적인 경우로, 대음 토큰 예측(next token prediction)문제를 생각해 봅시다.
다음과 같은 손실 함수(음의 로그 우도)를 사용해, 다음 토큰 ti의 예측확률을 기준으로 모델 파라미터 θ를 학습합니다.
이 방법은 매우 단순하지만, 생성형 AI 모델학습에서 놀라울 정도로 강력하게 작동하고 있습니다. 이 접근법의 전제는 분포 가ㅓㄹ(Distributional Hypothesis)이라 불리는 아이디어입니다. 이는 다음과 같은 가설입니다.
"단어의 의미는 그 단어가 등장하는 문맥(context)에 의해 형성된다."
여기서 문맥이란, 관심있는 단어 주변에 위치한 다른 단어들을 가리킵니다. 우리도 일상생활에서 어떤 단어를 따로 떼어 보면 모를 때라도, 문맥을 통해 대충 의미를 짐장하는 경우가 많습니다. 이것이 바로 분포가설에 기반한 추론입니다.
인간에게는 거의 무의식적으로 사용하는 익숙한 추론 방법이지만, 이 가설이 바로 생성형 AI 학습의 근간을 이루고 있습니다.
위 식은
ti보다 앞에 있는 토큰 열이 주어졌을 때, ti를 예측합니다.
라는 설정입니다. 이를 분포가설 관점에서 조검 더 좁혀 표현하면,
i-1번째까지의 토큰들이 주어지면, i번째 토큰의 의미는 예측 가능합니다.
정도로 볼 수 있습니다. 간단한 예시를 들어 봅시다.
초보적인 질문인데
라는 텍스트가 왔다고 가정해 봅시다.
그러면, 그 다음에 올 토큰 열은 사과나 양해를 구하는 의미와 관련 있을 것이라 예측할 수 있습니다.
구체적인 토큰 열로는,
죄송하지만,
죄송합니다
와 같은 표현이 올 확률이 높다고 할 수 있습니다.
이런 예측이 가능한 이유는 이런 표현이 실제로 굉장히 자주 사용되기 때문입니다.
그래서 "초보적인 질문이지만"이라는 표현만으로도 그 뒤에 이어질 토큰 열의 후보를 상당히 좁힐 수 있게 되는 것입니다. 여기에 문맥을 더 추가해, 예를 들어, "학회나 연구 발표 자리에서 쓰이는 표현"이라는 정보까지 알 수 있다면,
"초보적인 질문인데" 다음에는 "죄송하지만"이 정형화된 표현으로 자주 쓰입니다.
이라는 점을 반영해, 이 표현의 예측확률을 더 높게 줄 수 있습니다.
연습문제2: 비슷한 문맥에서 쓰이지만, 의미는 서로 다른 단어의 예를 생각해 보고, 그 예와 분포가설 관계를 스스로 분석해 봅시다.
이 분포가설은 원논문에서 자주 인용되는 것은 아래 논문입니다.
Contextual correlates of synonymy (1965/10/01)
이 논문에서 제시하려는 가설은 다음과 같은 표현이 있습니다.
the proportion of words common to the contexts of word A and to the contexts of word B is a function of the degree to which A and B are similar in meaning.
(단어 A의 문맥과 단어 B의 문맥에 공통적으로 등장하는 단어의 비율은, A와 B가 얼마나 의미적으로 유사한지의 함수이다.)
여기서 문맥(context)이 정확히 무엇을 의미하는지는 아직 정의되지 않았지만, 원 논문에서는 문맥의 정의를 여러 방식으로 두고 실험을 진행합니다.
이 가설은 갑자기 하늘에서 뚝 떨어진 것이 아니라 이전에 있었던 선행 연구에서
“단어 A와 B가 서로 치환 가능하다(interchangeable)”는 것은, 제3의 단어 X와의 공기(co-occurrence)가 A에서도, B에서도 모두 많이 나타나는 경우다
라는 추측이 제기된 것에서 출발합니다.
간단한 예로,
The U.S. Army launches rocket missiles while the U.S. Navy launches jet missiles; however, although the Navy flies jet planes, strangely it is not the case that the Army flies rocket planes.
라는 문장이 있다고 하자,
여기서 Army뒤에 오는 단어들을 보면, launches와 files가 함꼐 공기하고 있고 이 둘은 문맥상 꽤 높은 치환 가능성(동등성)을 가진다고 볼 수 있습니다.
Rubenstein & Goodenough의 논문은 이 선행 연구에서 제기된 관점을 크게 벗어나지 않으면서도, 좀 더 정량적으로 판단할 수 있도록 실험을 설계하고 검증했다는 점에서 큰 의미가 있습니다.
이제 원논문의 실험 설계를 살펴봅시다.
핵심이 되는 부분은
주목하고 싶은 단어 A와 B의 유사도를 정량적으로 표현하는 것
그 단어들을 포함하는 문장들을 만들어, 문맥을 정의하고 이를 이용해 유사도의 관계를 밝히는 것
입니다.
먼저, 유사도를 조사할 대상이 되는 "테마 단어(theme words)"쌍을 준비합니다. 테마 단어란 실험 대상이 되는 단어로, 아래 표처럼 A그룹과 B그룹에 각각 24개씩 총 48개 단어가 준비되어 있습니다.
원 논문에는 이 테마단어를 어떻게 선정했는지 구체적인 언급은 없지만, 예를 들어, car와 automobile처럼 양쪽 그룹에 서로 비슷한 단어가 포함되어 있다는 것이 눈에 띕니다.
테마 단어 쌍을 만들 때는,
A그룹에서 1개
B그룹에서 1개
를 복원 추출로 뽑아, 총 65쌍의 단어 쌍을 만듭니다.
유사도의 정량적 평가는 다음 절차로 이루어집니다.
15명과 36명으로 구성된 두 개의 대학생 피험자 그룹을 모집한다(유료 참여)
만들어 둔 65개 테마 단어 쌍을 보여주고, 의미적으로 비슷하다고 느끼는 순서대로 정렬하게 한다
각 쌍에 대해 유사도를 [0.0, 4.0]범위의 값으로 매기게 한다. 값이 높을수록 유사도가 높다는 의미이며, 서로 다른 쌍에 같은 점수를 줘도 된다
각 그룹별로, 각 쌍에 대한 유사도 점수의 평균을 계산하고 두 그룹의 평가 결과 사이의 상관계수를 구해보면 r=0.99가 나옵니다.
이로부터, "두 그룹 사이에 유사도 평가의 차이가 거의 없다."라고 볼 수 있고, 51명 전체 평가를 묶어 평균한 값을 최종적으로 단어A와 B의 유사도로 사용합니다. 그 결과는 아래 표로 정리됩니다.
cord와 smile이 별로 비슷하지 않고, gem과 jewel이 매우 비슷하다고 나오는등, 인간이 직관적으로 느끼는 것과 크게 어긋나지 않는 결과를 정량적인 수치로 얻었다고 볼 수 있습니다.
"어떤 단어들이 비슷한가?"라는 문제는 결국 인간의 판단이 기준이 될 수 밖에 없기 때문에, 사람을 적절히 모으고, 잘 설계된 절차로 평가받음으로써, 수치화된 결과를 얻었다는 점이 중요합니다.
다음으로 '문맥(context)'을 구성하기 위해 이 테마 단어들을 포함하는 문장을 준비합니다. 아직 문맥을 정확히 어떻게 정의할지는 정하지 않았지만, 테마 단어가 포함된 문장에서 문맥을 정의가능한 여러 방법 중 하나를 택하는 방식입니다.
문장 생성 절차는 다음과 같습니다.
유사도 평가에 참여하지 않은 100명의 대학생 피험자 그룹을 새로 모집한다.
이들을 50명씩 두 그룹으로 나누고, 각 그룹에게 A그룹과 B그룹에 있는 모든 테마 단어 각각에 대해 두 개씩 문장을 작성하도록 한다.
문장을 쓸때의 조건은 다음 2가지이다.
테마 단어는 명사로 사용할 것
문장은 최소 10단어 이상으로 구성할 것
이렇게 해서, 48개의 테마 단어 각각에 대해 총 100개의 문장을 얻습니다.
오늘날이라면 웹상의 대규모 텍스트 코퍼스에서 쉽게 뽑아낼 수 있을 법한 데이터를 당시에는 학생들에게 직접 작문을 시켜 만들고 있다는 점에서 시대적 분위기가 느껴집니다.
이제 실험에 필요한 데이터는 모두 준비되었습니다.
문맥을 구체적으로 정의하고,
문맥이 얼마나 비슷한지 정략적으로 측정하는 방법을 정한 뒤, "문맥의 유사도가 단어A와 B의 의미적 유사도를 반영한다"
는 가설을 검증합니다.
문맥의 정의는 다음과 같이 둡니다.
"주목하는 테마단어를 포함한 단어에 등장하는 모든 단어들의 집합"
원 논문에서는 이 밖에도 다른 정의들을 제안하고 비교하지만, 정량적 관점에서 큰 차이가 없으므로, 여기서는 생략합니다. 결국 데이터로부터 직접 얻을 수 있는 것은 문장 안에 등장하는 단어들뿐이기 때문에 가장 단순하게 모든 단어를 고려하는 정의를 사용하는 셈입니다.
이제 문맥을 정의했으니, 문맥 유사도를 다음과 같이 정의합니다.
여기서 각 기호는 다음과 같은 의미를 가집니다. 조건부의 차이는 있지만 핵심만 보면
"테마 단어 A와 B를 포함하는 문장들에서 등장하는 단어들 중 얼마나 많은 단어가 공통적으로 나타나는지"
를 비율로 측정하는 개념입니다.
SA: 테마 단어 A에 대해 수집된 모든 문맥입니다. 즉, A를 포함하는 문장들에서 사용된 단어 전체의 집합이며, 중복 제거는 하지 않습니다.
Ax: SA의 부분집합으로 조건 x에 의해 필터링된 것입니다.
- type 조건(x = y): SA에 등장하는 단어들의 중복제거한 집합
- token 조건(x = k): 단어의 중복을 제거하지 않고 그대로 두는 집합
count(): 집합(혹은 멀티셋)의 원소갯수를 세는 함수
연습문제3: 다음이 주어졌을 때,
각 테마 단어 쌍 A, B에 대해 위에서 정의한 Mx와 앞서 구한 의미 유사도 점수를 함께 플롯한 것이 아래 그림입니다. 이 그림은 "어떤 단어 A와 B의 문맥 유사도는 A와 B의 의미적 유사도의 3차 함수로 표현될 수 있다"라는 것을 보여줍니다.
단어 유사도가 3.0이상인 경우에는 두 값 사이의 상관관계가 뚜렷하게 드라나며, 유사도가 낮은 경우에도 어느정도 신뢰할 수 있는 결과를 얻고 있습니다.
원 논문에서는 단어 유사도 진정한 비율척도(ratio scale)로 표현할 수 있는지는 불명확하지만, 피험자들의 판단이 일관성 있게 유지되고 있다고 서술합니다.
또한 이외에도 다양한 분석이 이루어져 있지만, 이 강좌에서는 가장 깊게 파고들고 싶었던 부분은 여기까지입니다. 이 결과는 "어떤 단어의 문맥을 알면 그 단어의 의미를 예측할 수 있다"라는 점을 시사하며, 생성형 AI에서도 핵심적인 역할을 하고 있습니다.
이 논문은 1965년에 발표된 오래된 논문이지만 분포가설이 실제로 어떠헥 성립하는지를 정량적으로 보여준 기념비적인 연구로 지금 다시 읽어도 깊이가 있는 작업입니다.
연습문제4: 원논문을 직접 읽고, 문맥에 대한 다른 정의들이 어떤 것들이 있는지 정리한 뒤, 그 정의들을 사용했을 때의 결과도 함께 확인해 봅시다.
©2024-2025 MDRULES.dev, Hand-crafted & made with Jaewoo Kim.
AI 에이전트 개발, 컨텍스트 엔지니어링 교육 컨설팅, 바이브코딩 강의 문의: https://bit.ly/4kjk5OB