-
단어의 의미를 벡터로, Word2VecAI 2026. 2. 21. 11:27
인간의 언어를 컴퓨터가 이해하게 만드는 기술, 자연어 처리(NLP)의 근간이 되는 Word2Vec에 대해 심층적으로 알아보겠습니다.
배경: 왜 단어를 '좌표'로 만들어야 할까?
컴퓨터는 텍스트를 직접 이해할 수 없습니다. 따라서 숫자로 변환하는 과정이 필요한데, 과거에는 원-핫 인코딩(One-hot Encoding)을 사용했습니다.
- 원-핫 인코딩의 문제점:
- 차원의 저주: 단어가 10,000개라면 단어 하나를 표현하는 데 10,000차원의 벡터가 필요합니다.
- 의미 부재: 모든 단어 벡터 간의 내적이 0입니다. 즉, '강아지'와 '멍멍이'가 수학적으로 아무런 상관이 없는 단어가 됩니다.
- 희소성(Sparsity) 문제: 원-핫 벡터는 단 하나의 값만 1이고 나머지는 모두 0으로 채워집니다. 이로 인해 벡터 공간의 대부분이 '비어 있는' 상태가 되며, 이는 데이터의 낭비일 뿐만 아니라 단어 간의 관계를 전혀 담지 못하는 결과를 초래합니다.
- 희소 문제(Sparsity Problem): 현실에서는 충분히 가능한 문장이라도, 학습 데이터(말뭉치)에 없다는 이유만으로 그 확률을 0으로 판단
이런 문제를 해결하기 위해 등장한 것이 바로 단어 임베딩(Word Embedding)입니다. 단어를 저차원의 실수 공간에 '좌표'로 배치하여, 비슷한 의미의 단어들이 서로 가깝게 모이도록 만드는 것이 핵심입니다.이런 표현 방법을 사용하면 단어 벡터 간 유의미한 유사도를 계산할수있습니다.
Preprocessing: 단어장과 가중치 행렬의 완벽한 맵핑
1. 단어장(Vocabulary)은 '지도'다
학습을 시작하기 전, 데이터셋에 있는 모든 고유 단어를 모아 "몇 번 단어인지" 주소를 배정하는 작업이 선행되어야 합니다. indexing
- The → 0번, fat → 1번, cat → 2번...
- 이 지도가 없으면 가중치 행렬에서 값을 꺼내올 방법이 없습니다.
2. 가중치 행렬은 '저장소'다
단어장의 크기가 $V$이고 임베딩 차원이 $M$이라면, 우리는 $(V \times M)$ 크기의 거대한 빈 방(행렬)을 만듭니다.
- 처음에는 랜덤한 숫자로 채워져 있지만, 학습이 진행될수록 단어장의 각 번호에 해당하는 행(Row)들이 그 단어의 진짜 의미를 담은 숫자로 깎여 나갑니다.
3. '위치'가 곧 '의미'다
사용자님이 말씀하신 대로 "단어장의 위치 = 가중치 행렬의 행 번호"라는 약속이 핵심입니다.
- 추론할 때는 이 약속에 따라 인덱스 번호만 보고 값을 슥 꺼내오면 끝나는 거죠.
- 학습의 본질: "사전의 3번에 있는 sat이라는 단어의 벡터값을 주변 단어들과 어울리도록 계속 수정해라!"라고 명령하는 과정입니다.
Word2Vec의 성공 비결은 단순함에 있습니다. 모든 단어에 고유 번호(indexing)를 매기고(단어장), 그 번호에 대응하는 전용 공간(가중치 행렬의 행)을 할당한 뒤, 오직 그 공간의 숫자들만 집중적으로 훈련시켜 '단어의 주소록'을 완성하는 것이 이 알고리즘의 정수입니다
이제 학습을 해서 embedding을 어떻게 만들어 가는지 알아보겠습니다.
CBOW 방식 (주변어들로 중심어 맞추기)
Word2Vec의 학습 방식에는 CBOW(Continuous Bag of Words)와 Skip-Gram 두 가지 방식이 있습니다. CBOW는 주변에 있는 단어들을 입력으로 중간에 있는 단어들을 예측하는 방법입니다. 반대로, Skip-Gram은 중간에 있는 단어들을 입력으로 주변 단어들을 예측하는 방법입니다.
- 슬라이딩 윈도우(Sliding Window): 학습 데이터를 만드는 방식입니다. 윈도우 크기(Window Size)가 2라면, 중심 단어 앞뒤로 2개씩 총 4개의 주변 단어를 학습에 사용합니다. 이 윈도우를 한 칸씩 옆으로 밀면서 모든 단어를 한 번씩 중심 단어로 설정하며 데이터를 생성합니다.
- 중심 단어(Target Word): 모델이 맞춰야 하는 정답 단어입니다.
- 주변 단어(Context Words): 예측을 위해 입력값으로 사용되는 주변 단어들입니다.
컴퓨터는 문장을 읽을 때 한 번에 다 보는 게 아니라, 정해진 크기의 '창문(Window)'을 통해 봅니다. 이 창문의 정중앙에 위치한 단어가 항상 '중심 단어'가 되고, 나머지 단어들이 '주변 단어'가 됩니다.
예시 문장: "The fat cat sat on the mat"
윈도우 크기가 2라는 것은 중심 단어 앞뒤로 2개씩, 총 4개의 주변어를 보겠다는 뜻
중심 단어가 sat이라고 한다면 앞의 두 단어인 fat와 cat, 그리고 뒤의 두 단어인 on, the를 입력으로 사용합니다. 윈도우 크기가 n이라고 한다면, 실제 중심 단어를 예측하기 위해 참고하려고 하는 주변 단어의 개수는 2n
Word2Vec에서 입력은 모두 원-핫 벡터가 되어야 하는데, 우측 그림은 중심 단어와 주변 단어를 어떻게 선택했을 때에 따라서 각각 어떤 원-핫 벡터가 되는지를 보여줍니다.

입력층(Input layer)의 입력으로서 앞, 뒤로 사용자가 정한 윈도우 크기 범위 안에 있는 주변 단어들의 원-핫 벡터가 들어가게 되고, 출력층(Output layer)에서 예측하고자 하는 중간 단어의 원-핫 벡터가 레이블이 필요합니다.
입력층 (Input Layer)
모델이 학습할 주변 단어들의 원-핫 벡터가 처음으로 들어오는 지점이고, 가중치 $W$와 곱해지기 전, 가장 먼저 만나는 층입니다
- 단어장의 크기($V$)와 동일한 차원을 가진 벡터입니다.
- 전처리 단계에서 생성한 원-핫 인코딩 결과값이 위치합니다.
- 약 윈도우 크기가 2라면, 중심 단어를 맞히기 위해 좌우 2개씩 총 4개의 원-핫 벡터가 입력층을 통해 들어옵니다.
- 이 벡터들은 각각 가중치 $W$와 곱해져(룩업 테이블) 단어의 의미를 찾기 위한 여행을 시작합니다.
프로젝션 레이어(Projection Layer, 투사층)
보통의 신경망 은닉층에는 ReLU나 Sigmoid 같은 비선형 활성화 함수가 들어갑니다. 하지만 Word2Vec의 프로젝션 레이어는 활성화 함수가 전혀 없는 단순한 선형 결합 공간입니다.
- 단순 연산: 입력된 벡터에 가중치 행렬($W$)을 곱하기만 할 뿐, 값을 변형하지 않고 그대로 다음 층으로 '투사(Project)'하기 때문에 프로젝션 레이어라는 이름이 붙었습니다.
- 성능 최적화: 활성화 함수가 없어서 연산 속도가 매우 빠르며, 이것이 대량의 텍스트 데이터를 단시간에 학습할 수 있는 비결 중 하나입니다.
CBOW에서 투사층의 크기 M은 임베딩하고 난 벡터의 차원이 됩니다. 만약 투사층의 크기는 M=5 라면, CBOW를 수행하고나서 얻는 각 단어의 임베딩 벡터의 차원은 5가 됩니다.

입력층과 투사층 사이의 가중치 W는 V × M 행렬이며, 투사층에서 출력층사이의 가중치 W'는 M × V 행렬이라는 점입니다.
여기서 V는 단어 집합의 크기를 의미합니다. 즉, 위의 그림처럼 원-핫 벡터의 차원이 7이고, M은 5라면 가중치 W는 7 × 5 행렬이고, W'는 5 × 7 행렬이 될 것입니다. 주의할 점은 이 두 행렬은 동일한 행렬을 전치(transpose)한 것이 아니라, 서로 다른 행렬이라는 점입니다인공 신경망의 훈련 전에 이 가중치 행렬 W와 W'는 랜덤 값을 가지게 됩니다. CBOW는 주변 단어로 중심 단어를 더 정확히 맞추기 위해 계속해서 이 W와 W'를 학습해가는 구조입니다.
입력층 가중치 $W$ (V × M 행렬)
학습 데이터셋(정답지)에서 주변 단어(CBOW 기준)나 중심 단어(Skip-gram 기준)의 원-핫 벡터가 입력으로 들어오면, 이 벡터와 입력 가중치 행렬 $W$가 곱해집니다.
- 수식 표현: $x_{input} \times W = V_{output}$
- 여기서 $x_{input}$이 바로 전처리 단계에서 만든 원-핫 인코딩 벡터입니다.
- 학습이 완료된 후 우리가 최종적으로 추출하여 사용하는 '단어 임베딩 벡터'가 바로 이 $W$의 각 행들입니다.
즉, "내가 누구인가" (정체성), 즉 정 단어 자체가 가진 고유한 의미적 특징을 $M$차원에 담고 있습니다
룩업 테이블(Lookup Table)
수학적으로는 '행렬 곱셈'이지만, 실제 내부 동작은 '선택'에 가깝습니다.
- 원-핫 벡터는 단 한 곳만 1이고 나머지는 모두 0입니다.
- 이 벡터를 가중치 행렬 $W$와 곱하면, 1이 위치한 인덱스에 대응하는 $W$ 행렬의 특정 행(Row)만 결과값으로 남고 나머지는 0이 곱해져 사라집니다.
- 그래서 이 과정을 가중치 행렬에서 값을 꺼내온다는 의미로 룩업 테이블이라 부르는 것입니다.
출력층 가중치 $W'$ (M × V 행렬)
룩업 테이블로 가져온 실수값(임베딩 벡터)은 모델이 생각하는 그 단어의 "의미"일 뿐입니다. 하지만 모델은 이 의미가 실제 정답과 얼마나 일치하는지 확인해야 하죠.
룩업 테이블로 가져온 벡터는 $M$차원(예: 5차원)의 숫자 뭉치입니다. 그런데 우리가 가진 정답지는 $V$차원(예: 7차원)의 원-핫 벡터죠.
- 문제: 5차원 숫자와 7차원 원-핫 벡터는 체급이 달라서 직접 비교가 불가능합니다.
- 해결: 5차원 벡터를 다시 단어장 크기인 7차원 점수로 확장시켜야 합니다. 이때 출력층 가중치($W'$)가 그 확장기 역할을 합니다.

CBOW는 주변에 있는 여러 단어(힌트)를 보고 가운데 단어(정답)를 맞히는 모델입니다.
- 상황: 주변 단어가 4개(The, fat, sat, on)라면, 룩업 테이블을 통해 4개의 서로 다른 임베딩 벡터가 튀어나옵니다.
- 문제: 출력층 가중치($W'$)와 곱해서 점수를 매기려면 입력값은 딱 하나여야 합니다.
- 해결: 그래서 4개의 벡터를 하나로 합치는 '평균(Average)' 연산을 수행하는 것입니다.
이 평균 벡터는 "주변 단어 4개의 의미를 골고루 섞어놓은 요약본"과 같습니다.
- 예시: The, fat, sat, on의 벡터들을 다 더해서 4로 나누면, "이 근처에는 동물이나 앉아 있는 것과 관련된 의미가 흐르고 있구나"라는 종합적인 맥락이 만들어집니다.
- 이 요약된 맥락 벡터를 가지고 $W'$와 곱해서 "그러니까 정답은 cat이겠네!"라고 점수를 매기게 됩니다.
출력가중치는 누구와 잘 어울리는가(맥락적 관계입니다.) 단어가 주변 단어(맥락)로서 예측될 때 사용되는 값입니다.
이 단어가 어떤 상황이나 문맥에서 잘 나타나는지, 즉 주변 단어들과의 관계성 정보가 더 강하게 투영되어 있습니다.이렇게 구해진 평균 벡터는 두번째 가중치 행렬 W'와 곱해집니다. 곱셈의 결과로는 원-핫 벡터들과 차원이 V로 동일한 벡터가 나옵니다. 만약 입력 벡터의 차원이 7이었다면 여기서 나오는 벡터도 마찬가지입니다.

소프트맥스(Softmax)
벡터에 CBOW는 소프트맥스(softmax) 함수를 지나면서 벡터의 각 원소들의 값은 0과 1사이의 실수로, 총 합은 1이 됩니다.
다중 클래스 분류 문제를 위한 일종의 스코어 벡터(score vector)입니다.
스코어 벡터의 j번째 인덱스가 가진 0과 1사이의 값은 j번째 단어가 중심 단어일 확률을 나타냅니다.
그리고 이 스코어 벡터의 값은 레이블에 해당하는 벡터인 중심 단어 원-핫 벡터의 값에 가까워져야 합니다. 스코어 벡터를 라고 하겠습니다. 중심 단어의 원-핫 벡터를 로 했을 때, 이 두 벡터값의 오차를 줄이기위해 CBOW는 손실 함수(loss function)로 크로스 엔트로피(cross-entropy) 함수를 사용합니다.
단어장의 크기가 $V=7$이므로, 모든 벡터의 길이는 7이 됩니다.
- 진짜 정답 ($y$): [0, 0, 0, 1, 0, 0, 0]
- 단어장(The, fat, cat, sat, on, the, mat)에서 4번째인 sat만 1인 원-핫 벡터입니다.
- 모델의 예측 ($\hat{y}$): [0.02, 0.03, 0.15, 0.7, 0.05, 0.02, 0.03]
- 소프트맥스를 통과해 나온 확률 값들로, 전체 합은 1입니다.
크로스 엔트로피(Cross-Entropy): 오차 계산
모델의 답변($\hat{y}$)과 실제 정답($y$)이 얼마나 다른지 계산하는 손실 함수(Loss Function)입니다.
$$cost(\hat{𝑦}, y) = -\sum_{j=1}^{V}y_{j}\ log(\hat{𝑦_{j}})$$
- 정답 단어 ($y_j = 1$): 오직 정답인 단어의 인덱스에서만 값이 계산됩니다.
- 오답 단어 ($y_j = 0$): $0$이 곱해지므로 합계에서 무시됩니다.
- 결과적으로: 모델이 정답 단어에 대해 내놓은 확률($\hat{y_j}$)이 1(100%)에 가까울수록 손실 값은 0에 수렴하고, 확률이 낮을수록 손실 값은 무한대로 커집니다.
$$Loss = -( \underbrace{0 \cdot \log(0.02)}_{The} + \underbrace{0 \cdot \log(0.03)}_{fat} + \underbrace{0 \cdot \log(0.15)}_{cat} + \mathbf{1 \cdot \log(0.7)} + \underbrace{0 \cdot \log(0.05)}_{on} + \underbrace{0 \cdot \log(0.02)}_{the} + \underbrace{0 \cdot \log(0.03)}_{mat} )$$- 오답 소거: 정답이 아닌 다른 6개 단어 위치에서는 실제 정답 값($y_j$)이 0이기 때문에 계산 결과가 모두 0이 되어 사라집니다.
- 정답 집중: 오직 4번째 자리인 sat에서만 $1 \times \log(0.7)$이 살아남아 모델의 성적표를 결정합니다.
- 최종 손실 값: $Loss = -\log(0.7) \approx 0.35$
Back Propagation
역전파(Back Propagation)를 수행하면 W와 W'가 학습이 됩니다. 학습이 다 되었다면, 즉 추론시에 M차원의 크기를 갖는 W의 행렬의 행을 각 단어의 임베딩 벡터로 사용하거나 W와 W' 행렬 두 가지 모두를 가지고 임베딩 벡터를 사용하기도 합니다.
이렇게 임베딩 벡터를 가지고
Skip-gram
CBOW에서는 주변 단어를 통해 중심 단어를 예측했다면, Skip-gram은 중심 단어에서 주변 단어를 예측합니다. 앞서 언급한 예문에 대해서 동일하게 윈도우 크기가 2일 때, 데이터셋은 다음과 같이 구성됩니다.

윈도우 크기가 2일 때, CBOW는 4개의 단어를 묶어서 한 번 학습하지만, Skip-gram은 이를 4개의 개별 문제로 쪼갭니다.
- CBOW: ([fat, cat, on, the], sat) → 문제 1개
- Skip-gram: 1. (sat, fat) 2. (sat, cat) 3. (sat, on) 4. (sat, the)
- 즉, 중심 단어 하나로 주변 단어를 각각 하나씩 맞히는 문제 4개로 변신합니다.
인공 신경망을 도식화해보면 아래와 같습니다.

프로세스의 차이 (Process)
CBOW (다대일)
- 주변 단어 4개를 각각 룩업한다.
- 4개 벡터의 평균을 낸다.
- 그 평균 벡터를 $W'$와 곱해 Softmax를 한 번 돌린다.
- 정답(sat)과 비교해 한 번 업데이트한다.
Skip-gram (일대다)
- 중심 단어(sat) 하나만 룩업한다. (평균 낼 필요 없음)
- 이 벡터를 $W'$와 곱해 Softmax를 돌린다.
- 그런데 여기서 정답지가 4개입니다.
- sat으로 fat을 맞히는 오차 계산
- sat으로 cat을 맞히는 오차 계산
- sat으로 on을 맞히는 오차 계산
- sat으로 the을 맞히는 오차 계산
- 이 4개의 오차를 모두 합산하여 가중치를 업데이트합니다.
- 더 많은 학습 기회: 똑같은 문장을 지나가도 Skip-gram은 윈도우 크기만큼 가중치를 더 자주, 더 많이 흔들어 깨웁니다.
- 희소 단어의 승리: 자주 안 나오는 단어가 중심 단어로 딱 한 번만 등장해도, 주변의 여러 단어와 엮이며 강렬하게 학습됩니다. CBOW는 주변 단어들에 묻혀버릴 수 있지만, Skip-gram은 주인공(중심 단어)이 직접 주변을 지목하기 때문이죠.
Skip-Gram은 입력이 중심 단어 하나이기때문에 투사층에서 벡터들의 평균을 구하는 과정은 없습니다. 여러 논문에서 성능 비교를 진행했을 때 전반적으로 Skip-gram이 CBOW보다 성능이 좋다고 알려져 있습니다.
문제점
OOV(Out-Of-Vocabulary) 문제 (추론 불가능)
- 현상: 학습 데이터에 없던 신조어, 오타, 혹은 고유명사가 들어오면 모델은 이 단어의 인덱스를 찾을 수 없습니다.
- 결과: 인덱스가 없으니 룩업 테이블($W$)에서 꺼내올 '행(Row)'도 없습니다. 즉, 좌표 자체가 존재하지 않아 연산이 불가능합니다.
- 비유: 주소록에 없는 사람에게 편지를 보내려고 하는데, 우체국(모델)이 "그런 주소는 세상에 없어!"라며 수거조차 거부하는 상황입니다.
연산량 문제 (The Computational Burden)
중심 단어 벡터 $v_{sat}$이 들어오면 출력 가중치 행렬 $W'$의 모든 행(단어장 전체 $V$)과 곱합니다.
- 연산: $v_{sat} (1 \times M) \times W' (M \times V)$
- 문제: 단어장이 10만 개($V=100,000$)라면, 단어 하나를 공부할 때마다 10만 번의 내적 연산을 하고, 10만 개의 결과값에 대해 소프트맥스를 계산해야 합니다.
- 라벨: "10만 개 중 몇 번이 정답인가?"라는 거대한 다중 분류 문제입니다.
참고: 이를 해결하기 위한 방법
이런 비효율성을 해결하기 위해 실제 Word2Vec 학습 시에는 모든 단어를 업데이트하지 않는 기법들을 주로 사용합니다:
- 네거티브 샘플링(Negative Sampling): 전체 단어 집합이 아니라, 정답 단어와 무작위로 뽑은 몇 개의 오답 단어(Negative Samples)에 대해서만 가중치를 업데이트합니다. (질문하신 예시를 빌리자면 '강아지', '고양이'와 상관없는 수만 개의 단어 중 아주 일부만 골라 업데이트하는 방식입니다.)
- 계층적 소프트맥스(Hierarchical Softmax): 단어 집합을 이진 트리 형태로 구성하여 연산량을 $V$에서 $\log_2 V$로 줄입니다.
구조적 유연성의 한계 (고정된 창문)
Word2Vec(NNLM)은 다음 단어를 예측할 때 직전의 **정해진 $n$개의 단어(Window)**만을 참고합니다.
- 입력 크기의 고정: 단어 벡터들을 옆으로 길게 붙이는(Concatenate) 방식이라 입력 가중치($Weight$)가 고정됩니다. 문장 길이에 상관없이 처리할 수 있는 유연성이 부족합니다.
- 문맥의 단절: 창문 밖에 있는 정보는 완전히 잊어버리는 '장기 의존성' 문제가 발생합니다. 문장 앞부분의 중요한 맥락이 뒷부분에 전달되지 않는 치명적인 단점이 있습니다.
➡️ 결론: 그래서 RNN(Recurrent Neural Network)이 탄생했습니다
이러한 '고정된 크기'와 '단기 기억'의 한계를 극복하기 위해 등장한 것이 바로 RNN입니다.
RNN은 정보를 옆으로 붙이는 대신 아래와 같은 혁신을 시도했습니다.
- 순환(Recurrent) 구조: 정보를 다음 시점으로 계속 전달하여 문장의 길이에 상관없이 데이터를 처리합니다.
- 문맥 유지: 이전의 정보를 계속해서 다음 단계로 넘겨주며, 끊겼던 문맥의 흐름을 이어가기 시작했습니다.
결국 자연어 처리는 **단어의 의미(Word2Vec)**를 파악하는 단계를 넘어, **문장 전체의 흐름(RNN)**을 이해하는 방향으로 진화하게 된 것입니다.
'AI' 카테고리의 다른 글
FastText (0) 2026.02.22 Word2Vec: Negative Sampling (0) 2026.02.21 텍스트 벡터화(Text Vectorization) (0) 2026.02.20 토큰화(Tokenization)의 진화: 단어에서 서브워드까지 (1) 2026.02.20 텍스트 데이터의 특징과 자연어 처리 파이프라인 완벽 이해 (0) 2026.02.20 - 원-핫 인코딩의 문제점: