Colab으로 하루에 하나씩 딥러닝

텍스트 마이닝_ 1. BOW 기반의 텍스트 마이닝_3)나이브 베이즈 본문

딥러닝_개념

텍스트 마이닝_ 1. BOW 기반의 텍스트 마이닝_3)나이브 베이즈

Elleik 2022. 12. 23. 23:17
728x90

나이브 베이즈(cosine similarity)

  • 사전 확률에 기반을 두고 사후 확률을 추론하는 확률적 예측을 하는데, 이때 모든 사건이 독립사건이라는 순진한(naive) 가정을 하고 있음
  • P(A ¦ B) = (P(A ∩ B)) / (P(B))
    • 전제: 사건 B가 일어나고 사건 A가 발생함 
    • P(A): 사건 A가 일어날 확률
    • P(B): 사건 B가 일어날 확률, 사건 A가 발생하기 전 사건 B가 일어날 확률, 사전확률
    • P(A¦B): 사건 B가 일어난 후 사건 A가 일어날 확률, 조건부 확률
    • P(B¦A): 사건 A가 일어났을 때 사건 B가 앞서 일어났을 확률, 사후확률
  • 복잡하게 섞여 있는 문제를 비슷한 성격을 가진 특성(feature)으로 분류
    • 특정 영화를 보고 A와 B가 긍정적인 반응을 보였다면, 두 사람의 영화 취향이 비슷할 것이라고 일차적으로 볼 수 있음
    • 만일 A와 B가 다른 영화를 보고 상이한 반응을 보이면 나이브 베이즈 분류기를 사용하여 다차원의 문제를 해결함

나이브 베이즈 분류기를 이용한 문서 분류

2022.12.22 - [딥러닝_프로젝트] - 20 뉴스그룹 데이터 준비 및 특성 추출

 

20 뉴스그룹 데이터 준비 및 특성 추출

데이터셋 확인 및 분리 (사이킷런 20 뉴스그룹) 해당 데이터는 언론에서 나오는 기사가 아닌 게시판에 올라온 사용자들의 포스트 categories 매개 변수를 이용해 20개의 topic 중에서 원하는 토픽을

elleik.tistory.com

이전 게시물의 영화 리뷰를 기반으로 실습 진행하기 때문에 이전글 확인 후 아래의 실습을 보시는 걸 추천드립니다.
### 이전 코드 불러오기(해당 코드가 있어야 분류가 진행됨)

from sklearn.datasets import fetch_20newsgroups

# 20개 토픽 중 선택하고자 하는 토픽을 리스트로 생성
categories = ['alt.atheism', 'talk.religion.misc','comp.graphics','sci.space']

# 학습 데이터셋을 가져옴
newsgroups_train = fetch_20newsgroups(subset='train',
                                      # 매일 내용에서 hint가 되는 부분을 삭제(순수하게 내용만으로 분류)
                                      remove=("headers","footers","quotes"),
                                      categories=categories)

# 평가 데이터셋을 가져옴
newsgroups_test = fetch_20newsgroups(subset='test',
                                     remove=("headers","footers","quotes"),
                                     categories = categories)

X_train = newsgroups_train.data # 학습 데이터셋 문서
y_train = newsgroups_train.target # 학습 데이터셋 라벨

X_test = newsgroups_test.data # 평가 데이터셋 문서
y_test = newsgroups_test.target # 평가 데이터셋 라벨 

from sklearn.feature_extraction.text import CountVectorizer

cv = CountVectorizer(max_features=2000, min_df=5, max_df=0.5)

X_train_cv = cv.fit_transform(X_train)  # train set 변환

X_test_cv = cv.transform(X_test)  # test set 변환
### MultinominalNB를 사용하여 학습 후 데이터셋의 정확도 확인

from sklearn.naive_bayes import MultinomialNB

# 분류기 선언
NB_clf = MultinomialNB()

# train set을 이용해 분류기(classifier)를 학습
NB_clf.fit(X_train_cv, y_train)

# train set에 대한 예측 정확도를 확인
print('Train set score: {:.3f}'.format(NB_clf.score(X_train_cv, y_train)))

# test set에 대한 예측 정확도를 확인
print('Test set score:{:.3f}'.format(NB_clf.score(X_test_cv, y_test)))

학습 데이터에 대한 정확도가 평가 데이터에 대한 정확도보다 높음

  • MultinominalDB: 이산적인 값에 대하여 사용하기도 하지만, 간혹 연속적인 값에 대해서도 사용함
  • Train set과 Test set의 값의 차이가 크다면 과적합으로 의심할 수 있음
    • 과적합: 학습 데이터에 과하게 학습되어 일반화 성능이 떨어진 것
### predict() 메서드 이용

print('First document and label in test data: ', X_test[0],y_test[0])
print('Second document and label in test data: ', X_test[1], y_test[1])

pred = NB_clf.predict(X_test_cv[:2])

print('Predicted labels: ', pred)
print('Predicted categories: ', newsgroups_train.target_names[pred[0]], newsgroups_train.target_names[pred[1]])

실제 카테고리를 알기 위해 newsgroups_train.target_names를 사용

### 성능을 향상시키기 위해 CountVectorizer 대신 TfidVectorizer를 사용

from sklearn.feature_extraction.text import TfidfVectorizer

# CounterVectorizer와 동일한 인수 사용
tfidf = TfidfVectorizer(max_features=2000, min_df=5, max_df=0.5)
X_train_tfidf = tfidf.fit_transform(X_train)  # train set을 변환
X_test_tfidf = tfidf.transform(X_test)  # test set을 변환

# tfidf train set을 이용해 분류기를 새로 학습
NB_clf.fit(X_train_tfidf, y_train)

# train set에 대한 예측 정확도를 확인
print('Train set score; {:.3f}'.format(NB_clf.score(X_train_tfidf, y_train)))

# test set에 대한 예측 정확도를 확인
print('Test set score: {:.3f}'.format(NB_clf.score(X_test_tfidf, y_test)))

평가 데이터셋이 기존 73.2%에서 74.1%로 향상됨

성능 개선 방법

  • CountVectorizer의 매개 변수인 max_features, min_df, max_df의 변경
  • 나이브 베이즈의 매개변수 조절
  • 나이브 베이즈 이외의 머신러닝 알고리즘 사용
### 카테고리별로 계수가 큰 10개의 특성 출력

import numpy as np

def top10_features(classifier, vectorizer, categories):
  feature_names = np.asarray(vectorizer.get_feature_names_out())
  for i, category in enumerate(categories):
      # 역순으로 정렬하기 위해 계수에 음수를 취해 정렬 후 앞에서부터 10개의 값을 반환
      top10 = np.argsort(-classifier.coef_[i])[:10]
      # 카테고리와 영향이 큰 특성 10개를 출력
      print("%s: %s" %(category, ", ".join(feature_names[top10])))

top10_features(NB_clf, tfidf, newsgroups_train.target_names)

네 카테고리별로 영향을 많이 미친 상위 10개 단어 결과

특성 출력 결과

  • alt.atheism: 특징이 불명확
  • comp.grphics: 'graphics'라는 카테고리와 동일한 단어가 포함
  • sci.space: 'space'라는 카테고리와 동일한 단어가 포함
  • talk.religion.misc: 'god'이라는 단어가 존재
참고: 박상언, 『파이썬 텍스트 마이닝 완벽 가이드』, 위키북스(2022)