Post

머신러닝 공부 - 나이브 베이즈(Naive Bayes)를 활용한 문서 분류 파이썬 코드 예시

머신러닝 공부 - 나이브 베이즈(Naive Bayes)를 활용한 문서 분류 파이썬 코드 예시

이전 포스팅에서 나이브 베이즈(Naive Bayes)를 사용해 텍스트를 어떻게 분류할 수 있는지 개념적으로 살펴보았다.

이번에는 파이썬 머신러닝 라이브러리 scikit-learn에서 실제로 어떻게 구현하고 동작하는지 코드를 알아볼 차례.

scikit-learn 사용법

1. CounterVectorizer

scikit-learn에서 Naive Bayes 분류기를 사용하기 전에 일단 자연어(텍스트)로 이루어진 문서들을 1과 0 밖에 모르는 컴퓨터가 이해할 수 있는 형식으로 변환해야 할 거다. feature extraction, 어휘(특성) 추출 과정이라 볼 수 있다.

.fit()

일단 CountVectorizer라는 객체를 만든 후, fit() 메소드를 호출해서 학습 데이터 세트에 등장하는 어휘를 가르쳐놓아야 한다.

예를 들어 아래와 같이 코드를 작성하면

1
2
3
4
from sklearn.feature_extraction.text import CountVectorizer

vectorizer = CountVectorizer()
vectorizer.fit(["첫번째 문서 테스트", "두번째 문서 테스트"])

“첫번째”, “문서”, “테스트”, “두번째” 이렇게 총 4개의 어휘를 학습한 CountVectorizer를 만들게 된다.

직접 확인해보고 싶다면 vectorizer.vocabulary_를 출력해보면 된다. 이렇게 뜰 거다.

1
{'첫번째': 2, '문서': 1, '테스트': 3, '두번째': 0}

고유한 어휘가 딕셔너리처럼 각각의 인덱스를 가지고 있다.

.transform()

어휘 사전을 만들었으니 이제 .transform() 메서드를 호출할 수 있다. .transform()는 문자열 목록을 가져와 미리 학습해놓은 사전을 기반으로 어휘의 빈도를 세주는 거다.

아래와 같이 공백으로 구분되는 문자열로 가져와서 넣어주면

1
counts = vectorizer.transform (["직접 첫번째 테스트 두번째 테스트"])

counts에는 각 어휘가 등장한 빈도수가 저장되는 거다. counts.toarray()를 출력해보면 [[1 0 1 2]]와 같은 array를 볼 수 있다. 위에서 학습된 인덱스에 따라 개수를 세주었다. 그리고 “직접”이라는 단어는 애초에 사전에 등록된 단어가 아니기 때문에 고려하지 않는다.

이렇게 텍스트를 컴퓨터가 이해할 수 있는 숫자들로 변환시켜놓은 셈이니 이제 나이브 베이즈를 본격적으로 사용해볼 수 있다.

2. MultinomialNB

나이브 베이즈 분류기를 학습시킬 때는 당연히 2개의 파라미터가 필요하다. 위에서 여러 문서들을 .transform() 해놓은 문서-단어 행렬과 그 문서들이 어떤 분류에 속하는지 레이블을 준비해서 넣어주면 된다.

1
2
3
4
from sklearn.naive_bayes import MultinomialNB

classifier = MultinomialNB()
classifier.fit(counts, labels)

이제 새로운 문서가 등장했을 때 어떤 분류로 속할지 예측을 할 수 있다.

단, 텍스트를 바로 넣는다고 되는 게 아니다. 위에서 모델을 학습시키기 위해 학습 데이터를 문서-단어 행렬로 tranform 한 것처럼 새로운 텍스트도 tranform해서 넣어줘야 한다.

1
2
3
4
5
new_text= "이건 새로운 문서"
new_text_counts = counter.transform([new_text])

print(classifier.predict(new_text_counts))
print(classifier.predict_proba(new_text_counts))

.predict_proba()는 각 레이블로 분류될 확률을 돌려준다. 베이즈 정리로 해당 문서가 어떤 분류에 속할 확률을 각각 다 계산할 수 있기 때문이다.

나이브 베이즈 분류기를 구현하는 방법은 일단 여기까지.

주요 내용을 다시 간단히 요약해보자.

요약

  • 베이즈 정리에서 사용되는 확률을 계산하려면 레이블이 지정된 데이터 세트가 필요하다.
  • 데이터 세트에 포함된 문서에서 등장하는 어휘들이 곧 특성(feature)이다. 그리고 베이즈 정리를 적용하기 위해 이 특성(어휘)들은 모두 독립적인 것으로 가정한다.
  • 베이즈 정리를 사용하면 어떤 문서가 있을 때 그것이 특정 레이블에 속할 확률, P(레이블문서)를 계산할 수 있으며, 이 중 확률이 가장 높은 레이블로 예측을 하게 된다.

이렇게 간단해 보이긴 하지만 사실 텍스트(문서)를 나이브 베이즈로 제대로 분류하려면 그 전에 꽤 복잡한 과정을 거쳐 데이터를 잘 가공하는 게 정말 중요하다. garbage in, garbage out이라는 거.

일단 일반적으로 해볼 수 있는 작업으로는 다음과 같은 것들이 있다.

  • 문장 부호, 불용어 등을 제거한다.
  • 모든 단어를 소문자로 통일한다. (한국어는 해당사항 없지만)
  • ngram모델을 사용한다. 예를 들어 “이 음식은 너무 맛있다”는 문서가 있다면 여기서 feature는 “이”, “음식은”, “너무”, “맛있다”가 될 거다. 그러나 만약 bigram 모델을 사용하면 “이 음식은”, “음식은 너무”, “너무 맛있다”가 된다. 나이브 베이즈에서는 애초에 각 어휘들이 독립적이라고 가정하는데 이렇게 bigram 모델을 사용하면 연달아 등장하는 어휘를 고려하는 셈이니 조금 나아지는 편이다.
  • 형태소 단위로 쪼개서 집어 넣는다. 예를 들면 “공부하다”, “공부했다”, “공부하고”, “공부하는” 등의 다양한 어휘가 등장할 때 이것들 각각을 어휘로 보지 않고 “공부하-“라는 대표형으로 묶어서 보는 게 효과적이기 때문이다.
  • 특정 품사들만 선택해서 사용한다. 형태소 분석을 하면 각 어휘가 어떤 품사를 지니는지(태깅) 알 수 있기 때문에 이걸 바탕으로 일반명사, 고유명사, 형용사, 동사, 일반부사 위주로 사용하면 결과가 더 좋을 수도 있다. 물론 케바케다. 게다가 형태소를 나누는 기준이나 체계도 딱 정해져 있는 건 아니라…

사실 텍스트 분석은 생각보다 어렵다.


시리즈: 머신러닝 공부

  1. 학습세트, 평가세트를 나누는 이유와 방법
  2. 선형회귀(Linear Regression) 쉽게 이해하기
  3. 선형회귀(Linear Regression) 파이썬 코드 예시
  4. 다중선형회귀(Multiple Linear Regression) 파이썬 코드 예시
  5. 두 점 사이의 거리 공식(Distance Formula) 쉽게 이해하기
  6. 정규화(Normalization) 쉽게 이해하기
  7. K-최근접 이웃(K-Nearest Neighbor) 쉽게 이해하기
  8. K-최근접 이웃(K-Nearest Neighbor)을 활용한 분류 파이썬 코드 예시
  9. K-최근접 이웃(K-Nearest Neighbor)을 활용한 회귀 파이썬 코드 예시
  10. 분류 모델의 성능 평가 지표 (Accuracy, Recall, Precision, F1)
  11. 오버피팅(Overfitting)의 개념과 해결 방법
  12. 로지스틱 회귀(Logistic Regression) 쉽게 이해하기
  13. 로지스틱 회귀(Logistic Regression) 파이썬 코드 예시
  14. 의사결정 나무(Decision Tree) 쉽게 이해하기
  15. 랜덤 포레스트(Random Forest) 쉽게 이해하기
  16. 베이즈 정리 (Bayes’ Theorem) 쉽게 이해하기
  17. 나이브 베이즈(Naive Bayes)를 활용한 문서 분류 쉽게 이해하기
  18. 나이브 베이즈(Naive Bayes)를 활용한 문서 분류 파이썬 코드 예시  ← 현재 글
  19. K-Means 클러스터링 쉽게 이해하기
  20. 서포트 벡터 머신(Support Vector Machine) 쉽게 이해하기
  21. Bag-of-Words(BoW) 쉽게 이해하기
This post is licensed under CC BY 4.0 by the author.