수달이네 기술 블로그

2. 자연어 처리(벡터화) 본문

AI공부/자연어처리

2. 자연어 처리(벡터화)

슬픈 수달이 2026. 2. 16. 18:58

단어사전

자연어 처리에서 사용되는 모든 토큰을 모아 고유한 인덱스를 매핑한 집합

  • 문장 > 토크나이징 > 임베딩 > 단어사전
  • 모델이 문자열을 직접 처리할 수 없는 한계를 극복함
  • 사전에 없는 단어를 처리하기 위한 OOV(Out-Of-Vocabulary)토큰 같은 특수기호도 있음.

OOV

본 적 없는 단어나 토큰이 입력에 등장했을 때 발생하는 문제

  • 정수 인코딩, 임베딩으로 변환할 수 없어 성능 저하
  • OOV전용 토큰을 만들거나, 서브워드 분리(BPE, WordPiece)방법을 사용하여 새로운 단어를 작게 쪼개 처리하는 기법이 활용됨.

벡터화

텍스트 데이터를 숫자형태로 변환하는 것.

원핫 인코딩

텍스트 데이터를 숫자 벡터로 변환하는 방법.
각 단어를 벡터의 한 차원으로 지정하고 해당 단어에만 1을 넣고 나머지는 0으로 변환

  • 단어 자체를 나타내는 가장 간단한 방법
  • 단점: 단어간의 의미적 관계를 반영하지 못하고, 고차원 희소벡터를 생성해 메모리 낭비도 크다.
    • 희소벡터: 대부분의 값이 0인 벡터. 이를 해결하기 위해 Dense Vector로 변환하는 워드 임베딩 기법이 자주 사용됨

Bag of words

문장을 구성하는 단어의 등장 빈도를 기반으로 표현한다

  • 문장은 단어 집합의 크기만큼의 차원을 가진다.,
  • 특징: 구현이 간단하고, 텍스트 데이터를 빠르게 벡터화 할 수 있어 기초적인 자연어 처리로 사용된다.
  • 단점: 단어의 순서, 문맥은 고려되지 않고, 단순 빈도만 반영되어 구조, 의미를 표현하는데 한계가 있다.

DTM(Document_Term Matrix, 문서-단어 행렬)

여러 문서를 행으로, 단어사전에 포함된 단어들을 열로 두어 각 문서에서 단어가 몇번 등장했는지 수치로 표현한 행렬

  • 문서들을 단어 기반으로 정리한 표 형태로서, 각 칸의 값은 단어 빈도나 TF-IDF값이 들어간다
  • 문서를 수치화 하여 머신러닝이나 텍스트마이닝에서 분류, 군집, 주제 모델링 같은 작업에 활용할 수 있다.
from collections import Counter

documents = [
    "I love Python Python",
    "Python is great Python",
    "I love coding coding coding"
]

# 1. 단어 집합 생성
vocab = set() # 중복, 순서 없음
for doc in documents:
    vocab.update(doc.split()) # 공백 기준으로 단어 분리하여 집합에 추가
vocab = sorted(vocab)  # 단어 집합 정렬

# 결과 출력
print("단어 집합:", vocab)

# 단어 집합: ['I', 'Python', 'coding', 'great', 'is', 'love']
  • set을 사용해 집합 생성(공백기준으로 중복, 순서 없이)
# 2. 단어에 인덱스 부여
word_to_index = {word: idx for idx, word in enumerate(vocab)}

# 결과 출력
print("단어 인덱스:", word_to_index)
# 단어 인덱스: {'I': 0, 'Python': 1, 'coding': 2, 'great': 3, 'is': 4, 'love': 5}
  • 인덱스 부여 후
# 3. 각 문장을 벡터로 변환
bow_vectors = []
for doc in documents:
    word_counts = Counter(doc.split())  # 단어 등장 횟수 계산
    bow_vector = [word_counts.get(word, 0) for word in vocab]  # 단어 집합 순으로 벡터 생성
    bow_vectors.append(bow_vector)

# 결과 출력  
print("Bag of Words 벡터:")
for i, vector in enumerate(bow_vectors):
    print(f"문장 {i+1}: {vector}")
    
# Bag of Words 벡터:
# 문장 1: [1, 2, 0, 0, 0, 1]
# 문장 2: [0, 2, 0, 1, 1, 0]
# 문장 3: [1, 0, 3, 0, 0, 1]
 IPythoncodinggreatislove
문장 1120001
문장 2020110
문장 3103001

TF- IDF

텍스트 데이터에서 단어의 중요도를 측정하는 방법
단어의 빈도와 역문서 빈도를 조합하여 계산

  • 단어빈도(TF): 특정 문서에서 얼마나 자주 등장하는가
    • 이 문장에서 중요한 단어임
  • 역문서빈도(IDF): 다른 문서에서도 흔하게 등장하는가
    • 조사같은 단어일 가능성이 있어 가중치가 낮아짐
  • 텍스트데이터의 벡터화를 통해 검색엔진, 텍스트 분류등의 작업에 널리 사용된다.
from sklearn.feature_extraction.text import TfidfVectorizer

corpus = [
    'you know I want your love',
    'I like you',
    'what should I do ',
]

tfidfv = TfidfVectorizer().fit(corpus)
print(tfidfv.transform(corpus).toarray())
print(tfidfv.vocabulary_)

# [[0.         0.46735098 0.         0.46735098 0.         0.46735098
#   0.         0.35543247 0.46735098]
#  [0.         0.         0.79596054 0.         0.         0.
#   0.         0.60534851 0.        ]
#  [0.57735027 0.         0.         0.         0.57735027 0.
#   0.57735027 0.         0.        ]]
# {'you': 7, 'know': 1, 'want': 5, 'your': 8, 'love': 3, 'like': 2, 'what': 6, 'should': 4, 'do': 0}

코사인 유사도

두 벡터의 방향(각도)를 기반으로 유사도를 측정하는 방법

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

doc1 = np.array([[0,1,1,1]])
doc2 = np.array([[1,0,1,1]])
doc3 = np.array([[2,0,2,2]])

print('문서 1과 문서2의 유사도 :',cosine_similarity(doc1, doc2))
print('문서 1과 문서3의 유사도 :',cosine_similarity(doc1, doc3))
print('문서 2와 문서3의 유사도 :',cosine_similarity(doc2, doc3))

# 문서 1과 문서2의 유사도 : [[0.66666667]]
# 문서 1과 문서3의 유사도 : [[0.66666667]]
# 문서 2와 문서3의 유사도 : [[1.]]

신경망 기반의 벡터화

워드 임베딩

단어를 고차원 희소벡터를 표현하는 기존 방식대신 저차원의 밀집 벡터로 변환하는 자연어처리 기법

  • 문장들의 단어사전을 시각화한 사이트

Embedding Layer

신경망에서 단어를 밀집 벡터로 표현하기 위해 사용되는 층으로 워드 임베딩을 수행하는 역할을 함.

  • 이 레이어는 주어진 단어를 정수 인덱스로 매핑하고, 해당 인덱스에 대응되는 고정길이의 임베딩 벡터를 학습 가능한 파라미터로 초기화하여 반환한다.
  • 단어가 새로 들어오면 의미적 관계를 학습해 가중치를 계속 업데이트 한다.

랜덤 초기화 인베딩

학습 초기 단계에서 임베딩 벡터를 무작위 값으로 설정하고, 학습 데이터를 사용해 임베딩 값을 점진적으로 업데이트.

  • 초기엔 벡터 표현이 의미를 가지지 않음. 그러나 학습 과정에서 점차 유의미한 벡터를 형성
  • 특정 도메인이나 언어의 특수성을 반영하기 적합하고, 사전 훈련된 임베딩이 없을때나 사용자 정의 데이터를 기반으로 처음부터 학습해야할 때 주로 사용됨.
    • 학습되는 데이터에 따라 LLM은 잘하는 답이 달라진다.

사전 훈련된 임베딩

대규모 코퍼스에서 미리 학습된 임베딩 벡터를 사용하여 초기 값을 설정하는 방식

  • Word2Vec., GloVe, FastText등과 같은 모델로 생성된 임베딩은 단어간의 의미적 유사성을 잘 반영함
  • 데이터가 부족하거나 일반적 언어의 특징을 잘 반영해야하는 상황에서 유용함
  • frozen: 임베딩 벡터를 고정, Fine-tuning: 미세 조정 하여 사용 가능

Word2Vec

단어를 벡터로 표현하기위해 개발된 자연어 처리 기법

  • 단어 간의 의미적 유사성을 수치적으로 나타낼 수 있는 임베딩 벡터를 생성한다.
  • CBOW, Skip-gram의 두가지 모델구조를 사용
  • 위 과정을 통해 단어간의 문맥적 관계를 반영하고, 유사한 의미를 가진 단어들이 가깝게 위치한다.
  • word2Vec연산 사이트: https://word2vec.kr/search/

CBOW

주변 단어를 기반으로 중심단어를 예측

  • 좌우 몇개 단어를 입력으로 받아 중심단어를 출력으로 예측하는 구조
  • 단어간의 문맥적 관계를 효과적으로 학습
  • 단어를 고차원 공간의 벡터로 표현하며 의미적으로 유사한 단어들이 가까운 위치에 있도록 학습
  • CBOW는 문장을 다양하게 보기보다, 문장을 외우듯이 획일적인 문장을 만든다. 그러나 학습은 확실함

ex) "나는 오늘 공원에서 귀여운 강아지를 산책시키며 행복한 시간을 보냈다."

  • 문맥과 중심 단어 설정
    • ex)윈도우 크기: 2(중심단어 기준 앞뒤 2개의 단어를 문맥으로 사용) 중심단어: 오늘 > 문맥단어 [나는, 공원에서, 귀여운]
  • CBOW에선 중심 단어와 그 주변 단어를 문맥으로 설정한다. 이를 위해 윈도우 크기를 정한다.
  • 단어를 벡터로 변환
    • ex) 원핫 벡터 공원에서 > [0,0,1,0,0,0,0,0,0]
    • 요즘엔 원핫벡터를 사용하지 않는다.
  • 컴퓨터는 텍스트를 숫자로 이해하므로, 단어를 원 핫 벡터로 변환한다. 단어 집합을 만들고, 각 단어에 고유한 인덱스를 할당한다.
  • 입력 데이터 구성문맥: [공원에서, 귀여운, 산책시키며, 행복한] > 인덱스 {2,3,5,6}
    • 합: [0,0,1,1,0,1,1,0,0]
    • 평균(÷4): [0,0,0.25,0.25,0,0.25,0.25,0,0]
  • 타깃: 강아지를
  • 문맥: [공원에서, 귀여운, 산책시키며, 행복한] > 인덱스 {2,3,5,6}
    • 합: [0,0,1,1,0,1,1,0,0]
    • 평균(÷4): [0,0,0.25,0.25,0,0.25,0.25,0,0]
  • 모델의 학습 과정
  • 학습 결과
  • 모델은 문맥 단어를 보고 중심단어를 정확히 예측할 수 있도록 가중치를 학습한다. 단어를 임베딩 벡터로 변환해 의미적으로 유사한 단어들이 가까운 위치에 배치되도록 한다.

Skipgram

중심 단어를 기반으로 주변 단어를 예측

  • 중심단어를 입력으로 사용하고, 그 단어를 기준으로 윈도우 크기 내의 주변단어를 출력으로 예측한다
  • ex) 고양이 > 귀여운, 자는 등을 예측
  • 희소한 데이터에서 성능이 우수하고, 문맥적 의미를 학습하는데 효과적, 고품질 단어 벡터를 생성할 수 있지만, CBOW에 비해 계산량이 더 많음.

ex)"나는 오늘 공원에서 귀여운 강아지를 산책시키며 행복한 시간을 보냈다."

  • 문맥과 중심 단어 설정
    • ex)윈도우 크기: 2(중심단어 기준 앞뒤 2개의 단어를 문맥으로 사용) 중심단어: 오늘 > 문맥단어 [나는, 공원에서, 귀여운]
  • CBOW에선 중심 단어와 그 주변 단어를 문맥으로 설정한다. 이를 위해 윈도우 크기를 정한다.
  • 단어를 벡터로 변환
    • ex) 원핫 벡터 공원에서 > [0,0,1,0,0,0,0,0,0]
    • 요즘엔 원핫벡터를 사용하지 않는다.
  • 컴퓨터는 텍스트를 숫자로 이해하므로, 단어를 원 핫 벡터로 변환한다. 단어 집합을 만들고, 각 단어에 고유한 인덱스를 할당한다.
  • 학습데이터 구성
    • 강아지를 : [0,0,0,0,1,0,0,0,0]
    • 출력 : 귀여운, 산책시키며, 공원에서, 행복한
  • skip-gram은 중심단어를 입력으로 사용하고, 그 주변의 문맥 단어를 출력으로 예측
  • 학습과정은닉층: 입력 벡터를 저차원 벡터로 변환한다.손실 계산 및 업데이트: 모델이 예측한 문맥 단어들과 실제 단어간의 차이를 계산한 뒤 손실을 줄이도록 가중치를 업데이트 한다
  • 출력층: 소프트맥스를 사용해 각 단어에 대한 확률 분포를 계산한다.
  • 입력층: 원 핫 벡터를 입력으로 받는다.
  • 결과

SGNS(가장 많이 사용)

Skip-gram모델의 변형으로 단어 임베딩을 효율적으로 학습하기 위해 네거티브 샘플링 기법을 사용한다.

  • 주변 단어와의 관계를 일부 샘플로만 학습하여 계산 비용을 줄인다.
  • 중심단어와 실제 문맥 단어 쌍을 학습하면서 무작위로선택된 단어들과의 관계를 연관성이 없다고 학습시킨다.

ex) "나는 오늘 공원에서 귀여운 강아지를 산책시키며 행복한 시간을 보냈다."

  • 문맥과 중심 단어 설정(Positive Pair)
    • ex)윈도우 크기: 2(중심단어 기준 앞뒤 2개의 단어를 문맥으로 사용) 중심단어: 오늘 > 문맥단어 [나는, 공원에서, 귀여운]
  • CBOW에선 중심 단어와 그 주변 단어를 문맥으로 설정한다. 이를 위해 윈도우 크기를 정한다.
  • Negative pairNegative Sample수: 5
    • ex)중심단어: 강아지를 > 네거티브[보냈다, 나는, 시간을,오늘, 공원에서]
  • 중심단어와 연관되지 않은 먼 단어를 학습

결과

Gensim

자연어 처리를 위한 라이브러리, 문서와 단어 임베딩, 주제 모델링 작업에 적합하다.
Gensim은 효율적이고 확장 가능한 방식으로 Word2Vec, Doc2Vec, FastText 등의 임베딩 모델과 LDA(Latent Dirichlet Allocation) 같은 주제 모델링 알고리즘을 지원한다.

  • 대규모 텍스트 데이터에서도 빠르게 학습할 수 있도록 최적화되어 있으며, 스트리밍 방식으로 메모리 효율적으로 데이터를 처리할 수 있다.
  • 간단한 API를 제공
  • 텍스트의 의미적 관계를 학습하거나 토픽 분류, 문서 추천 등 다양한 작업에 활용

'AI공부 > 자연어처리' 카테고리의 다른 글

5. RNN(Recurrent Neural Network)기초  (1) 2026.02.22
4. FastText  (0) 2026.02.21
3. NSMC를 활용한 단어 분류  (1) 2026.02.20
1. 자연어처리  (0) 2026.02.16
0. 텐서플로우  (1) 2026.02.14