https://hanglestocks.tistory.com/109#google_vignette
내가 시험공부하려고 만든 자연어처리-전처리 3탄(벡터화)
1. 벡터화(Vectorization)란 무엇인가? (정의 및 핵심 아이디어)가장 먼저 '벡터화'가 무엇인지 정확히 알아야 합니다.정의벡터화란 우리가 사용하는 자연어(예: 한국어, 영어 문장)를 컴퓨터가 이해
hanglestocks.tistory.com
📌 1. 정수 인코딩(Integer Encoding)이란?
정의
정수 인코딩이란 텍스트 데이터를 컴퓨터가 처리할 수 있도록, 각 단어(토큰)에 고유한 정수(Integer)를 부여(mapping)하는 과정입니다.
이전 단계에서 배운 '벡터화'의 가장 기초적인 방법 중 하나예요. 컴퓨터는 '오늘', '날씨' 같은 한글 단어를 직접 이해하지 못하기 때문에, 미리 만들어 둔 **단어 사전(Vocabulary)**을 기준으로 각 단어를 숫자 ID로 바꿔주는 거죠.
- 핵심 원리:
- 가지고 있는 전체 텍스트(코퍼스)에서 모든 단어를 뽑아 중복을 제거한 단어 사전을 만든다.
- 사전에 있는 각 단어에 1부터 시작하는 고유한 정수 번호를 붙인다.
- 문장이 들어오면, 문장을 단어 단위로 쪼갠 뒤, 각 단어를 사전에서 찾아 해당 정수 번호로 변환한다.
결과적으로 "오늘 날씨가 좋다"라는 문장은 [1, 2, 3] 과 같은 **숫자의 나열(Sequence)**이 되고, 이 숫자 시퀀스가 컴퓨터 모델의 입력값으로 사용됩니다.
🔢 2. 정수 인코딩 예시로 과정 이해하기
슬라이드에 나온 예시를 통해 과정을 하나하나 뜯어보겠습니다.
- 문장 1: "오늘 날씨가 좋아요"
- 문장 2: "내일 날씨를 알려주세요"
1단계: 토큰화 및 단어 사전(Vocabulary) 구축
먼저, 두 문장에 있는 모든 단어를 뽑아내고 기본형으로 바꾼 뒤(표제어 추출), 중복을 제거해서 사전을 만듭니다.
- 문장 1에서 나온 단어: "오늘", "날씨", "좋다"
- 문장 2에서 나온 단어: "내일", "날씨", "알려주다"
- → 최종 단어 사전: {"오늘", "날씨", "좋다", "내일", "알려주다"}
2단계: 각 단어에 고유 정수 부여
이제 사전의 각 단어에 1부터 시작하는 번호를 붙여줍니다.
- {"오늘": 1, "날씨": 2, "좋다": 3, "내일": 4, "알려주다": 5}
- (💡 시험 포인트!) 여기서 정수를 부여하는 기준은 여러 가지가 될 수 있습니다. 그냥 가나다순으로 할 수도 있고, 이미지에 노란색으로 강조된 것처럼 빈도수를 고려할 수도 있습니다. 즉, 텍스트 전체에서 자주 등장하는 단어에 더 낮은 번호(예: 1번, 2번)를 부여하는 방식이 일반적입니다. "날씨"는 두 문장에 모두 등장했으니 가장 빈도수가 높다고 볼 수 있겠네요. (예시에서는 편의상 순서대로 부여했습니다.)
3단계: 문장을 정수 시퀀스로 변환
만들어진 사전을 바탕으로 원래 문장을 변환합니다.
- 문장 1 인코딩: "오늘 날씨 좋다" → [1, 2, 3]
- 문장 2 인코딩: "내일 날씨 알려주다" → [4, 2, 5]
이제 컴퓨터는 [1, 2, 3]이라는 숫자 배열을 보고 "오늘 날씨가 좋아요"라는 문장으로 인식하고 처리할 수 있게 됩니다.
👍👎 3. 정수 인코딩의 장점과 단점 (★시험 핵심★)
정수 인코딩은 간단하지만 명확한 한계가 있습니다. 이 장단점을 비교하는 문제가 시험에 자주 나옵니다.
장점 (Advantages)
- 구현이 간단하고 직관적이다
- 사전 만들고, 각 단어를 해당하는 숫자로 바꾸기만 하면 되므로 원리가 매우 단순하고 이해하기 쉽습니다.
- 텍스트를 빠르게 숫자로 변환 가능하다
- 복잡한 계산 없이 사전을 조회(lookup)하는 방식이라 처리 속도가 매우 빠릅니다.
단점 (Disadvantages)
- 단어 간 의미/유사성 반영 불가 (가장 큰 문제!)
- 예를 들어 '날씨'는 2번, '내일'은 4번입니다. 숫자의 크기(4 > 2)는 단어의 의미와 아무런 관련이 없습니다. '오늘'(1번)과 '내일'(4번)이 '알려주다'(5번)보다 의미적으로 더 가까운데도, 정수 값만으로는 이런 관계를 전혀 알 수 없습니다.
- 모델이 숫자 자체의 크기나 순서에서 어떤 패턴을 학습하려는 오해를 불러일으킬 수 있습니다.
- 사전 크기가 커지면 관리 어려움
- 분석해야 할 텍스트의 양이 방대해지면 사전에 있는 단어의 수가 수만, 수십만 개로 늘어납니다. 이렇게 되면 사전을 메모리에 유지하고 관리하는 것이 부담될 수 있습니다.
- OOV (Out-of-Vocabulary) 문제
- OOV란 **'사전에 없는 단어'**를 의미합니다. 학습할 때 만든 사전에 없던 새로운 단어(신조어 등)가 테스트 문장에 나타나면, 이를 어떤 숫자로 바꿔야 할지 알 수 없습니다.
- 이 문제를 해결하기 위해 보통 사전에 없는 단어는 <UNK> (Unknown) 같은 특별 토큰으로 처리하지만, 이 경우 새로운 단어의 정보는 모두 잃어버리게 됩니다.
🎓 시험 대비 최종 요약
- 정수 인코딩이란? 단어를 고유한 정수 ID로 바꾸는 가장 기초적인 벡터화 방법.
- 핵심 과정: 단어 사전 구축 → 각 단어에 정수 부여 (주로 빈도수 높은 순) → 문장을 정수 배열로 변환.
- 장점: 간단하고 빠르다.
- 치명적 단점: 단어의 의미 관계를 전혀 표현하지 못하고, OOV 문제에 취약하다.
정수 인코딩은 그 자체로 쓰이기보다는, 이후에 배울 원-핫 인코딩이나 워드 임베딩으로 나아가기 위한 중간 단계로 이해하는 것이 중요합니다. 이 단점들을 극복하기 위해 더 발전된 벡터화 기법들이 등장했기 때문입니다.
전체 과정은 "원시 텍스트 → 텍스트 정제 → 단어 빈도수 계산 → 정수 부여" 순서로 진행됩니다. 각 단계를 슬라이드와 함께 따라가 보겠습니다.
1단계: 원시 텍스트 준비 (Slide 11)
raw_text = "A barber is a person. a barber is good person. a barber is huge person. he Knew A Secret! The Secret He Kept is huge secret. His barber kept his word. A barber kept his word. His barber kept his secret. But keeping and keeping such a huge secret to himself was driving the barber crazy. the barber went up a huge mountain."
- 설명: 모든 것은 이 raw_text라는 변수에 담긴 하나의 긴 문자열에서 시작됩니다. 우리가 분석하고 처리해야 할 원본 데이터이죠. 문장 부호, 대소문자 등이 모두 섞여 있는, 아직 정제되지 않은 상태입니다.
2단계: 텍스트 정제 및 토큰화 (Slide 12)
이제 지저분한 원본 텍스트를 깨끗하게 다듬는, 전처리(Preprocessing) 과정을 거칩니다. 코드가 길어 보이지만, 하나씩 보면 간단합니다.
# 문장 토큰화
from nltk.tokenize import sent_tokenize, word_tokenize
from nltk.corpus import stopwords
sentences = sent_tokenize(raw_text)
# 출력: ['A barber is a person.', 'a barber is good person.', ...]
- 문장 토큰화 (sent_tokenize): 먼저 긴 텍스트를 ., ?, ! 등을 기준으로 문장 단위로 자릅니다. sentences는 이제 각 문장이 하나의 원소로 들어있는 리스트가 됩니다.
# 단어 토큰화 및 정제
preprocessed_sentences = []
stop_words = set(stopwords.words('english')) # 불용어 집합
for sentence in sentences:
tokenized_sentence = word_tokenize(sentence) # 문장을 단어로 쪼갬
result = []
for word in tokenized_sentence:
word = word.lower() # 1. 모든 단어를 소문자로 변환
if word not in stop_words: # 2. 불용어 제거
if len(word) > 2: # 3. 길이가 2 이하인 단어 제거
result.append(word)
preprocessed_sentences.append(result)
print(preprocessed_sentences)
# 출력: [['barber', 'person'], ['barber', 'good', 'person'], ...]
- 단어 토큰화 및 정제 (for 반복문): 각 문장을 순회하며 단어를 쪼개고 깨끗하게 만듭니다.
- word_tokenize(sentence): 문장을 ['A', 'barber', 'is', 'a', 'person', '.'] 처럼 단어와 문장부호 단위로 쪼갭니다.
- 핵심 정제 과정 (안쪽 for 반복문)
- word.lower(): 'Barber'와 'barber'를 같은 단어로 취급하기 위해 모두 소문자로 통일합니다.
- if word not in stop_words: stop_words는 'a', 'is', 'the' 와 같이 문법적으로는 필요하지만 의미 분석에는 큰 도움이 안 되는 불용어 목록입니다. 이들을 제거하여 핵심 단어만 남깁니다.
- if len(word) > 2: 길이가 짧은 단어(예: 's', 'to')는 보통 의미가 없거나 문법 요소인 경우가 많아 제거합니다.
- 결과: preprocessed_sentences에는 위 정제 과정을 모두 거친 단어들만 문장 단위로 묶여서, 2차원 리스트 형태로 저장됩니다.
3단계: 단어 리스트 통합 (Slide 13)
all_words_list = sum(preprocessed_sentences, [])
print(all_words_list)
# 출력: ['barber', 'person', 'barber', 'good', 'person', ...]
- 설명: 이제 각 단어의 빈도수를 세기 위해, 문장 단위로 나뉘어 있던 2차원 리스트([['barber'], ['good', 'person']])를 하나의 긴 1차원 리스트(['barber', 'good', 'person'])로 합쳐줍니다. sum(..., [])은 이런 2차원 리스트를 1차원으로 펼치는 간단한 파이썬 기술입니다.
4단계: 단어 사전 생성 및 정수 인코딩 (Slide 14, 15)
드디어 각 단어에 정수를 부여하는 핵심 단계입니다! 빈도수 높은 순서대로 번호를 부여할 겁니다.
- 단어 빈도수 계산 (Slide 14, Counter 사용)
- Counter는 리스트에 있는 각 원소(단어)가 몇 번 등장했는지 세어서 딕셔너리 형태로 만들어 줍니다. 이제 'barber'가 8번, 'secret'이 6번 나왔다는 것을 알 수 있습니다.
-
Python
from collections import Counter vocab = Counter(all_words_list) # 출력: Counter({'barber': 8, 'secret': 6, 'huge': 5, ...}) - 빈도수 상위 단어 추출 (Slide 14)
- most_common(5)는 가장 빈도수가 높은 상위 5개의 단어만 (단어, 빈도수) 형태의 튜플 리스트로 추출합니다. vocab_size를 조절해 사전의 크기를 결정할 수 있습니다.
-
Python
vocab_size = 5 vocab = vocab.most_common(vocab_size) # 출력: [('barber', 8), ('secret', 6), ('huge', 5), ('kept', 4), ('person', 3)] - 단어에 정수 ID 부여 (Slide 15, 최종 단계)
- 이제 최종 목표인 word_to_index 사전을 만듭니다.
- 빈도수 상위 단어 리스트(vocab)를 순회하면서, 가장 빈번한 'barber'부터 1번, 그다음 'secret'에 2번, ... 이렇게 차례대로 정수를 부여합니다.
- (💡 시험 포인트!) 코드를 보면 index + 1 또는 i = i + 1을 사용해 1부터 번호를 시작합니다. 0번은 보통 패딩(padding, 문장 길이를 맞추기 위한 빈 공간)이나 OOV(사전에 없는 단어)를 위해 남겨두는 것이 일반적이기 때문입니다. 이 관례를 기억해두는 것이 중요합니다.
-
Python
word_to_index = {} i = 0 for (word, frequency) in vocab: i = i + 1 word_to_index[word] = i print(word_to_index) # 출력: {'barber': 1, 'secret': 2, 'huge': 3, 'kept': 4, 'person': 5}
🎓 시험 대비 최종 요약
- 1단계 (텍스트 준비): 하나의 긴 문자열 raw_text에서 시작.
- 2단계 (정제): sent_tokenize로 문장 분리 → word_tokenize로 단어 분리 → lower()로 소문자화 → stopwords로 불용어 제거 → 짧은 단어 제거.
- 3단계 (통합): 2차원 리스트를 1차원으로 펼쳐 전체 단어 리스트 생성.
- 4단계 (인코딩): Counter로 단어 빈도수 계산 → most_common으로 상위 N개 단어 선정 → 빈도수 높은 순서대로 1부터 정수 ID 부여하여 word_to_index 사전 완성!
이제 이 word_to_index 사전을 이용하면 어떤 문장이든 정수 시퀀스로 바꿀 수 있습니다. 이 전체 흐름과 각 단계에서 사용하는 파이썬 함수들의 역할을 정확히 이해하면 시험에서 어떤 코드가 나와도 자신 있게 분석하실 수 있을 거예요!
'코딩공부 > 자연어처리' 카테고리의 다른 글
| 내가 시험공부하려고 만든 자연어처리-전처리 3탄(벡터화)-패딩 (0) | 2025.10.05 |
|---|---|
| 내가 시험공부하려고 만든 자연어처리-전처리 3탄(벡터화)-원핫인코딩 (0) | 2025.10.05 |
| 내가 시험공부하려고 만든 자연어처리-전처리 3탄(벡터화) (1) | 2025.10.05 |
| 내가 시험공부하려고 만든 자연어처리-전처리 3탄(후속처리) (0) | 2025.10.05 |
| 내가 시험공부하려고 만든 자연어처리-전처리 2탄(토큰화)-WordPiece (0) | 2025.10.05 |