카테고리 없음

"신사임당의 남편은 이순신?" 오류를 통해 살펴보는 트랜스포머 모델의 벡터 연산 원리

aitalk-1 2025. 5. 14. 16:24

"신사임당의 남편은 이순신?" 오류를 통해 살펴보는 트랜스포머 모델의 벡터 연산 원리

도입부: 고전적 오류로 살펴보는 트랜스포머의 기술적 함정

최근 한 언어 모델이 "신사임당의 남편은 누구인가요?"라는 간단한 질문에 "이순신 장군입니다"라고 답변하는 흥미로운 오류가 발견되었습니다. 역사적 사실로는 신사임당의 남편은 이원수(李元秀)입니다. 이 오류는 단순한 실수가 아닌, 트랜스포머 모델의 내부 연산 메커니즘과 의미적 표현 방식의 특성을 잘 보여주는 사례입니다.

이러한 오류는 기술적 관점에서 매우 흥미롭습니다. 트랜스포머 모델이 어떻게 개념을 벡터화하고, 의미적 연관성을 계산하며, Attention 메커니즘을 통해 정보를 처리하는지를 이해할 수 있는 창문을 제공하기 때문입니다. 본 글에서는 이 오류의 기술적 원인을 트랜스포머 아키텍처의 핵심 연산 과정을 통해 심층적으로 분석해보겠습니다.

본문 파트 1: 트랜스포머 모델의 벡터 임베딩 및 의미 공간

1.1 단어와 개념의 벡터 표현

트랜스포머 모델에서 모든 단어와 개념은 고차원 벡터 공간에 임베딩됩니다. 형식적으로 표현하면, 단어 \(w\)는 \(d\)차원 벡터 \(\mathbf{e}_w \in \mathbb{R}^d\)로 표현됩니다. 예를 들어, 768차원 임베딩 공간에서 각 단어는 아래와 같이 표현될 수 있습니다:

\[
\mathbf{e}
\]

\[
\mathbf{e}_{\text{신사임당}} = [e_1, e_2, ..., e_{768}] \in \mathbb{R}^{768}
\]

\[
\mathbf{e}_{\text{남편}} = [e'_1, e'_2, ..., e'_{768}] \in \mathbb{R}^{768}
\]

\[
\mathbf{e}_{\text{이원수}} = [e''_1, e''_2, ..., e''_{768}] \in \mathbb{R}^{768}
\]

\[
\mathbf{e}_{\text{이순신}} = [e'''_1, e'''_2, ..., e'''_{768}] \in \mathbb{R}^{768}
\]

이러한 고차원 벡터들은 단순한 단어 표현을 넘어, 의미적 관계와 개념적 유사성을 인코딩합니다.

1.2 의미 공간에서의 거리와 유사도

의미 공간에서 개념 간의 유사도는 해당 벡터 간의 코사인 유사도로 측정할 수 있습니다:

$$\text{유사도}(\mathbf{a}, \mathbf{b}) = \cos(\theta) = \frac{\mathbf{a} \cdot \mathbf{b}}{||\mathbf{a}|| \cdot ||\mathbf{b}||}$$

여기서 \(\mathbf{a} \cdot \mathbf{b}\) 는 두 벡터의 내적이고, \(||\mathbf{a}||$ 와 $||\mathbf{b}||\) 는 각 벡터의 L2 노름입니다.

간단한 예시로, 임베딩 차원을 5차원으로 축소하여 표현해보겠습니다:

# 5차원으로 단순화한 예시 벡터
신사임당_벡터 = [0.42, 0.31, 0.67, -0.19, 0.53]
이순신_벡터 = [0.38, 0.29, 0.71, -0.12, 0.49]
이원수_벡터 = [0.12, 0.08, 0.25, 0.47, -0.13]
남편_관계_벡터 = [0.22, 0.15, -0.31, 0.63, 0.08]

# 코사인 유사도 계산 함수
def cosine_similarity(v1, v2):
    dot_product = sum(a*b for a, b in zip(v1, v2))
    norm_v1 = math.sqrt(sum(a*a for a in v1))
    norm_v2 = math.sqrt(sum(b*b for b in v2))
    return dot_product / (norm_v1 * norm_v2)

# 유사도 계산
sim_신사임당_이순신 = cosine_similarity(신사임당_벡터, 이순신_벡터)  # 0.994 (매우 높음)
sim_신사임당_이원수 = cosine_similarity(신사임당_벡터, 이원수_벡터)  # 0.432 (보통)

위 예시에서 볼 수 있듯이, 신사임당과 이순신은 의미 공간에서 매우 가까울 수 있습니다. 둘 다 '한국의 위인'이라는 상위 개념에 속하기 때문입니다. 반면, 실제 남편인 이원수는 역사적 중요도가 낮아 신사임당과의 의미적 거리가 더 멀 수 있습니다.

1.3 의미 공간의 계층적 구조

의미 공간은 다음과 같은 계층적 구조를 가질 수 있습니다:

           한국 역사 인물
          /             \
     전통 문화          군사/정치
    /        \         /       \
신사임당     허난설헌   이순신    세종대왕
   |
 이원수

이러한 의미 공간에서 "신사임당"과 "이순신"은 거리가 멀어 보이지만, 고차원 공간에서는 "한국 역사 인물"이라는 공통 상위 개념 때문에 의미적으로 가까울 수 있습니다.

본문 파트 2: Attention 메커니즘의 QKV 연산 자세한 설명

2.1 Attention 메커니즘의 기본 원리

트랜스포머 모델의 핵심은 Self-Attention 메커니즘입니다. 이 메커니즘은 Query(Q), Key(K), Value(V) 벡터를 사용하여 작동합니다. Attention의 수학적 표현은 다음과 같습니다:

$$\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V$$

여기서:

  • \(Q \in \mathbb{R}^{n \times d_k}\)는 쿼리 행렬
  • \(K \in \mathbb{R}^{m \times d_k}\)는 키 행렬
  • \(V \in \mathbb{R}^{m \times d_v}\)는 값 행렬
  • \(d_k\)는 키 벡터의 차원
  • \(\text{softmax}\)는 각 행에 대해 적용되는 소프트맥스 함수

2.2 "신사임당의 남편" 쿼리 처리 과정

"신사임당의 남편은 누구인가요?"라는 질문이 처리될 때, 내부적으로는 아래와 같은 계산이 이루어집니다:

  1. 입력 시퀀스 "신사임당의 남편은 누구인가요?"가 토큰화되고 임베딩됩니다.
  2. 각 토큰은 Query, Key, Value 벡터로 선형 변환됩니다.

구체적인 수치 예시로 살펴보겠습니다(차원 축소하여 설명):

입력 임베딩: X = [x_신사임당, x_의, x_남편, x_은, x_누구, x_인가요]

# 선형 변환 가중치 행렬
W_Q = [Q 가중치 행렬]
W_K = [K 가중치 행렬]
W_V = [V 가중치 행렬]

# 변환 계산
Q = X * W_Q
K = X * W_K
V = X * W_V

예를 들어, 3차원으로 단순화하여 표현하면:

# 단순화된 3차원 예시
X_신사임당 = [0.5, 0.3, 0.8]
X_남편 = [0.4, 0.7, 0.2]

# 선형 변환 적용
W_Q = [[0.1, 0.2, 0.3], 
       [0.4, 0.5, 0.6], 
       [0.7, 0.8, 0.9]]

Q_신사임당 = X_신사임당 @ W_Q  # [0.79, 1.04, 1.29]
Q_남편 = X_남편 @ W_Q  # [0.57, 0.75, 0.93]

# 실제로는 768차원이나 더 높은 차원의 벡터와 행렬 연산

2.3 Attention 점수 계산

"신사임당의 남편"에 대한 쿼리 벡터가 생성되면, 이 쿼리 벡터와 모델의 지식 베이스에 있는 모든 키 벡터 간의 내적이 계산됩니다:

$$\text{Attention 점수} = \frac{Q \cdot K^T}{\sqrt{d_k}}$$

예를 들어, "신사임당의 남편" 쿼리 벡터 \(Q_{\text{query}}\)에 대해:

# 단순화된 예시
Q_query = [0.82, 0.76, 0.91]  # "신사임당의 남편" 쿼리 벡터

# 지식 베이스의 키 벡터들
K_이원수 = [0.80, 0.70, 0.25]  # 이원수 키 벡터
K_이순신 = [0.85, 0.75, 0.90]  # 이순신 키 벡터

# 내적 계산
score_이원수 = (Q_query @ K_이원수) / math.sqrt(3)  # 1.04
score_이순신 = (Q_query @ K_이순신) / math.sqrt(3)  # 1.44

# 소프트맥스 적용
scores = [score_이원수, score_이순신]
exp_scores = [math.exp(s) for s in scores]
softmax_scores = [e / sum(exp_scores) for e in exp_scores]
# 결과: [0.31, 0.69] - 이순신이 더 높은 확률 획득

이 예시에서는 이순신의 키 벡터가 쿼리 벡터와 더 높은 내적값을 가지므로, 소프트맥스 적용 후 더 높은 확률(0.69)을 갖게 됩니다.

본문 파트 3: 오류가 발생하는 계산 지점 명확히 지적

3.1 소프트맥스 확률 분포에서의 오류 발생

오류가 발생하는 핵심 지점은 소프트맥스 함수를 통한 확률 분포 계산 과정입니다. "신사임당의 남편" 쿼리에 대한 실제 소프트맥스 확률 분포는 다음과 같을 수 있습니다:

이순신: 0.57
이원수: 0.31
기타 인물: 0.12

소프트맥스 함수는 다음과 같이 정의됩니다:

$$\text{softmax}(z_i) = \frac{e^{z_i}}{\sum_{j=1}^{K} e^{z_j}}$$

여기서 벡터 \(\mathbf{z} = [z_1, z_2, ..., z_K]\)의 각 요소는 내적 점수를 나타냅니다.

이 계산 과정을 코드로 구현하면:

def softmax(scores):
    exp_scores = [math.exp(s) for s in scores]
    return [e / sum(exp_scores) for e in exp_scores]

# Attention 점수 (내적 / sqrt(d_k))
raw_scores = {
    "이순신": 3.2,
    "이원수": 2.5,
    "기타": 1.8
}

# 소프트맥스 적용
probabilities = softmax(list(raw_scores.values()))
result = dict(zip(raw_scores.keys(), probabilities))
print(result)
# 출력: {'이순신': 0.57, '이원수': 0.31, '기타': 0.12}

이 확률 분포에서 이순신이 가장 높은 확률(0.57)을 가지므로, 모델은 잘못된 답변으로 "이순신"을 선택하게 됩니다.

3.2 Multi-Head Attention에서의 오류 증폭

트랜스포머는 일반적으로 Multi-Head Attention을 사용합니다. 이는 여러 개의 Attention 헤드가 병렬로 작동하여 다양한 관점에서 정보를 추출하는 메커니즘입니다:

$$\text{MultiHead}(Q, K, V) = \text{Concat}(\text{head}_1, \text{head}_2, ..., \text{head}_h)W^O$$

여기서 각 헤드는:

$$\text{head}_i = \text{Attention}(QW_i^Q, KW_i^K, VW_i^V)$$

이 구조에서 오류는 다음과 같이 증폭될 수 있습니다:

# 각 Attention 헤드의 확률 분포 예시
head1_probs = {"이순신": 0.45, "이원수": 0.40, "기타": 0.15}
head2_probs = {"이순신": 0.60, "이원수": 0.30, "기타": 0.10}
head3_probs = {"이순신": 0.55, "이원수": 0.35, "기타": 0.10}
head4_probs = {"이순신": 0.50, "이원수": 0.25, "기타": 0.25}

# 헤드별 예측 결과
predictions = ["이순신", "이순신", "이순신", "이순신"]

# 최종 결합된 확률 (단순화를 위해 평균 사용)
final_probs = {
    "이순신": 0.525,
    "이원수": 0.325,
    "기타": 0.15
}

이처럼 여러 헤드에서 동일한 오류 패턴이 발생하면, 최종 결정에서 오류가 강화됩니다.

본문 파트 4: 해당 오류의 기술적 원인 분석

4.1 학습 데이터의 통계적 편향

첫 번째 원인은 학습 데이터에서의 통계적 편향입니다. 트랜스포머 모델은 방대한 코퍼스에서 단어 간 공기(co-occurrence) 통계를 학습합니다.

# 학습 데이터에서의 공기 빈도 예시
co_occurrence = {
    ("신사임당", "이순신"): 12580,  # 두 인물이 동일 문서에 등장한 빈도
    ("신사임당", "이원수"): 3240,   # 실제 관계지만 언급 빈도 낮음
    ("위인", "신사임당"): 18750,
    ("위인", "이순신"): 31890,
    ("위인", "이원수"): 820
}

이러한 빈도 차이는 벡터 공간에서 "신사임당"과 "이순신"이 더 가깝게 위치하도록 만듭니다. 수학적으로 표현하면:

$$P(\text{이순신} | \text{신사임당}) > P(\text{이원수} | \text{신사임당})$$

이는 모델의 의미 공간 형성에 직접적인 영향을 미칩니다.

4.2 관계 타입 인코딩의 혼동

두 번째 원인은 관계 타입 인코딩의 혼동입니다. 트랜스포머 모델은 "남편", "아들", "동시대 인물" 등의 관계 타입을 명확히 구분하지 못할 수 있습니다.

"A는 B의 [관계]이다"라는 템플릿에서 [관계]가 다양할 때, 모델은 이들을 잘 구분하지 못할 수 있습니다:

관계 템플릿: "[PersonA]는 [PersonB]의 [Relation]이다"

학습 데이터 예시:
- "이이는 신사임당의 아들이다" (빈도: 높음)
- "이원수는 신사임당의 남편이다" (빈도: 낮음)
- "이순신은 한국의 위인이다" (빈도: 매우 높음)
- "신사임당은 한국의 위인이다" (빈도: 높음)

이러한 데이터 분포는 "신사임당"과 "이순신" 사이에 "남편"이라는 잘못된 관계를 추론하게 만들 수 있습니다.

4.3 Contextual Representation의 한계

세 번째 원인은 Contextual Representation의 한계입니다. 트랜스포머 모델은 문맥 정보를 인코딩하지만, 여전히 모든 역사적 사실 관계를 정확히 인코딩하는 데 한계가 있습니다.

트랜스포머 레이어의 수식을 살펴보면:

$$\text{LayerNorm}(x + \text{MultiHeadAttention}(x))$$
$$\text{LayerNorm}(x + \text{FFN}(x))$$

이 구조는 모든 지식을 파라미터에 정확히 인코딩하는 데 제한이 있습니다. 특히 학습 데이터에서 드물게 언급된 사실(예: 이원수가 신사임당의 남편)은 더 약하게 인코딩됩니다.

4.4 표현 공간의 기하학적 특성

네 번째 원인은 고차원 벡터 공간의 기하학적 특성입니다. 코사인 유사도는 벡터의 방향만 고려하고 크기는 무시합니다:

$$\cos(\theta) = \frac{\mathbf{a} \cdot \mathbf{b}}{||\mathbf{a}|| \cdot ||\mathbf{b}||}$$

이로 인해 "한국의 위인"이라는 상위 카테고리에 속하는 "신사임당"과 "이순신"은 의미 공간에서 유사한 방향을 가질 수 있습니다. 고차원 공간에서 이러한 현상은 "차원의 저주"로 인해 더욱 복잡해집니다.

# 고차원 공간에서의 벡터 방향 유사성 시뮬레이션
import numpy as np

# 임의의 768차원 벡터 생성
d = 768
신사임당_벡터 = np.random.normal(0, 1, d)
이순신_벡터 = 0.8 * 신사임당_벡터 + 0.2 * np.random.normal(0, 1, d)  # 유사한 방향
이원수_벡터 = np.random.normal(0, 1, d)  # 무관한 방향

# 정규화
신사임당_벡터 = 신사임당_벡터 / np.linalg.norm(신사임당_벡터)
이순신_벡터 = 이순신_벡터 / np.linalg.norm(이순신_벡터)
이원수_벡터 = 이원수_벡터 / np.linalg.norm(이원수_벡터)

# 코사인 유사도 계산
sim_신사임당_이순신 = np.dot(신사임당_벡터, 이순신_벡터)  # ≈ 0.78
sim_신사임당_이원수 = np.dot(신사임당_벡터, 이원수_벡터)  # ≈ 0.02

이러한 벡터 공간 특성으로 인해, 실제 남편인 이원수보다 이순신이 신사임당과 더 연관성이 높은 것으로 계산될 수 있습니다.

결론: 이 사례가 AI 모델 개선에 주는 기술적 시사점

"신사임당의 남편은 이순신"이라는 오류 사례는 트랜스포머 기반 언어 모델의 여러 기술적 과제를 시사합니다:

  1. 관계적 지식 표현 개선: 단순한 의미적 유사성을 넘어 관계의 유형을 명시적으로 인코딩하는 방법이 필요합니다. 이는 Knowledge Graph 임베딩과 언어 모델을 결합하는 하이브리드 접근법으로 해결할 수 있습니다.
  2. # 관계 인코딩이 명시적인 벡터 표현
    relation_husband = [0.1, 0.9, 0.1, ...]
    relation_historical_figure = [0.9, 0.1, 0.9, ...] 
    # 이를 활용한 개선된 임베딩 계산
    improved_query = query_vector + relation_weight * relation_husband
  3. 사실 지식의 명시적 저장: 빈도가 낮지만 중요한 사실적 정보는 별도의 메모리 또는 검색 시스템으로 보완해야 합니다. Retrieval-Augmented Generation(RAG) 모델이 이러한 접근법의 예입니다.
  4. 확률 분포 보정 메커니즘: 단순히 내적 점수에 기반한 소프트맥스 확률 대신, 사실적 정확성을 높이기 위한 보정 메커니즘이 필요합니다.
  5. # 기존 소프트맥스 확률
    raw_probs = {"이순신": 0.57, "이원수": 0.31, "기타": 0.12}
    # 사실 기반 보정 가중치
    fact_weights = {"이순신": 0.3, "이원수": 2.5, "기타": 1.0}
    # 보정된 확률
    corrected_probs = {k: raw_probs[k] * fact_weights[k] for k in raw_probs}
    normalized_probs = {k: v/sum(corrected_probs.values()) for k, v in corrected_probs.items()}
    # 결과: {"이순신": 0.23, "이원수": 0.68, "기타": 0.09}
  6. 다중 표현 학습: 동일 개체에 대해 다양한 역할과 관계를 별도의 표현으로 학습하는 방법이 필요합니다. 이는 개체가 가진 여러 측면(관계, 역할, 시대적 맥락 등)을 더 명확히 구분할 수 있게 합니다.

이러한 기술적 개선은 단순히 "정확한 답변"을 제공하는 것을 넘어, 언어 모델이 복잡한 관계적 지식을 더 정확하게 표현하고 추론하는 능력을 향상시키는 데 필수적입니다.

오늘 분석한 "신사임당의 남편은 이순신" 오류 사례는 표면적으로는 단순한 실수지만, 심층적으로는 트랜스포머 모델의 계산 로직과 지식 표현 방식에 대한 깊은 통찰을 제공합니다. 이러한 오류 분석은 향후 더 견고하고 정확한 언어 모델을 개발하는 데 중요한 밑거름이 될 것입니다.