- 수업 내용 리마인드 및 아카이빙 목적의 업로드
텍스트 데이터를 다룰 때 단어들의 순서와 문맥을 고려하는 것은 매우 중요해요. 특히 N-gram은 문맥을 일부 반영할 수 있는 방법으로, 인접한 단어들을 묶어 표현해주는 기법이에요. 이 글에서는 N-gram의 개념부터 실제로 어떻게 활용되는지까지 차근차근 살펴볼게요.
N-gram이란?
N-gram은 텍스트에서 연속된 n개의 단어 묶음을 의미해요. 예를 들어, "I love deep learning"이라는 문장에서 2-gram은 "I love", "love deep", "deep learning"과 같이 두 단어씩 묶은 형태가 되죠. 이렇게 하면 단순히 단어의 빈도만 고려하는 것이 아니라, 단어들의 순서를 유지하면서 문맥 정보를 파악할 수 있어요. 하지만 N-gram도 한계는 있어요. 너무 작은 n 값은 문맥 정보를 충분히 반영하지 못하고, 큰 n 값은 희소성이 커질 수 있죠. 자주 등장하는 N-gram은 불필요한 불용어와 유사한 경우도 많아요.
1. N-gram 실습
이제 실제로 영어와 한국어 문장에서 N-gram을 어떻게 생성할 수 있는지 실습해볼게요.
from nltk import ngrams
# 영어 텍스트
english_text = "I love deep learning"
english_tokens = english_text.split()
# 한국어 텍스트
korean_text = "나는 딥러닝을 좋아해"
korean_tokens = korean_text.split()
list(ngrams(english_tokens, 2)) # 2-gram
list(ngrams(korean_tokens, 3)) # 3-gram
위 코드는 각각 영어와 한국어 문장에서 2-gram과 3-gram을 생성하는 예시입니다. 이렇게 N-gram을 생성하면, 단어들의 순서와 문맥을 어느 정도 반영할 수 있답니다.
N-gram 생성 함수
N-gram을 생성하는 함수를 만들어 더 다양한 문장에 적용해볼게요.
def generate_ngrams(tokens, n):
return list(ngrams(tokens, n))
# 1-gram, 2-gram, 3-gram 생성 예제
for n in range(1, 4):
print(f"{n}-gram for English text: {generate_ngrams(english_tokens, n)}")
print(f"{n}-gram for Korean text: {generate_ngrams(korean_tokens, n)}\n")
이 함수는 주어진 단어 토큰 리스트와 n 값을 받아서 해당 N-gram을 생성해줍니다. 결과는 각 문장에서 연속된 단어 묶음으로 출력됩니다.
2. N-gram 빈도수 확인
N-gram을 생성한 후, 텍스트에서 자주 등장하는 N-gram을 분석하는 것도 중요해요. 이번에는 Gutenberg 코퍼스에서 고전 소설 "Moby Dick"의 텍스트를 가져와 N-gram의 빈도를 계산해볼게요.
1) 데이터 로드 및 전처리
먼저 NLTK에서 제공하는 Gutenberg 코퍼스의 "Moby Dick" 텍스트 데이터를 다운로드하고, 텍스트 전처리를 진행합니다.
import nltk
from nltk.corpus import gutenberg, stopwords
from nltk import ngrams
import re
nltk.download('gutenberg')
nltk.download('stopwords')
nltk.download('punkt')
# 'Moby Dick' 텍스트 데이터 로드
text = gutenberg.raw('melville-moby_dick.txt')
# 텍스트 전처리 (소문자 변환, 구두점 제거, 불용어 제거)
def preprocess_text(text):
text = text.lower()
words = nltk.word_tokenize(text)
words = [word for word in words if re.match(r'\w+', word)]
stop_words = set(stopwords.words('english'))
words = [word for word in words if word not in stop_words]
return words
processed_text = preprocess_text(text)
이 코드는 텍스트 데이터를 소문자로 변환하고 구두점을 제거한 후, 영어 불용어를 제거해 텍스트를 정제합니다.
2) N-gram 빈도 계산
이제 텍스트에서 N-gram을 생성하고, 그 빈도를 계산해봅시다.
from collections import Counter
def calculate_ngram_frequencies(tokens, n):
n_grams = list(ngrams(tokens, n))
return Counter(n_grams)
# 2-gram, 3-gram, 4-gram 빈도 계산
bigrams = calculate_ngram_frequencies(processed_text, 2)
trigrams = calculate_ngram_frequencies(processed_text, 3)
fourgrams = calculate_ngram_frequencies(processed_text, 4)
# 상위 10개의 빈도가 높은 N-gram 출력
print("Top 10 2-grams:", bigrams.most_common(10))
print("Top 10 3-grams:", trigrams.most_common(10))
print("Top 10 4-grams:", fourgrams.most_common(10))
위 코드는 각 N-gram의 빈도를 계산하고, 가장 자주 등장한 N-gram을 상위 10개씩 출력합니다. 여기서 자주 등장하는 N-gram은 주로 고래와 관련된 표현들로, 이야기의 중심 주제와 연관이 있음을 알 수 있습니다.
3. N-gram 빈도 시각화
마지막으로, 계산한 N-gram 빈도를 시각화해봅시다. 시각화를 통해 텍스트에서 중요한 주제나 반복되는 패턴을 한눈에 파악할 수 있어요.
import matplotlib.pyplot as plt
def plot_ngram_frequencies(ngram_counter, n, title):
ngrams, counts = zip(*ngram_counter.most_common(10))
ngrams = [' '.join(gram) for gram in ngrams]
plt.figure(figsize=(10, 6))
plt.barh(ngrams, counts, color='skyblue')
plt.xlabel('Frequency')
plt.ylabel(f'{n}-grams')
plt.title(f'Top 10 {title}')
plt.gca().invert_yaxis()
plt.show()
# 2-gram, 3-gram, 4-gram 시각화
plot_ngram_frequencies(bigrams, 2, '2-grams in Moby Dick')
plot_ngram_frequencies(trigrams, 3, '3-grams in Moby Dick')
plot_ngram_frequencies(fourgrams, 4, '4-grams in Moby Dick')
이 함수는 주어진 N-gram의 빈도를 막대그래프로 시각화해줍니다. 이를 통해 텍스트에서 어떤 표현이 자주 등장하는지 한눈에 확인할 수 있어요.
N-gram은 단어들의 순서와 문맥을 반영할 수 있는 유용한 기법입니다. 이를 통해 단순한 단어 빈도 분석을 넘어서, 텍스트에서 자주 사용되는 구나 패턴을 분석할 수 있어요. 특히 고전 문학 작품처럼 긴 텍스트에서는 중요한 주제나 반복되는 표현을 찾아내는 데 매우 유용하죠.
'+ 개발' 카테고리의 다른 글
단어 임베딩을 활용한 유사도 계산 (0) | 2024.09.09 |
---|---|
문서 표현 기법(ft. Scikit-learn & Gensim) (1) | 2024.09.08 |
단어 표현(Word Representation) (1) | 2024.09.06 |
자연어 처리를 위한 텍스트 전처리(ft.NLTK & KoNLPy) (1) | 2024.09.05 |
텍스트 마이닝 : 개념부터 활용까지 (9) | 2024.09.04 |