이 글은 임베딩 실험 시리즈의 두 번째 글이다.
1편에서는 LLM이 단어와 문장의 의미를 벡터로 표현하고, 문장 간 의미 유사도를 수치로 비교하는 실험을 다루었다.

1편 바로가기: LLM이 단어/문장을 이해하는 방법 – 임베딩과 의미 유사도 실험(1)

 

이번에는 앞서 실험에 사용한 문장 또는 단어 임베딩을 2차원 공간에 시각화하여, 의미적으로 비슷한 문장/단어가 실제로 가까운 위치에 배치되는지 확인해보았다. 

 

1) 사용 임베딩

paraphrase-multilingual-MiniLM-L12-v2 모델을 이용해 다음 5개 문장을 벡터화

 

2) 문장 목록

  1. 오늘은 날씨가 정말 좋다.
  2. 맑은 하늘이 기분을 상쾌하게 해준다.
  3. 고양이는 낮잠을 자고 있다.
  4. 나는 새로운 언어를 배우고 있다.
  5. 자동차가 도로를 달리고 있다.

3) 시각화 방식 

  • 벡터 차원: 384차원 → PCA로 2차원 축소
  • 시각화 도구: matplotlib, sklearn.decomposition.PCA

4) PCA 시각화

-  PCA 시각화 사용 코드

from sentence_transformers import SentenceTransformer
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
import platform

# 한글 폰트 설정
if platform.system() == 'Windows':
    plt.rc('font', family='Malgun Gothic')
elif platform.system() == 'Darwin':
    plt.rc('font', family='AppleGothic')
else:
    plt.rc('font', family='NanumGothic')
plt.rcParams['axes.unicode_minus'] = False

# 문장 목록
sentences = [
    "오늘은 날씨가 정말 좋다.",
    "맑은 하늘이 기분을 상쾌하게 해준다.",
    "고양이는 낮잠을 자고 있다.",
    "나는 새로운 언어를 배우고 있다.",
    "자동차가 도로를 달리고 있다."
]

# 모델 및 임베딩
model = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')
embeddings = model.encode(sentences)

# PCA
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
reduced = pca.fit_transform(embeddings)

# 시각화
plt.figure(figsize=(8, 6))
for i, (x, y) in enumerate(reduced):
    plt.scatter(x, y)
    plt.text(x + 0.01, y + 0.01, sentences[i], fontsize=12)
plt.title("문장 임베딩 PCA 시각화")
plt.xlabel("PC1")
plt.ylabel("PC2")
plt.grid(True)
plt.show()

 

- PCA 시각화 결과 및 해석

PCA를 통해 384차원의 문장 임베딩을 2차원으로 축소한 결과, 다음과 같은 공간적 분포가 나타났다:

  1. 문장 1 ("오늘은 날씨가 정말 좋다.")
  2. 문장 2 ("맑은 하늘이 기분을 상쾌하게 해준다.")
    → 두 문장은 PCA 공간에서 거의 겹쳐진 위치에 배치됨
    → 의미상 유사한 두 문장이 실제로 임베딩 공간에서도 가까운 위치에 있음을 시각적으로 확인
  3. 문장 3 ("고양이는 낮잠을 자고 있다.")
    → 좌하단에 고립된 위치에 존재
    → 주제가 완전히 다르며, 동물/행동 중심 문장이라는 점에서 다른 문장들과 구분됨
  4. 문장 4 ("나는 새로운 언어를 배우고 있다.")
    → 최상단에 단독 위치
    → 학습/자기계발이라는 고유한 의미로, 감정·날씨·관찰 문장들과는 구별됨
  5. 문장 5 ("자동차가 도로를 달리고 있다.")
    → 중앙 왼쪽에 위치
    → 고양이/낮잠 문장과 가까운 쪽에 있으나, 전체적으로는 독립적 위치

5) t-SNE 시각화

-  t-SNE 시각화 사용 코드

from sklearn.manifold import TSNE
from sentence_transformers import SentenceTransformer
import matplotlib.pyplot as plt
import platform

# 한글 폰트 설정
if platform.system() == 'Windows':
    plt.rc('font', family='Malgun Gothic')
elif platform.system() == 'Darwin':
    plt.rc('font', family='AppleGothic')
else:
    plt.rc('font', family='NanumGothic')
plt.rcParams['axes.unicode_minus'] = False

# 문장 리스트
sentences = [
    "오늘은 날씨가 정말 좋다.",
    "맑은 하늘이 기분을 상쾌하게 해준다.",
    "고양이는 낮잠을 자고 있다.",
    "나는 새로운 언어를 배우고 있다.",
    "자동차가 도로를 달리고 있다."
]

# 임베딩
model = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')
embeddings = model.encode(sentences)

# t-SNE (주의: 랜덤성 있음, perplexity는 샘플 수에 맞게 낮게)
tsne = TSNE(n_components=2, perplexity=3, random_state=42, n_iter=1000)
reduced = tsne.fit_transform(embeddings)

# 시각화
plt.figure(figsize=(8, 6))
colors = ['orange', 'blue', 'green', 'red', 'purple']
for i, (x, y) in enumerate(reduced):
    plt.scatter(x, y, color=colors[i])
    plt.text(x + 0.1, y + 0.1, sentences[i], fontsize=12)
plt.title("문장 임베딩 t-SNE 시각화")
plt.xlabel("t-SNE 1")
plt.ylabel("t-SNE 2")
plt.grid(True)
plt.show()

 

-  t-SNE 시각화 결과 및 해석

t-SNE를 통해 문장 임베딩을 2차원으로 축소한 결과, 다음과 같은 의미 군집이 시각적으로 드러났다:

  1. 문장 1 ("오늘은 날씨가 정말 좋다.")
  2. 문장 2 ("맑은 하늘이 기분을 상쾌하게 해준다.")
    → 두 문장은 서로 가까운 하단 구역에 위치
    → 의미적으로 모두 날씨 및 감정과 관련되어 있으며, 의미 유사성을 기반으로 동일 클러스터 내에 배치됨
  3. 문장 3 ("고양이는 낮잠을 자고 있다.")
    → 상단에 고립된 위치
    → 동물 행동 묘사로, 다른 문장들과 의미적 관련성이 낮아 독립적인 위치에 존재
  4. 문장 4 ("나는 새로운 언어를 배우고 있다.")
    → 우측 하단에 단독 위치
    → 학습·지적 활동이라는 주제 특성상 고유한 의미 군집을 형성
  5. 문장 5 ("자동차가 도로를 달리고 있다.")
    → 중앙에 가까운 위치지만, 다른 문장들과는 충분한 거리 유지
    → '관찰된 행동'이라는 일반적 특징을 갖지만 주제 측면에서는 중립적인 의미

6) PCA vs t-SNE 시각화 비교 분석 요약

- PCA 결과 요약:

  • 문장 1번과 2번이 같은 클러스터 내에서 매우 근접
  • 나머지 문장들은 의미적으로 분리되긴 했으나, 간격이 완벽히 구분되지는 않음
  • 전체 구조 파악에 유용하지만, 일부 문장 간 거리 차이는 다소 완만하게 표현됨

- t-SNE 결과 요약:

  • 문장 1번(날씨 좋다)과 2번(기분 상쾌)만이 강하게 가까운 위치로 클러스터링
  • 나머지 문장들은 의미적 독립성에 따라 명확히 멀어진 위치에 분산
  • 특히 고양이, 자동차, 언어 학습 문장은 명확히 구분된 위치에 있어 분류 관점에서 더 직관적

 

- 표 비교

항목 PCA (주성분 분석) t-SNE (확률적 이웃 임베딩)
목적 전역적인 분산 최대화 국소적인 거리 보존 (이웃 구조 유지)
수학적 기반 선형 변환 (고차원 → 저차원 직선 축) 비선형 확률 기반 거리 보존
해석 가능성 좌표축의 의미 명확 (PC1, PC2) 좌표축의 의미 없음, 해석 불가능
속도 빠름 상대적으로 느림
결과 일관성 동일 데이터면 항상 동일 결과 매 실행마다 약간씩 달라짐 (랜덤성 존재)

 

7) 종합 결론

  • PCA는 전체적인 전역적 분포를 해석하거나 트렌드를 설명할 때 유리하며,
  • t-SNE는 의미 유사성 기반의 문장 군집화 또는 분류 판단에 효과적이다.
  • 따라서 데이터의 전체 구조를 해석할 목적이라면 PCA, 유사한 의미끼리 모이는 현상을 직관적으로 보여줄 목적이라면 t-SNE가 더 적합하다.

 

 

8) 분석 및 느낀 점

  • PCA 시각화를 통해, 문장의 의미적 유사성이 벡터 간 거리로 표현되며 공간상에서도 군집을 형성한다는 점을 확인할 수 있었다.
  • 특히 의미 유사한 문장(1번과 2번)은 인접하게 시각화되었고, 주제가 완전히 다른 문장들(3~5번)은 서로 멀리 위치함으로써 임베딩 공간이 구조화되어 있음을 입증함.
  • 이 결과는 단순 수치 비교(Cosine 유사도)를 넘어, 직관적으로 임베딩 구조를 이해하는 데 매우 효과적이었다.
  • t-SNE 시각화를 통해 "유사한 의미는 가까이, 다른 의미는 멀리"라는 임베딩 공간의 구조가 잘 드러났다.
  • 날씨와 감정 관련 문장은 하나의 클러스터를 이루었고, 학습, 동물 행동, 이동 행동 등의 문장은 각각 다른 방향으로 뚜렷이 분리되었다.
  • 이는 문장을 단순한 단어 나열이 아닌, 의미 단위의 벡터로 표현하는 임베딩의 핵심 원리를 시각적으로 증명한 결과이다.

 

 

1. 임베딩 개념 조사 요약

1-1. 벡터의 정의

벡터는크기(길이)와 방향을 동시에 나타내는 물리량을 말한다.
힘, 속도, 가속도 등을 이것으로 나타내며, 기호는 화살표(→) 를 쓴다.
벡터와 대비하여 크기만(길이, 높이, 질량, 에너지)을 갖는 대상을 스칼라(Scalar)라고 한다.

벡터가 크기와 방향만을 가지므로 원점의 특정한 위치는 아무런 의미를 갖지 않는다.
즉, 원점(시작점)이 일치하지 않더라도 두 화살표의 방향이 일치하고 그 크기가 같으면, 동일한 벡터다.
벡터를 표현하는 방법으로 공간에 좌표계를 설정하여 좌표 값을 사용할 수 있다.

자연어처리(NLP)에서는 각 단어를 고정된 크기의 실수 벡터로 표현하는데, 이것을 임베딩 벡터라고 한다.  
이 임베딩 벡터는 보통 300차원, 768차원 등 고차원 실수 공간의 점으로 나타내며, 각 차원은 단어의 의미와 관련된 추상적인 속성을 담고 있다.  
이러한 벡터는 단어의 의미를 수치화한 것으로, 기계가 언어를 이해하고 비교할 수 있게 만든다.  
또한 벡터 간 유사도 계산을 통해 단어 또는 문장 간 의미적 가까움을 측정할 수 있으며, 이는 검색, 분류, 추천 등 다양한 NLP 응용에 활용된다.

1-2. 벡터의 내적과 코사인 유사도

벡터의 내적(dot product) 은 두 벡터의 각 성분을 곱한 뒤 모두 더한 값으로, 결과는 스칼라(하나의 수)이다.
예를 들어, 벡터 a = [a₁, a₂, ..., aₙ], 벡터 b = [b₁, b₂, ..., bₙ]이라면 내적은 다음과 같이 계산한다.


내적은 두 벡터 간의 방향성과 관계를 수치로 표현할 수 있으며, 각도와의 관계는 다음 수식으로 나타난다.

여기서 θ는 두 벡터 사이의 각도이다. 이 식을 변형하면 코사인 유사도(Cosine Similarity) 공식을 얻을 수 있다.


코사인 유사도는 두 벡터가 이루는 각도의 코사인 값을 기반으로 유사도를 측정하는 방식이다.
이 값은 -1부터 1 사이이며, 1에 가까울수록 두 벡터의 방향이 유사함을 의미한다.

  • 1에 가까울수록 두 벡터의 방향이 유사하고,
  • 0이면 서로 직각,
  • -1이면 반대 방향임을 의미한다.

코사인 유사도의 장점은 벡터의 크기(길이)에 영향을 받지 않고, 오직 방향만을 기준으로 유사도를 판단할 수 있다는 점이다.
자연어처리(NLP)에서는 단어 또는 문장 간 의미적 유사도를 비교할 때 자주 사용된다.

 

1-3. 벡터 공간 의미론과 의미적 연산

벡터의 덧셈과 뺄셈은 수학적으로는 위치 이동, 방향 결합 또는 차이를 나타내는 연산이다.
자연어처리(NLP)에서는 이러한 연산을 단어 사이의 의미 관계 추론에 활용한다.
이는 벡터 공간 의미론(Vector Space Semantics) 개념에 기반한다.

벡터 공간 의미론이란, 단어나 문장의 의미를 고차원 실수 공간의 한 점(벡터)으로 나타내는 방식이다.
이때 단어들 사이의 의미적 유사성은 벡터 간 거리나 각도 등 기하학적 관계로 표현된다.
이 공간에서 덧셈과 뺄셈은 의미의 결합과 차이를 나타내며, 유사한 단어들은 가까운 위치에 놓이게 된다.
특히, 이 벡터 공간에서는 덧셈과 뺄셈을 통해 의미의 조합이나 관계 추론이 가능하다.

예를 들어 "Paris - France + Italy = Rome" 예시를 살펴보자.

벡터("Paris") - 벡터("France") + 벡터("Italy") ≈ 벡터("Rome")

"Paris - France + Italy"와 같은 연산을 수행하면, 결과는 "Rome"과 유사한 벡터에 도달한다.
파리에서 프랑스라는 의미를 빼는 것은 ‘프랑스의 수도’라는 관계에서 ‘수도’라는 개념만 남기는 것과 비슷하다.
즉, ‘프랑스의 수도가 파리이듯, 이탈리아의 수도는 로마’라는 관계적 의미를 반영한 결과이다.

이처럼 임베딩 공간에서는 단어 간 의미적 관계가 선형 구조로 표현된다.
이러한 벡터 연산은 단어 유추, 의미 분류, 문장 생성 등 다양한 NLP 응용에서 매우 유용하게 활용된다.

 

2. 실험 개요 및 목적

2-1. LLM에서 임베딩의 역할

LLM은 입력된 단어나 문장을 기계가 이해할 수 있는 벡터 형태로 변환한 뒤, 그 벡터를 기반으로 문맥을 해석하거나 다음 단어를 예측하는 작업을 수행한다. 이때 임베딩은 단어 또는 문장을 고차원 공간의 실수 벡터로 바꾸는 과정이며, LLM 내부에서 의미 정보를 전달하는 핵심 매개체 역할을 한다. 의미가 유사한 단어는 벡터 공간에서도 가까운 위치에 있도록 학습되며, 이러한 구조 덕분에 모델은 의미 기반 추론이나 유사성 계산이 가능해진다.

2-2. 실험을 통해 검증하고자 하는 것

이번 실험은 LLM이 생성한 임베딩 벡터들이 실제로 의미 유사성에 기반해 구조화되어 있는지를 검증하는 데 목적이 있다. 서로 유사한 문장 또는 단어의 벡터가 실제로 가까운 위치에 있는지를 코사인 유사도를 통해 확인하며, 의미가 다른 경우 멀어진다는 성질도 함께 살펴본다. 또한, 벡터 연산이나 시각화를 통해 임베딩 공간이 의미적으로 얼마나 조작 가능한지를 실험해본다. 이 과정을 통해 LLM이 단순히 텍스트를 암기하는 것이 아니라, 의미 간 관계를 수치적으로 파악하고 있다는 점을 체감할 수 있다.

 

3. 실험 문장 선정 및 설계

문장의 의미 유사성과 비유사성을 임베딩 벡터로 비교하기 위해 주제나 감정의 흐름이 비슷한 문장과 전혀 다른 주제의 문장을 함께 구성하였다.
특히, 문장 A와 B는 ‘날씨’와 ‘기분’이라는 감성적 주제를 공유하며, 나머지 문장 C~E는 각각 고양이의 행동, 언어 학습, 자동차 운전 등 전혀 다른 의미를 포함하고 있다.
이를 통해 의미가 유사한 문장은 임베딩 벡터 간 거리가 가깝고, 의미가 상이한 문장은 멀리 떨어져 있는지를 확인하고자 한다.

  • 문장 A: 오늘은 날씨가 정말 좋다.
  • 문장 B: 맑은 하늘이 기분을 상쾌하게 해준다.
  • 문장 C: 고양이는 낮잠을 자고 있다.
  • 문장 D: 나는 새로운 언어를 배우고 있다.
  • 문장 E: 자동차가 도로를 달리고 있다.

 

4. 임베딩 모델 소개

(1) sentence-transformers/all-MiniLM-L6-v2
설명: 경량 sentence embedding 모델로 빠르고 효율적임
언어지원: 영어 중심, 한국어 성능은 보통 수준
출력 차원: 384
링크: https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2

(2) jhgan/ko-sroberta-multitask
설명: 한국어에 특화된 Sentence-BERT 구조 기반 모델
한국어 성능: 한국어 의도 분류, 감정 분석, STS 등 여러 태스크로 학습되어 문장 간 의미 비교에 적합
출력 차원: 768
링크: https://huggingface.co/jhgan/ko-sroberta-multitask

(3) sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2
지원 언어: 50개 이상, 한국어 포함
특징: 한국어를 포함한 다국어 문장 유사도 비교에 강한 성능
출력 차원: 384
호환: SentenceTransformer에서 바로 사용 가능
링크: https://huggingface.co/sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2

 

5. 임베딩 결과 및 유사도 비교

(1) 사용 코드

from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np

# 실험 문장
sentences = [
    "오늘은 날씨가 정말 좋다.",
    "맑은 하늘이 기분을 상쾌하게 해준다.",
    "고양이는 낮잠을 자고 있다.",
    "나는 새로운 언어를 배우고 있다.",
    "자동차가 도로를 달리고 있다."
]

# 사용할 모델 리스트
model_names = [
    'sentence-transformers/all-MiniLM-L6-v2',
    'jhgan/ko-sroberta-multitask',
    'paraphrase-multilingual-MiniLM-L12-v2'

]

# 각 모델별 유사도 행렬 저장
for name in model_names:
    print(f"\n모델: {name}")
    model = SentenceTransformer(name)
    embeddings = model.encode(sentences)
    sim_matrix = cosine_similarity(embeddings)
    print(np.round(sim_matrix, 2))  # 보기 쉽게 소수점 2자리

(2) 문장 임베딩 결과

- 모델: sentence-transformers/all-MiniLM-L6-v2

[[1. 0.51 0.49 0.61 0.57]
[0.51 1. 0.59 0.72 0.54]
[0.49 0.59 1. 0.67 0.76]
[0.61 0.72 0.67 1. 0.72]
[0.57 0.54 0.76 0.72 1. ]]

- 모델: jhgan/ko-sroberta-multitask

[[ 1. 0.72 0.04 0.09 0.02]
[ 0.72 1. 0.06 0.08 -0.04]
[ 0.04 0.06 1. -0.1 -0.03]
[ 0.09 0.08 -0.1 1. -0.03]
[ 0.02 -0.04 -0.03 -0.03 1. ]]

- 모델: paraphrase-multilingual-MiniLM-L12-v2

[[ 1. 0.67 0. 0.03 0.21]
[ 0.67 1. 0.03 0.07 0.1 ]
[ 0. 0.03 1. -0.01 0.11]
[ 0.03 0.07 -0.01 1. 0.03]
[ 0.21 0.1 0.11 0.03 1. ]]

(3) 결과비교표 

문장 쌍 (A vs ...) all-MiniLM-L6-v2 ko-sroberta-multitask paraphrase-multilingual
A vs B 0.51 0.72 0.67
A vs C 0.49 0.04 0.00
A vs D 0.61 0.09 0.03
A vs E 0.57 0.02 0.21

 

6. 결과 해석

이번 실험에서는 세 가지 sentence embedding 모델을 사용하여 동일한 문장쌍 간의 코사인 유사도를 비교하였다.
특히 문장 A와 B는 의미적으로 유사한 문장쌍이며, 문장 A와 C~E는 주제가 전혀 다른 비유사 문장쌍으로 구성하였다.
실험 결과, 각 모델이 의미 유사성과 비유사성을 어떻게 구별하는지 뚜렷한 차이를 보였다.

1. ko-sroberta-multitask (한국어 특화 모델)

  • 문장 A vs B에서 0.72의 높은 유사도 점수를 부여하며, 의미 유사성을 정확히 인식함.
  • 반면 A vs C~E 에서는 0.02 ~ 0.09 수준의 매우 낮은 점수를 부여하여 의미가 다르면 확실히 구별함.
  • 한국어 문장 간 의미 구분이 매우 명확하고 예민하게 작동하는 특성을 보였다.

2. all-MiniLM-L6-v2 (영어 중심 모델)

  • A vs B는 0.51로 중간 정도의 유사도를 보였고, A vs C~E 도 0.49 ~ 0.61로 비슷한 수준의 점수를 부여함.
  • 의미적으로는 무관한 문장임에도 구조적 유사성이나 문장 길이 등 비의미적 요소에 영향을 받은 것으로 보인다.
  • 한국어에 대한 의미 구별력이 다소 떨어지는 경향이 확인되었다.

3. paraphrase-multilingual-MiniLM-L12-v2 (다국어 모델)

  • A vs B는 0.67로 높게 평가했지만, A vs C ~ E는 대부분 0.00 ~ 0.21 수준으로 매우 낮은 유사도를 기록함.
  • 의미가 겹치는 경우에만 유사도를 높게 부여하고, 그렇지 않으면 신중하게 낮은 값을 주는 특징이 있다.
  • 전체적으로 분별력 위주의 보수적인 스코어링을 하는 모델로 해석된다.


결론적으로,

  • ko-sroberta-multitask는 의미 기반 유사도 판별에서 가장 직관적이고 명확한 결과를 보여주었다.
  • all-MiniLM-L6-v2는 문장 구조에 민감한 반면 의미 구별력은 상대적으로 낮았다.
  • paraphrase-multilingual-MiniLM-L12-v2는 의미 구분에 민감하면서도 보수적으로 반응하는 모델이었다.

따라서 한국어 의미 유사성 실험에서는 ko-sroberta-multitask 모델이 가장 신뢰도 높은 결과를 제공하는 것으로 판단된다.

 

7. 벡터 연산 실험

이번에는 단어 수준의 임베딩 벡터를 이용하여 벡터 연산이 실제로 의미적 조작으로 작동하는지를 확인하였다.
이번 실험에서는 보고서의 주요 주제인 "날씨와 기분"이라는 주제를 반영하여 아래와 같은 연산을 구성하였다:

- "기분" + "맑다" ≈ 상쾌한 감정 상태?

1) 사용 모델 : paraphrase-multilingual-MiniLM-L12-v2 (sentence-transformers)

  • 한국어 포함 다국어 지원, 단어 수준 의미 연산 실험에 적합

2) 실험 단어 :

  • base 단어: 기분, 맑다
  • 후보 단어: 행복, 기쁨, 쾌활, 우울, 평온, 불쾌, 즐겁다, 상쾌

3) 사용 코드 : 

from sentence_transformers import SentenceTransformer, util
import torch

model = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')

# 입력 단어들
words = ["기분", "맑다", "행복", "기쁨", "쾌활", "우울", "평온", "불쾌", "즐겁다", "상쾌"]
embeddings = model.encode(words, convert_to_tensor=True)

# 벡터 연산: 기분 + 맑다
target_vec = embeddings[0] + embeddings[1]

# 유사도 계산
cos_scores = util.pytorch_cos_sim(target_vec, embeddings)
cos_scores = cos_scores[0].tolist()

# 결과 정렬
result = sorted(zip(words, cos_scores), key=lambda x: x[1], reverse=True)

# 상위 유사도 결과 출력
for word, score in result[:5]:
    print(f"{word}: {score:.4f}")

4) 실험 결과 (상위 5개) : 순위 단어 Cosine 유사도

1 기분 0.9290
2 맑다 0.8948
3 평온 0.8605
4 쾌활 0.8283
5 즐겁다 0.8250

5) 결과 해석

기분 + 맑다라는 개념 조합은 임베딩 공간에서 실제로 '평온', '쾌활', '즐겁다' 등의 긍정적 감정 상태와 매우 높은 유사도를 보였다.
이는 벡터 연산을 통해 의미가 조합된 위치를 찾을 수 있다는 것을 보여주며, 임베딩 공간이 단순 위치 정보가 아니라 개념 구조화된 공간임을 증명한다.
특히 평온(0.8605), 쾌활(0.8283), 즐겁다(0.8250)는 맑고 기분 좋은 상태를 반영한 단어로, 임베딩 공간이 단순한 숫자 배열이 아니라 개념이 구조화된 공간임을 증명하는 대표적인 사례라 할 수 있다.

 

 

1. Tokenizer

Tokenizer문장을 LLM(Large Language Model)이해할 있도록 잘게 나누는 도구다. LLM인간의 언어를 그대로 이해하지 못하기 때문에 입력 문장을 일정한 단위의 토큰(token)으로 나누고 이를 숫자 ID변환해 처리한다.

토큰의 단위는 모델마다 다르다. 어떤 모델은 단어 단위로, 어떤 모델은 서브워드(subword) 또는 문자(character) 단위로 나눈다. 예를 들어 "행복합니다"라는 문장은 어떤 모델에서는 하나의 토큰으로 처리되고, 또 다른 모델에서는 "행", "복", "합", "니", "다"쪼개질 있다.

Tokenizer방식에 따라 모델이 입력을 해석하는 방식과 비용, 성능이 달라진다. 대표적인 방식으로는 Byte Pair Encoding(BPE), WordPiece, SentencePiece 등이 있으며, 각각의 방식은 분해 기준과 어휘 집합이 다르다. 따라서 같은 문장이라도 사용하는 Tokenizer따라 토큰 수, 의미 단위, 처리 효율성모두 달라진다.

 

 

2. 실험 목적

실험의 목적은 같은 문장을 다양한 토크나이저로 분해했을 때, 토큰 수와 분해 방식이 어떻게 달라지는지를 관찰하는 이다. 특히 한국어, 영어, 특수문자, 한자가 섞인 문장을 사용할 경우 모델별로 얼마나 다르게 분해되는지를 직접 확인하고자 했다.

또한, 토크나이저마다 한글 처리 능력에 차이가 있는지를 살펴보고 사람이 이해하기에 직관적인 토큰 분해 결과를 제공하는 모델이 무엇인지 비교하였다. 

 

 

3. 사용한 tokenizer 이름

아래 네 가지 토크나이저를 이용했다. 

- GPT2
- bert-base-multilingual-cased
- deepseek-ai/DeepSeek-V3-0324
- gpt-4o (tiktoken)

1) gpt2 : OpenAI초기 언어 모델인 GPT-2에서 사용하는 토크나이저로, Byte Pair Encoding(BPE) 기반이다. 주로 영어 텍스트를 대상으로 학습되었으며, 한글이나 특수문자 처리에 한계가 있다.

2) bert-base-multilingual-cased : 구글의 다국어 모델인 BERT에서 사용하는 WordPiece 기반 토크나이저다.  110이상의 언어를 다룰 있으며, 영어 단어를 서브워드 단위로 분해하는 특징이 있다.

3) deepseek-ai/DeepSeek-V3-0324 : 중국에서 개발한 대규모 언어모델 DeepSeek 시리즈 하나로, 다국어 처리 성능이 강화구조다. 한글 특수문자 처리에서도 GPT-2보다 자연스러운 분해를 보여준다.

4) gpt-4o(tiktoken 기반) : 2024OpenAI에서 발표한 GPT-4o멀티모달 모델로, Tiktoken이라는 고속 토크나이저를 사용한다. 다양한 언어와 특수문자, 이모지까지 효율적으로 처리하며, 가장 최적화된 토큰 분해 결과를 보인다.

 

 

4. 실험에 사용한 문장 및 코드

이번 실험에서는 문장의 언어 구성에 따라 토크나이저의 분해 방식이 어떻게 달라지는지를 확인하기 위해 다음 가지 유형의 문장을 선정하였다.

 

  • 문장1: 한국어로만 문장
    새해 복 많이 받으세요. 오늘도 운수 좋은 하루 되세요.
    한국어만 포함된 문장으로, 한글 토크나이징 처리 성능을 비교하기 위해 사용하였다.
  • 문장2: 영어로만 문장
    Happy New Year! Wishing you a day full of good fortune and happiness.
    대부분의 토크나이저가 영어 기반으로 학습되었기 때문에 기준선 역할로 사용하였다.
  • 문장3: 한국어 + 특수문자 + 영어 포함 혼합 문장
    2025년 새해 福 많이 받으세요!! Happy New Year~~
    숫자, 한자, 특수문자, 영어가 혼합된 문장으로, 복합 구성에 대한 토크나이저의 대응 방식을 보기 위해 설정하였다.

 

사용한 코드는 다음과 같다.

from transformers import AutoTokenizer
import tiktoken

# 비교용 텍스트
text = "2025년 새해 福 많이 받으세요!! Happy New Year~~!!"

# Hugging Face 기반 tokenizer 실험 함수
def tokenize_with_model(model_name, text):
    tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
    tokens = tokenizer.tokenize(text)
    input_ids = tokenizer.encode(text, add_special_tokens=False)
    decoded_tokens = [tokenizer.decode([tid]) for tid in input_ids]

    print(f"\n⭐ Model: {model_name}")
    print("✅ 입력 문장:", text)
    print("✅ Token 수:", len(input_ids))
    print("✅ Token ID 목록:", input_ids)
    print("✅ Token 목록:", tokens)
    print("✅ 사람이 읽을 수 있는 Token들:", decoded_tokens)

# GPT-2
tokenize_with_model("gpt2", text)

# BERT
tokenize_with_model("bert-base-multilingual-cased", text)

# DeepSeek
tokenize_with_model("deepseek-ai/DeepSeek-V3-0324", text)

# GPT-4o tokenizer (tiktoken 기반)
encoding = tiktoken.encoding_for_model("gpt-4o")
input_ids = encoding.encode(text)
decoded = [encoding.decode([tid]) for tid in input_ids]

print("\n⭐ Model: gpt-4o (tiktoken)")
print("✅ 입력 문장:", text)
print("✅ Token 수:", len(input_ids))
print("✅ Token ID 목록:", input_ids)
print("✅ 사람이 읽을 수 있는 Token들:", decoded)

 

 

5. 각 tokenizer에서 분해된 token 수 및 token 목록

- 문장 1 : 새해 복 많이 받으세요. 오늘도 운수 좋은 하루 되세요.

 

  • GPT2해당 문장을 62개의 토큰으로 매우 많이 쪼갰으며, 대부분 깨진 문자로 처리되어 한글 처리 성능이 낮은 특징보였다.
  • BERT21개의 토큰으로 적절히 분해했지만, “받으세요” 같은 표현을 [받] [##으] [##세] [##요]처럼 서브워드 단위로 나누어 사람 눈에는 다소 비직관적이다.
  • DeepSeekGPT-4o각각 21개, 17개의 토큰으로 분해했으며, 단위로 자연스럽게 나누는 경향보였다. 특히 GPT-4o가장 압축적이고 직관적인 분해 결과보였다.

 

- 문장 2 : Happy New Year! Wishing you a day full of good fortune and happiness.

 

  • GPT216개의 토큰으로 분해했으며, 영어 문장에는 강한 성능을 보였다.
  • BERT는 "happiness"[ha] [##ppi] [##ness]처럼 서브워드로 분해했지만, 영어권에서는 자주 쓰는 방식이다.
  • GPT-4oDeepSeek거의 동일하게 영어 단어 단위의 토큰화를 수행했다.

 

- 문장3: 2025년 새해 福 많이 받으세요!! Happy New Year~~!!

 

  • GPT2무려 36개의 토큰으로 분해되었고, 한자(福)특수문자(!!, ~~) 등에서 처리 성능이 떨어지는 경향보였다.
  • BERT적당한 수준(19개)토큰 수를 유지했고, 특수문자를 별도로 인식했다.
  • GPT-4o16개의 토큰으로 가장 효율적인 분해 결과보였으며, 한글·한자·특수문자·영어 혼합에도 강인한 처리 능력을 보였다.

 

 

6. 가장 흥미로웠던 token 분해 결과와 이유

GPT-2 tokenizer의 경우 토큰 수가 다른 토크나이저에 비해 월등히 많았다. decoded_tokens을 이용해 모델의 Token Id를 사람이 읽을 수 있는 형태로 복원했을 때 영어는 잘 됐지만 한글, 한자는 대부분이 깨진 문자로 처리되었다. GPT-2의 tokenizer는 BPE(Byte Pair Encoding) 기반이며 주로 영어 데이터로 학습되었기 때문에 한글이나 한자의 성능이 떨어지는 구조적 한계를 생각하면 당연한 결과인 것 같다. 결과적으로 같은 문장임에도 더 많은 토큰으로 쪼개졌고, 이는 의미 단위가 지나치게 분리되면서 해석 효율이 떨어질 수 있음을 의미한다.

다른 토크나이저들의 경우 GPT-2 tokenizer와는 달리 한글 처리가 잘 되긴했지만 BERT tokenizer의 경우 happiness를 ["ha", "##ppi", "##ness"]처럼 불연속적인 subword 단위로 분해했다. 이는 사람의 눈으로 보기엔 직관적이지 않아 뜻 파악이 어렵지만, 모델 입장에선 의미 단위별 학습이 가능해서 학습 성능의 면에선 오히려 도움이 됨을 의미한다.

DeepSeek과 GPT-4o tokenizer는 의미 단위에 가깝게 분해했고, 한국어와 영어는 물론이고 “福”이나 “!!”와 같은 한자나 특수문자도 잘 처리한 것으로 보인다. 특히 GPT-4o tokenizer 같은 경우 세 문장 모두 가장 적거나 다른 tokenizer와 같은 토큰 수로 가장 자연스럽게 분해했다.

 

 

+ Recent posts