[데이터분석] 부트캠프 TIL

20260312 TIL

myun0506 2026. 3. 12. 21:47

[Today I Learn]

- 텍스트 빈도 분석


[텍스트 빈도 분석]

날짜: 2026-03-12

과목: 텍스트 분석

키워드: 텍스트 전처리, 정규 표현식, 형태소 분석, CountVectorizer, TF-IDF, N-gram


1. 데이터 로드 및 탐색

  • 결측치 제거 후 유효 리뷰 1,428건으로 분석을 시작했다.
  • 별점 기준으로 긍정(4~5점) / 부정(1~3점) 라벨을 생성했다.
    • 긍정: 1,301건 / 부정: 127건
df['label'] = (df['rating'] >= 4).astype(int)

2. 텍스트 전처리 파이프라인

텍스트 데이터는 원본 그대로 분석하면 노이즈가 너무 많다. HTML 태그, URL, 특수문자, 오타, 반복 문자 등이 섞여있기 때문에 전처리 파이프라인을 거쳐 텍스트를 정리해야 한다.

(1) 정제 (Cleaning)

  • 목적: 분석에 불필요한 문자/기호를 제거
  • HTML 태그 → URL → 특수문자 → 여러 공백 순서로 제거
text = re.sub(r'<[^>]+>', '', text)       # HTML 태그 제거
text = re.sub(r'http\\S+', '', text)       # URL 제거
text = re.sub(r'[^가-힣a-zA-Z\\d\\s]', ' ', text)  # 한글/영문/숫자/공백만 남기기
text = re.sub(r'\\s+', ' ', text).strip()  # 여러 공백을 하나로

(2) 정규화 (Normalization)

  • 목적: 같은 의미의 다른 표현을 통일
  • 예: ㅋㅋㅋㅋㅋ → ㅋㅋ, GOOD → good
def normalize_text(text):
    text = re.sub(r'(.)\\1{2,}', r'\\1\\1', text)  # 같은 문자 3번 이상 → 2번으로 축소
    return text

(3) 형태소 분석 (Tokenization)

영어 vs 한국어 토큰화 차이

영어 한국어

방법 공백으로 쉽게 분리 형태소 분석 필수
이유 단어가 독립적 교착어 → 조사/어미 결합
예시 "I love this" → ["I", "love", "this"] "자세교정이 됩니다" → ["자세", "교정", "이", "되", "ㅂ니다"]

kiwipiepy 형태소 분석기

  • C++로 작성되어 빠른 속도와 높은 정확도
  • pip만으로 설치 완료 (Java 불필요)
  • 주요 파라미터: normalize_coda, z_coda, split_complex, stopwords 등
  • 오타 교정 옵션: 'basic', 'continual', 'lengthening' 등 제공 (속도·메모리 트레이드오프 있음)
kiwi = Kiwi()

def extract_morphs(text):
    target_tags = {'NNG', 'NNP', 'VA'}  # 일반명사, 고유명사, 형용사
    tokens = kiwi.tokenize(text, normalize_coda=True)
    morphs = [token.form for token in tokens if (token.tag in target_tags) and (len(token.form) > 1)]
    return morphs

(4) 불용어 제거 (Stopword Removal)

  • 불용어: 분석에 의미 없는 고빈도 단어 (예: "정말", "진짜", "너무")
  • 범용 불용어 리스트(stopwords-ko)를 기반으로, 도메인에 맞게 직접 수정하는 것이 핵심
  • 범용 리스트 → 분석 결과 확인 → 추가/제거를 반복하는 과정이 실무에서 중요하다
def remove_stopwords(morphs, stopwords):
    return [word for word in morphs if word not in stopwords]

(5) 전처리 파이프라인 통합

(1)~(4) 단계를 하나의 함수로 통합하고, 최종 결과를 공백으로 연결된 문자열로 반환한다.

→ 이 형태가 CountVectorizer, TfidfVectorizer에 입력할 수 있는 형식이다.

def preprocess_pipeline(text):
    text = clean_text(text)
    text = normalize_text(text)
    morphs = extract_morphs(text)
    morphs = remove_stopwords(morphs)
    return ' '.join(morphs)

3. CountVectorizer와 N-gram 빈도 분석

CountVectorizer란?

전처리된 텍스트를 **숫자 행렬(빈도 행렬)**로 변환하는 도구. 각 문서에서 단어가 몇 번 등장했는지를 행렬로 만들어준다.

N-gram 종류

N-gram 설명 예시 용도

Unigram (1,1) 단일 단어 "자세", "어깨" 워드클라우드, 기본 빈도 분석
Bigram (2,2) 2단어 조합 "자세 교정", "어깨 통증" 주제 파악, 감성 분석 보완
Unigram+Bigram (1,2) 단일 + 2단어 위 두 가지 통합 TF-IDF, 분류 모델 피처

핵심 코드

# Unigram
uni_vec = CountVectorizer(ngram_range=(1, 1))
unigram_matrix = uni_vec.fit_transform(df_sample['processed'])
unigram_counts = unigram_matrix.sum(axis=0).A1

# Bigram
bigram_vec = CountVectorizer(ngram_range=(2, 2))
bigram_matrix = bigram_vec.fit_transform(df_sample['processed'])

fit_transform 주의사항

  • fit_transform은 훈련 데이터에만 사용
  • 테스트 세트/새 데이터에는 반드시 transform만 사용해야 함 (훈련 시 기준 유지)

실무 팁

  • EDA 단계: (1,1) Unigram이 가장 보편적
  • 분류/감성 분석 모델링: (1,2)가 가성비 가장 좋음
  • 주제/문맥 분석: (2,2) 또는 (2,3) Bigram/Trigram 사용
  • (1,3) 이상은 토큰 수가 폭발적으로 증가하여 효율 저하

4. TF-IDF 벡터화 및 핵심 키워드 추출

TF-IDF란?

요소 의미 해석

TF (단어 빈도) 하나의 문서 안에서 단어 등장 빈도 높을수록 → 그 문서 안에서 중요
IDF (역문서 빈도) 전체 문서 중 해당 단어가 포함된 문서가 얼마나 적은가 적은 문서에만 등장할수록 → 차별적
TF-IDF = TF × IDF 특정 문서에서 자주 나오면서 다른 문서에는 잘 안 나오는 단어 높을수록 → 핵심 키워드!

긍정/부정 그룹별 TF-IDF 키워드 추출

def get_top_tfidf_keywords(tfidf_matrix, feature_names, indices, top_n=20):
    group_tfidf = tfidf_matrix[indices].mean(axis=0).A1
    top_indices = group_tfidf.argsort()[-top_n:][::-1]
    return [(feature_names[i], group_tfidf[i]) for i in top_indices]

코드 해석:

  • tfidf_matrix[indices].mean(axis=0).A1 → 해당 그룹 내 각 단어의 평균 중요도
  • argsort()[-top_n:][::-1] → 점수 높은 순으로 상위 N개 인덱스 추출

min_df / max_df 필터링

파라미터 의미 효과

max_df=0.85 전체 문서의 85% 이상에 등장하는 단어 제거 자동 불용어 제거
min_df=3 3개 미만의 문서에 등장하는 단어 제거 희귀 단어(노이즈) 제거

⚠️ 주의: min_df와 max_df는 단어의 출현 횟수가 아니라, 해당 단어가 포함된 문서의 수를 기준으로 한다.

tfidf_filtered_vec = TfidfVectorizer(
    ngram_range=(1,1),
    max_features=3000,
    max_df=0.85,
    min_df=3
)
  • max_features: 빈도수 높은 순서대로 상위 N개의 단어만 사전에 포함
  • 필터링 후: 모든 리뷰에 공통 등장하던 일반 단어가 제거되고, 각 그룹을 더 잘 대표하는 차별적 키워드가 상위에 올라온다.

📌 오늘의 핵심 요약 3줄

  1. 텍스트 분석의 기본은 정제 → 정규화 → 형태소 분석 → 불용어 제거의 전처리 파이프라인이며, 이 과정을 통해 노이즈를 제거하고 분석 가능한 형태로 변환한다.
  2. CountVectorizer로 단어 빈도 행렬을 만들고, N-gram을 활용하면 단일 단어뿐 아니라 2~3단어 조합의 문맥 패턴까지 포착할 수 있다.
  3. TF-IDF는 단순 빈도를 넘어 "특정 문서에서만 중요한 단어"를 찾아주며, min_df/max_df 필터링으로 노이즈와 범용 단어를 제거하면 더 차별적인 핵심 키워드를 추출할 수 있다.

 

'[데이터분석] 부트캠프 TIL' 카테고리의 다른 글

20260316 TIL  (1) 2026.03.16
20260313 TIL  (0) 2026.03.13
20260311 TIL  (0) 2026.03.11
20260305 TIL  (0) 2026.03.05
20260304 TIL  (0) 2026.03.04