벡터화는 텍스트 데이터를 숫자 형태로 변환하여 머신러닝 또는 딥러닝 모델에서 처리할 수 있도록 만드는 과정입니다. 이를 위해 단어의 빈도를 기반으로 한 Bag-of-Words(BOW), TF-IDF와 같은 방법부터, 단어 간의 의미적 관계를 학습하는 Word Embedding(단어 임베딩), 문장의 문맥과 구조를 반영하는 Transformer 기반 임베딩(BERT, GPT) 등 다양한 기법이 사용됩니다. 벡터화는 단어, 문장, 문서와 같은 텍스트 데이터의 특징을 수치적으로 표현하며, 단순히 단어의 빈도를 반영하거나 의미적 유사성을 학습하여 벡터 공간에서 단어 간 관계를 나타냅니다. 데이터의 특성과 분석 목적에 따라 적절한 벡터화 기법을 선택하는 것이 중요합니다.
원-핫 인코딩(One-Hot Encoding)은 텍스트 데이터를 숫자 벡터로 변환하는 가장 단순한 방법 중 하나로, 단어 집합(vocabulary)에 있는 단어들을 고유한 숫자 벡터로 표현합니다. 이 방법은 각 단어를 벡터의 한 차원으로 지정하고, 해당 단어에만 1을 넣고 나머지는 0으로 설정합니다. 이를 통해 텍스트 데이터를 컴퓨터가 이해할 수 있는 숫자로 변환합니다. 예를 들어, 단어 집합이 ["I", "love", "Python"]이라면, "love"는 [0, 1, 0]으로 표현됩니다. 이 방법은 단어를 간단하고 직관적으로 표현할 수 있지만, 단어 간의 의미적 관계를 반영하지 못하며, 단어 집합 크기만큼 고차원 희소 벡터를 생성하므로 메모리 낭비가 큽니다.
※ 희소 벡터
희소 벡터(Sparse Vector)는 대부분의 값이 0인 벡터를 의미하며, 자연어 처리에서 원-핫 인코딩(One-Hot Encoding)과 같은 방법으로 단어를 표현할 때 자주 나타납니다. 예를 들어, 단어 집합의 크기가 10,000이라면 각 단어를 표현하는 벡터는 10,000차원이 되고, 이 중 단 하나의 위치만 1이고 나머지는 모두 0으로 채워집니다. 이러한 벡터는 메모리 낭비와 계산 복잡도를 초래하며, 특히 단어 집합이 클수록 문제가 심각해집니다. 이를 해결하기 위해 단어를 저차원의 조밀한 벡터(Dense Vector)로 변환하는 워드 임베딩(Word Embedding) 기법이 자주 사용됩니다.
Bag of Words(BOW)는 텍스트 데이터를 벡터화하는 간단한 방법으로, 문장을 구성하는 단어들의 등장 빈도를 기반으로 표현합니다. 각 문장은 단어 집합(vocabulary)의 크기만큼 차원을 가지며, 단어가 해당 문장에 몇 번 나타나는지 그 빈도를 벡터의 값으로 나타냅니다. 예를 들어, 단어 집합이 ["I", "love", "Python"]이고 문장이 "I love Python Python"이라면, 벡터는 [1, 1, 2]로 표현됩니다. 단어의 순서나 문맥은 고려되지 않고 단순히 단어의 빈도만 반영되기 때문에, 문장의 구조나 의미를 표현하는 데는 한계가 있습니다. 하지만 구현이 간단하고 텍스트 데이터를 빠르게 벡터화할 수 있어 자연어 처리의 기초적인 방법으로 널리 사용됩니다. TF-IDF와 같은 확장 기법을 통해 BOW의 단점을 보완하기도 합니다.
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) # 단어 집합 정렬
# 2. 단어에 인덱스 부여
word_to_index = {word: idx for idx, word in enumerate(vocab)}
# 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("단어 집합:", vocab)
print("단어 인덱스:", word_to_index)
print("Bag of Words 벡터:")
for i, vector in enumerate(bow_vectors):
print(f"문장 {i+1}: {vector}")
TF-IDF(Term Frequency-Inverse Document Frequency)는 텍스트 데이터에서 단어의 중요도를 측정하는 방법으로, 단어의 빈도(TF)와 역문서 빈도(IDF)를 조합하여 계산됩니다. 단어 빈도(TF)는 특정 문서에서 해당 단어가 얼마나 자주 등장하는지를 나타내고, 역문서 빈도(IDF)는 해당 단어가 다른 문서들에 얼마나 흔하게 등장하는지를 반영하여 중요도를 조정합니다. 이를 통해, 특정 문서에서 자주 등장하면서도 다른 문서에서는 잘 나타나지 않는 단어의 가중치가 높아집니다. 예를 들어, 일반적으로 모든 문서에서 자주 등장하는 단어(예: "the", "is")는 낮은 가중치를 받고, 특정 문서에서만 중요한 단어는 높은 가중치를 받습니다. TF-IDF는 문서의 내용을 잘 나타내는 단어를 식별하고, 텍스트 데이터의 벡터화를 통해 검색 엔진, 텍스트 분류 등의 작업에서 널리 사용됩니다.
※ 간단한 예제
TF-IDF는 텍스트 데이터에서 특정 문서에 중요하면서도 전체 문서에서 흔하지 않은 단어를 찾아내기 위한 효과적인 방법입니다. TF-IDF는 TF와 IDF를 곱하기 때문에, 특정 문서에서 자주 등장하면서 다른 문서에서는 잘 나타나지 않는 단어일수록 TF-IDF 값이 높아집니다. TF-IDF의 값이 높으면 해당 단어는 특정 문서에서 중요하다는 것을 뜻합니다.
import pandas as pd
from math import log
# 4개의 문서
docs = [
'먹고 싶은 사과',
'먹고 싶은 바나나',
'길고 노란 바나나 바나나',
'저는 과일이 좋아요'
]
# vocab 구축
vocab = list(set(w for doc in docs for w in doc.split()))
vocab.sort()
print(vocab)
# 총 문서의 수
N = len(docs)
print('총 문서의 수', N)
# TF를 구하는 함수
def tf(t, d):
return d.count(t)
# IDF를 구하는 함수
def idf(t):
df = 0
for doc in docs:
df += t in doc
return log(N/(df+1))
# TF와 IDF의 값을 곱하는 함수
def tfidf(t, d):
return tf(t,d)* idf(t)
result = []
# 각 문서에 대해서 아래 연산을 반복
for i in range(N):
result.append([])
d = docs[i]
for j in range(len(vocab)):
t = vocab[j]
# tf 함수를 호출 : TF 값을 계산
result[-1].append(tf(t, d))
tf_ = pd.DataFrame(result, columns = vocab)
tf_
result = []
# 각 단어에 대해서 idf값을 계산
for j in range(len(vocab)):
t = vocab[j]
# idf 함수를 호출 : IDF 값을 계산
result.append(idf(t))
# IDF 출력
idf_ = pd.DataFrame(result, index=vocab, columns=["IDF"])
idf_
result = []
for i in range(N):
result.append([])
d = docs[i]
for j in range(len(vocab)):
t = vocab[j]
# tfidf 함수를 호출 : TF-IDF 값 계산
result[-1].append(tfidf(t,d))
# TF-IDF 행렬
tfidf_ = pd.DataFrame(result, columns = vocab)
tfidf_
from sklearn.feature_extraction.text import CountVectorizer
corpus = [
'you know I want your love',
'I like you',
'what should I do ',
]
vector = CountVectorizer()
# 코퍼스로부터 각 단어의 빈도수를 기록
print(vector.fit_transform(corpus).toarray())
# 각 단어와 맵핑된 인덱스 출력
print(vector.vocabulary_)
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_)
코사인 유사도(Cosine Similarity)는 두 벡터 간의 방향(각도)을 기반으로 유사도를 측정하는 방법으로, 벡터 간의 크기가 아니라 방향이 얼마나 유사한지를 나타냅니다. 두 벡터의 코사인 유사도는 코사인 함수를 사용해 계산되며, 값의 범위는 -1에서 1 사이입니다. 두 벡터가 완전히 같은 방향이면 유사도가 1, 서로 수직이면 유사도가 0, 정반대 방향이면 유사도가 -1이 됩니다. 주로 텍스트 데이터를 벡터로 표현한 후(예: TF-IDF, 임베딩), 문서나 문장의 유사도를 계산하는 데 사용됩니다. 코사인 유사도는 벡터의 크기(빈도 차이)에 영향을 받지 않으므로, 단어 등장 횟수보다는 패턴이나 구조적인 유사성을 측정하는 데 적합합니다.
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))
LSTM과 GRU (0) | 2025.02.10 |
---|---|
RNN (0) | 2025.02.05 |
신경망 기반의 벡터화 (1) | 2025.02.04 |
IMDB Dataset를 활용한 데이터 전처리 (2) | 2025.01.22 |
자연어 처리 (1) | 2025.01.21 |