https://hanglestocks.tistory.com/109

 

내가 시험공부하려고 만든 자연어처리-전처리 3탄(벡터화)

1. 벡터화(Vectorization)란 무엇인가? (정의 및 핵심 아이디어)가장 먼저 '벡터화'가 무엇인지 정확히 알아야 합니다.정의벡터화란 우리가 사용하는 자연어(예: 한국어, 영어 문장)를 컴퓨터가 이해

hanglestocks.tistory.com

 

 

🧠 1. 모든 것의 시작: 분포 가설 (Distributional Hypothesis)

카운트 기반 벡터화 방법을 이해하려면, 그 바탕에 깔린 핵심 철학인 **'분포 가설'**을 먼저 알아야 합니다.

정의

분포 가설이란 **"어떤 단어의 의미는 그 단어 주변에 함께 나타나는 단어들(문맥, context)에 의해 결정된다"**는 아이디어입니다. 즉, 끼리끼리 논다는 말처럼, 비슷한 단어는 비슷한 환경에서 등장한다는 뜻이죠.

  • 핵심 아이디어: 비슷한 의미를 가진 단어는 비슷한 문맥에서 자주 등장한다.
  • 예시: "wine"과 "와인"은 다른 언어지만, 두 단어의 주변에는 보통 '마시다', '포도', '레드', '화이트', '치즈' 등 유사한 단어들이 함께 나타납니다. 이를 통해 우리는 'wine'과 '와인'의 의미가 매우 비슷할 것이라고 추정할 수 있습니다.

카운트 기반 접근법의 단순화

여기서 카운트 기반 방법은 한 가지 단순한 가정을 합니다. "여기서 말하는 **문맥(context)**을 그냥 문서(document) 전체라고 보자!"

이 가정에서부터 모든 것이 시작됩니다. 이제 단어의 의미는 '그 단어가 어떤 문서에서 얼마나 자주 등장하는가'를 통해 파악할 수 있다는 아이디어가 탄생합니다.


🔢 2. 구현 방법: 카운트 기반 벡터화 (Count-based Vectorization)

위의 '분포 가설'을 실제 벡터로 구현하는 방법이 바로 '카운트 기반 벡터화'입니다.

정의

카운트 기반 벡터화는 단어의 의미를 그 단어의 출현 빈도(count) 분포를 기반으로 표현하는 방식입니다.

  • 벡터 값의 의미: 벡터를 구성하는 각 숫자 값은 해당 단어(토큰)의 **출현 횟수(빈도)**를 직접적으로 의미합니다.
  • 대표적인 모델: Bag-of-Words (BoW) 모델이 여기에 속합니다. BoW는 문서에 포함된 단어들의 순서는 무시하고, 오직 각 단어가 몇 번 등장했는지만을 세어 벡터로 만듭니다. 이 결과를 표로 나타낸 것을 **문서-단어 행렬(DTM, Document-Term Matrix)**이라고 합니다.

의미와 유사성 추론

이 방식을 사용하면 다음과 같은 추론이 가능해집니다.

  • 텍스트의 의미: 특정 단어들의 출현 분포를 통해 텍스트 전체의 주제나 의미를 유추할 수 있습니다. (예: '농구', '선수', '득점'이라는 단어가 많이 등장하면 스포츠 관련 문서일 확률이 높다.)
  • 텍스트 간 유사성: 두 문서에 등장하는 단어들의 분포가 비슷하다면, 두 문서는 서로 유사하다고 판단할 수 있습니다.

🎯 3. 벡터화의 지향점 (그리고 카운트 기반 방식의 한계)

그렇다면 이 카운트 기반 벡터화는 우리가 궁극적으로 원하는 '이상적인 벡터'를 만들어 냈을까요? '벡터화의 지향점'과 비교하며 평가해 보겠습니다.

벡터화의 이상적인 목표

  1. 벡터 공간의 효율적 사용: 단어(토큰)를 고차원 공간의 벡터로 매핑하여, 의미 관계를 공간상에 표현한다.
  2. 의미 유사도 표현: 비슷한 의미를 가진 단어는 벡터 공간에서 서로 가까운 벡터로 표현되어야 한다. 이를 통해 의미를 수학적으로 계산할 수 있어야 한다.

카운트 기반 벡터화의 평가 (★시험 핵심★)

  • 어떤 것을 해결했나?
    • 단순히 존재 여부만 표시하던 원핫 인코딩과는 달리, '등장 빈도'라는 통계적 정보를 벡터에 담아냈습니다. 이를 통해 문서의 주제를 파악하거나 문서 간의 유사도를 계산하는 데는 어느 정도 성공했습니다.
  • 무엇이 여전히 문제인가? (한계점)
    1. 벡터 공간의 비효율성: 여전히 벡터의 차원은 전체 단어 사전의 크기와 동일하여 고차원이며, 대부분의 값이 0인 **희소 벡터(Sparse vector)**입니다. 이는 차원의 저주(Curse of Dimensionality) 문제를 그대로 가지고 있습니다.
    2. 의미 유사도 표현 실패: 가장 결정적인 한계입니다. 카운트 기반 벡터화는 '단어 자체'의 의미를 표현하지 못합니다. 예를 들어 '고양이'와 '강아지'는 의미가 매우 유사하지만, BoW 벡터 상에서는 이 두 단어 벡터 역시 서로 아무 관계가 없는(직교하는) 벡터일 뿐입니다. 단어 간의 의미적 유사성을 벡터 거리로 계산할 수 없습니다.

🎓 시험 대비 최종 요약

  • 핵심 이론: 분포 가설 ("단어의 의미는 주변 단어로부터 나온다").
  • 구현 방식: 분포 가설의 '문맥'을 '문서'로 단순화하여, 문서 내 **단어의 출현 횟수(count)**를 벡터 값으로 사용하는 것 (대표 예시: Bag-of-Words).
  • 성과와 한계:
    • 성과: 문서의 주제 파악 및 문서 간 유사도 계산이 가능해짐.
    • 한계: 여전히 고차원/희소 벡터 문제를 가지며, 결정적으로 단어 간의 의미적 유사성을 벡터에 담아내지는 못했다.

이러한 한계 때문에, 이후에는 단어의 의미 자체를 저차원의 밀집 벡터(Dense Vector)에 담아내는 **TF-IDF(카운트 기반의 발전형)**나 예측 기반의 Word2Vec 같은 방법들이 등장하게 됩니다. 이 전체적인 흐름을 이해하는 것이 중요합니다!

 

Bag-of-Words (BoW)는 카운트 기반 벡터화의 가장 대표적인 모델입니다. 


👜 1. Bag-of-Words (BoW)란 무엇인가?

개념 (The "Bag" Analogy)

**Bag-of-Words (BoW)**는 이름 그대로 텍스트를 **'단어들의 가방'**으로 취급하는 모델입니다. 문장에서 모든 단어를 꺼내 순서나 문법 구조는 다 무시하고 그냥 하나의 가방 안에 뒤죽박죽 섞어 넣는다고 상상해 보세요.

이 가방에서 우리가 관심을 갖는 것은 딱 하나, "어떤 단어가 몇 번 들어있는가?" 입니다.

  • 핵심 아이디어: 텍스트를 단어(토큰)들의 집합으로 보고, 각 단어가 등장한 빈도(frequency) 정보만을 사용하여 텍스트를 숫자 벡터로 표현합니다.
  • 무시하는 것 (🚨 시험 포인트!): 단어의 순서나 문법을 완전히 무시합니다. 예를 들어, "소년이 소녀를 사랑한다"와 "소녀가 소년을 사랑한다"는 의미가 전혀 다르지만, BoW 모델에게는 완전히 동일한 텍스트로 보입니다. (두 문장 모두 '소년', '소녀', '사랑한다'가 한 번씩 들어있기 때문이죠.)
  • 결과: 텍스트는 최종적으로 각 단어의 빈도를 나타내는 **'토큰 빈도 벡터'**로 표현됩니다.

🛠️ 2. BoW 벡터 생성 과정 (Step-by-Step)

BoW 벡터(및 행렬)는 크게 두 단계로 만들어집니다.

1단계: 어휘집(Vocabulary) 구축 과정

먼저 전체 텍스트 데이터(코퍼스)를 기반으로 기준이 될 **어휘집(단어 사전)**을 만듭니다.

  1. 토큰화(Tokenization): 가지고 있는 모든 텍스트를 문장이나 단어 같은 토큰 단위로 쪼갭니다.
  2. 정제(Cleaning): 불필요한 기호(마침표, 쉼표 등)나 큰 의미가 없는 불용어(stopwords, 예: a, the, 은, 는)를 제거합니다.
  3. 고유 토큰 추출: 모든 텍스트에서 등장한 단어들의 중복을 없애고 고유한 단어들만 남깁니다. 이것이 바로 어휘집이 됩니다.
  4. 인덱스 부여: 어휘집에 있는 각 고유 토큰에 고유한 번호(인덱스)를 부여합니다.
  • 예시:
    • 문장1: "오늘 날씨가 좋아요" → ["오늘", "날씨", "좋다"]
    • 문장2: "내일 날씨를 알려주세요" → ["내일", "날씨", "알려주다"]
    • → 최종 어휘집: {"오늘": 1, "날씨": 2, "좋다": 3, "내일": 4, "알려주다": 5}

2단계: 문서-단어 행렬 (DTM) 생성

어휘집이 완성되면, 각 문장(문서)을 이 어휘집을 기준으로 벡터화하여 **문서-단어 행렬(Document-Term Matrix, DTM)**을 만듭니다.

  • 행(row): 각 문장 또는 문서
  • 열(column): 어휘집에 있는 모든 고유 토큰
  • 값(value): 해당 문서(행)에 해당 토큰(열)이 등장한 횟수 (Term Frequency, TF)
  • 예시 DTM:
토큰 오늘 날씨 좋다 내일 알려주다
문장1 1 1 1 0 0
문장2 0 1 0 1 1
  • 결과 해석:
    • 문장1의 BoW 벡터: [1, 1, 1, 0, 0]
    • 문장2의 BoW 벡터: [0, 1, 0, 1, 1]
    • 이제 각 문장은 어휘집의 차원(이 경우 5차원)을 갖는 숫자 벡터로 성공적으로 변환되었습니다!

👍👎 3. BoW의 장점과 한계 (★시험 핵심★)

장점 (Pros) 단점 (Cons)
✔️ 구현이 간단하고 이해하기 쉽다. ❌ 단어 순서를 무시하여 문맥 정보를 잃는다. (가장 치명적!)
✔️ 문서의 주제 분류에 효과적이다. (예: "선수, 경기, 골"이 많이 나오면 스포츠 문서) ❌ 희소성(Sparsity) 및 고차원 문제: 단어 수가 많아지면 벡터가 매우 길어지고 대부분이 0으로 채워져 비효율적이다. (차원의 저주)
  ❌ 단어의 의미적 유사성을 반영하지 못한다. ('강아지'와 '개'를 완전히 다른 단어로 취급)

🎓 시험 대비 최종 요약

  • BoW란? 단어의 순서는 무시하고, 오직 출현 빈도만으로 텍스트를 숫자 벡터로 만드는 방법.
  • 핵심 결과물: 문서-단어 행렬 (DTM). 여기서 각 행은 하나의 문서를 나타내는 BoW 벡터.
  • 가장 큰 특징이자 한계: 문맥 정보의 손실. "아버지가 방에 들어가신다"와 "아버지 가방에 들어가신다"를 구분하지 못함.
  • 주요 용도: 간단하면서도 효과가 좋아 텍스트 분류, 스팸 메일 필터링, 토픽 모델링 등 넓은 범위의 기초 모델로 사용됨

🔄 1. BoW 모델 프로세스 요약 (Summary Flowchart)

먼저 BoW 모델이 어떻게 동작하는지 전체적인 흐름을 다시 한번 복습해 보겠습니다. 슬라이드의 요약 이미지는 이 과정을 매우 명확하게 보여줍니다.

  1. Corpus (코퍼스): 분석하고자 하는 텍스트 문서들의 모음에서 시작합니다.
  2. Tokenize (토큰화): 각 문서를 단어(토큰)와 같은 작은 단위로 나눕니다.
  3. Count Word Frequencies (단어 빈도수 계산): 전체 문서에서 고유한 단어들로 어휘집(Vocabulary)을 만들고, 각 문서에서 어휘집의 단어들이 몇 번씩 등장하는지 횟수를 셉니다.
  4. Encode the Data (데이터 인코딩): 위에서 계산한 빈도수 정보를 바탕으로, 각 문서를 숫자 벡터로 변환합니다. 이 결과물을 모아놓은 것이 바로 **문서-단어 행렬(DTM)**입니다.

이 네 단계를 거치면, 텍스트는 컴퓨터가 이해하고 계산할 수 있는 숫자 데이터(벡터)로 변환됩니다.


📏 2. BoW의 문제점과 해결책: 텍스트 길이 문제

기본적인 BoW 모델은 한 가지 중요한 약점을 가지고 있습니다. 바로 문서의 길이에 따라 단어의 중요도가 왜곡될 수 있다는 점입니다.

문제점: 긴 문서의 함정

  • 문장1: 전체 단어 10개, "오늘" 1번 등장 → 출현 횟수: 1
  • 문장2: 전체 단어 100개, "오늘" 10번 등장 → 출현 횟수: 10

단순히 등장 횟수(count)만 보면, 문장2에서 "오늘"이라는 단어가 문장1에서보다 10배나 더 중요해 보입니다. 하지만 문장2는 길이가 10배나 길기 때문에 "오늘"이 10번 등장한 것일 수 있습니다. 오히려 전체 문서에서 "오늘"이 차지하는 비중은 문장1(1/10)과 문장2(10/100)가 동일합니다.

이처럼 단순 카운트는 긴 문서에 있는 단어에 더 높은 가중치를 부여하여, 문서 간의 공정한 비교를 어렵게 만듭니다.

해결책: 정규화된 출현 횟수, TF (Term Frequency) 사용

이 문제를 해결하기 위해 **정규화(Normalization)**를 사용합니다. 즉, 각 단어의 등장 횟수를 그 단어가 포함된 문서의 전체 단어 수로 나누어 주는 것입니다. 이것을 바로 **단어 빈도(TF, Term Frequency)**라고 합니다.

TF(단어 t, 문서 d) = (문서 d에서 단어 t의 등장 횟수) / (문서 d의 전체 단어 수)

  • 예시 DTM (TF 적용 후):
토큰 오늘 날씨 좋다 내일 알려주다
문장1 1/3 1/3 1/3 0 0
문장2 0 1/3 0 1/3 1/3

이렇게 TF를 사용하면, 각 벡터의 값은 문서 길이에 상관없이 해당 단어가 문서 내에서 차지하는 **상대적인 중요도(비중)**를 나타내게 됩니다. 따라서 문서 길이가 달라도 훨씬 공정하게 비교할 수 있습니다.


🛠️ 3. BoW의 활용 사례 (Use Cases)

BoW는 단순한 모델이지만, 그 효과가 뛰어나 여러 분야에서 널리 활용됩니다.

  • 메일 필터링 (Spam Mail Filtering)
    • 스팸 메일에는 'free', 'offer', 'money', 'win' 등의 단어가 일반 메일보다 훨씬 자주 등장합니다. BoW로 메일의 단어 빈도 벡터를 만든 후, 기계학습 모델을 통해 스팸 메일의 단어 분포 패턴을 학습시켜 스팸을 걸러낼 수 있습니다.
  • 뉴스 카테고리 분류 (News Categorization)
    • '선수', '경기', '골' 등의 단어가 많이 나오면 스포츠 기사로, '대통령', '국회', '선거' 등의 단어가 많으면 정치 기사로 분류할 수 있습니다. BoW는 문서의 주제를 파악하는 데 매우 효과적입니다.
  • 감정 분석 (Sentiment Analysis)
    • 영화 리뷰나 상품 후기에서 '최고', '추천', '만족' 같은 긍정적인 단어와 '최악', '실망', '별로' 같은 부정적인 단어의 빈도를 세어 해당 텍스트의 감정이 긍정적인지 부정적인지 판단할 수 있습니다.
  • 정보 검색 (Information Retrieval) 및 주제 추론 (Topic Modeling)
    • 사용자가 검색어를 입력했을 때, 검색어에 포함된 단어들의 빈도가 높은 문서를 찾아 보여주는 원리도 BoW에 기반합니다. 또한, 문서들의 단어 빈도 분포를 분석하여 해당 문서 집단의 주요 주제가 무엇인지 추론할 수도 있습니다.

🎓 시험 대비 최종 요약

  • BoW 프로세스: **코퍼스 → 토큰화 → 빈도수 계산 → 인코딩(DTM 생성)**의 4단계를 거친다.
  • 핵심 문제점: 문서 길이가 길수록 단어 빈도수가 부풀려져 중요도가 왜곡될 수 있다.
  • 핵심 해결책: 단순 카운트 대신, 단어 횟수를 전체 단어 수로 나눈 **정규화된 값, 즉 단어 빈도(TF)**를 사용한다.
  • 주요 활용 분야: 스팸 필터링, 뉴스 분류, 감정 분석 등 텍스트의 주제나 성격을 파악하는 대부분의 기초적인 자연어 처리 문제에 효과적으로 사용된다.

🛠️ 1. 직접 구현으로 원리 파악하기 (Manual Implementation)

이 코드는 외부 라이브러리 없이 기본적인 파이썬 문법만으로 BoW 모델의 핵심 로직을 처음부터 끝까지 만드는 과정을 보여줍니다. BoW의 동작 원리를 이해하는 데 가장 좋은 예제입니다.

코드 분석 (단계별)

  1. 데이터 준비 및 토큰화
    • 분석할 4개의 문서를 리스트로 준비합니다.
  2. Python
     
    docs = ['먹고 싶은 사과', '먹고 싶은 바나나', '길고 노란 바나나 바나나', '저는 바나나가 좋아요']
    # 실제 코드에서는 각 문서를 .split()으로 단어 리스트로 만듭니다.
    
  3. 어휘집(Vocabulary) 생성
    • 모든 문서에 있는 단어들을 모아 중복을 제거하여 고유한 단어의 집합, 즉 어휘집을 만듭니다.
    • enumerate를 사용해 어휘집의 각 단어에 0부터 시작하는 고유한 정수 인덱스를 부여한 word_to_index 딕셔너리를 생성합니다. 이것이 단어와 숫자(벡터의 위치)를 연결하는 다리 역할을 합니다.
  4. Python
     
    # 모든 문서의 단어들을 하나로 합친 후, set으로 중복을 제거해 고유 단어만 추출
    vocab = list(set(word for doc in docs for word in doc.split()))
    vocab.sort() # 순서를 보장하기 위해 정렬
    
    # 단어에 고유 인덱스 부여
    word_to_index = {word: i for i, word in enumerate(vocab)}
    
  5. BoW 벡터 생성 함수 (make_bow)
    • 이 함수가 BoW의 핵심 로직입니다.
      1. 먼저 어휘집의 크기와 동일한 길이의 0으로 채워진 리스트(bow)를 만듭니다.
      2. 입력된 문서(doc)의 단어들을 하나씩 확인합니다.
      3. word_to_index에서 해당 단어의 인덱스를 찾아, bow 리스트의 그 인덱스 위치에 있는 값을 1씩 더해줍니다.
      4. 모든 단어를 다 세면, 최종적으로 완성된 빈도수 벡터(bow)를 반환합니다.
  6. Python
     
    def make_bow(doc):
        # 1. 어휘집 크기의 0으로 채워진 벡터 생성
        bow = [0] * len(vocab)
        # 2. 입력된 문서의 단어들을 하나씩 순회
        for word in doc.split():
            # 3. 단어의 인덱스를 찾아서
            idx = word_to_index[word]
            # 4. 해당 인덱스의 값을 1 증가 (카운트)
            bow[idx] += 1
        return bow
    
  7. 실행 및 결과 확인
    • 이 make_bow 함수를 모든 문서에 대해 실행하면 슬라이드 우측에 보이는 **BoW 행렬(DTM)**이 만들어집니다.
    • 예를 들어, 3번째 문서 "길고 노란 바나나 바나나"의 벡터가 [1, 0, 2, 0, 0, 0, 0, 1]인 이유를 어휘집 ['길고', '먹고', '바나나', '사과', '싶은', '저는', '좋아요', '노란']과 비교해 보면,
      • '길고'(0번 인덱스) 1번, '바나나'(2번 인덱스) 2번, '노란'(7번 인덱스) 1번 등장했음을 정확히 알 수 있습니다.

🚀 2. Scikit-learn으로 간단하게 구현하기

이번 코드는 머신러닝 라이브러리인 Scikit-learn의 CountVectorizer를 사용합니다. 실무에서 BoW 모델을 만들 때 사용하는 표준적인 방법입니다.

코드 분석 (단계별)

  1. CountVectorizer 불러오기 및 생성
    • BoW 모델을 만들어주는 도구인 CountVectorizer를 불러와 객체를 생성합니다.
  2. Python
     
    from sklearn.feature_extraction.text import CountVectorizer
    vectorizer = CountVectorizer()
    
  3. 학습 및 변환 (fit_transform)
    • 이 한 줄이 위에서 직접 구현한 모든 과정을 알아서 처리해 줍니다.
      • fit(): 입력된 docs 데이터를 분석해서 스스로 어휘집을 만들고 단어-인덱스 매핑을 학습합니다.
      • transform(): 학습된 어휘집을 기준으로 docs 데이터를 BoW 행렬(DTM)로 변환합니다.
      • **fit_transform()**은 이 두 과정을 한 번에 수행하는 편리한 메서드입니다.
  4. Python
     
    X = vectorizer.fit_transform(docs)
    
  5. 결과 확인
    • vectorizer.get_feature_names_out(): CountVectorizer가 학습한 어휘집(DTM의 열 순서)을 보여줍니다.
    • X.toarray(): 생성된 X는 원래 메모리 효율을 위해 희소 행렬(sparse matrix) 형태로 저장되어 있습니다. .toarray()를 통해 우리가 눈으로 보기 쉬운 일반적인 행렬(Numpy 배열)로 변환하여 출력합니다.
    • 출력된 어휘집과 BoW 행렬은 위에서 직접 구현한 결과와 완전히 동일한 것을 확인할 수 있습니다.
  6. Python
     
    print("어휘집:", vectorizer.get_feature_names_out())
    print("BoW 행렬:\n", X.toarray())
    

🎓 시험 대비 최종 요약

구분 직접 구현 (Manual) Scikit-learn (CountVectorizer)
목적 BoW의 동작 원리를 단계별로 이해하기 위함 실용적이고 효율적인 BoW 모델 구현을 위함
핵심 word_to_index 딕셔너리 생성, for 루프를 통한 직접 카운팅 fit_transform() 메서드 하나로 모든 과정 자동 처리
시험 Tip 코드의 각 부분이 어휘집 생성, 인덱싱, 카운팅 중 어느 역할을 하는지 파악하는 것이 중요. CountVectorizer, fit_transform, get_feature_names_out의 기능과 역할을 암기하는 것이 중요.

결론적으로, 두 방법은 동일한 결과를 내지만, 원리 이해를 위해서는 직접 구현 코드를, 실제 문제 해결을 위해서는 Scikit-learn 코드를 알아두는 것이 좋습니다. 두 가지를 모두 이해하고 있으면 어떤 형태의 문제가 나와도 완벽하게 대비할 수 있습니다!

 

📉 Bag-of-Words (BoW)의 명확한 한계점

BoW는 구현이 간단하고 직관적이라는 장점이 있지만, 다음과 같은 4가지의 치명적인 약점을 가지고 있습니다.

1. 불용어 문제 (Stopword Problem) 🚮

  • 설명: 텍스트에는 'the', 'a', 'is'나 한국어의 '은', '는', '이', '가'와 같이 자주 등장하지만 실제 의미에는 거의 기여하지 않는 단어들이 있습니다. 이를 **불용어(Stopword)**라고 합니다.
  • BoW의 문제점: BoW는 오직 단어의 '빈도'만을 보기 때문에, 이 의미 없는 불용어들이 가장 중요한 단어인 것처럼 취급될 수 있습니다. 예를 들어, 어떤 문서의 BoW 벡터에서 '는'이라는 단어가 가장 높은 빈도수를 차지한다면, 이 벡터는 문서의 핵심 의미를 제대로 담고 있다고 보기 어렵습니다.
  • 해결책: 일반적으로 BoW 모델을 만들기 전, 텍스트 전처리 단계에서 불용어를 미리 제거하는 작업을 거칩니다.

2. 순서 정보 손실 (Loss of Word Order) 🤷

  • 설명: BoW의 가장 근본적이고 심각한 한계입니다. BoW는 단어를 '가방'에 담는다는 개념 때문에, 원래 문장에 있던 단어의 순서 정보를 완전히 무시합니다.
  • 왜 문제인가?: 단어의 순서는 문장의 의미를 결정하는 핵심적인 요소입니다.
  • (🚨 시험 단골 예시!)
    • 문장 A: "개가 사람을 물었다"
    • 문장 B: "사람이 개를 물었다"
    • 이 두 문장은 의미가 완전히 반대입니다. 하지만 BoW의 관점에서는 두 문장 모두 {'개': 1, '사람': 1, '물었다': 1} 이라는 동일한 단어 구성을 가지므로, 완전히 똑같은 벡터로 변환됩니다. 즉, BoW는 이 두 문장을 전혀 구별하지 못합니다.
  • 추가 문제: 부정(negation) 표현처럼 순서가 중요한 문맥을 파악하기 어렵습니다. 예를 들어, "이 영화는 전혀 재미있지 않다"에서 '전혀'와 '않다'의 관계를 이해하지 못하고 '재미있다'라는 단어의 존재만으로 긍정으로 잘못 판단할 수 있습니다.

3. 차원의 저주 (Curse of Dimensionality) 🌌

  • 설명: BoW 벡터의 차원(길이)은 어휘집(Vocabulary)에 있는 고유 단어의 총개수와 동일합니다.
  • 왜 문제인가?: 일반적인 텍스트 데이터(예: 뉴스 기사 모음)의 어휘집 크기는 수만 개에서 수십만 개에 달하는 경우가 흔합니다. 이는 단어 하나하나가 수만 차원의 벡터가 된다는 의미입니다.
  • 결과:
    • 계산 비용 증가: 차원이 클수록 모델이 계산해야 할 양이 기하급수적으로 늘어나 학습이 매우 느려집니다.
    • 과적합(Overfitting) 위험: 데이터의 양에 비해 차원이 너무 크면, 모델이 훈련 데이터에만 과도하게 최적화되어 새로운 데이터에 대한 예측 성능이 떨어질 수 있습니다.

4. 희소 벡터 (Sparse Representation) 문제 💨

  • 설명: 이 문제는 '차원의 저주'와 직접적으로 연결됩니다. 벡터의 차원은 수만 개로 매우 크지만, 하나의 문서에는 그중 극히 일부의 단어만 포함됩니다.
  • 왜 문제인가?: 결과적으로 BoW 벡터는 대부분의 값이 0이고 몇 개의 값만 1 이상의 수를 갖는 **희소 벡터(Sparse Vector)**가 됩니다.
  • 결과:
    • 메모리 비효율성: 수많은 0을 저장하기 위해 엄청난 메모리 공간이 낭비됩니다. (물론 실제 구현에서는 이를 해결하기 위해 희소 행렬 자료구조를 사용하지만, 근본적인 비효율성은 존재합니다.)
    • 정보 밀도 저하: 벡터 하나에 담긴 정보의 밀도가 매우 낮아, 모델이 의미 있는 패턴을 학습하기 어려워집니다.

🎓 시험 대비 최종 요약

한계점 핵심 내용 결과 및 영향
불용어 문제 의미 없는 단어(a, the, 은, 는)가 높은 빈도수를 차지함 벡터가 핵심 의미를 제대로 표현하지 못할 수 있음
순서 정보 손실 단어의 순서를 완전히 무시함 ("개가 사람을..." vs "사람이 개를...") 문맥과 뉘앙스를 파악하지 못하고, 의미가 다른 문장을 동일하게 취급함
차원의 저주 어휘집 크기만큼 벡터 차원이 커짐 계산 비용이 급증하고 모델 성능이 저하될 수 있음
희소 벡터 벡터의 대부분이 0으로 채워짐 메모리 낭비가 심하고 정보 밀도가 낮음

이러한 명확한 한계점들 때문에, 자연어 처리 기술은 BoW를 개선한 TF-IDF, 그리고 더 나아가 단어의 순서와 의미를 모두 고려하는 Word2Vec, BERT와 같은 모델로 발전하게 되었습니다. 이 전체적인 흐름을 기억해두시면 시험에 큰 도움이 될 겁니다!

+ Recent posts