본문 바로가기
machine learning

[SCIKITLEARN] naive bayes를 이용해서 문서 분류 하기

by 유주원 2017. 12. 18.

Naive bayes를 이용해서 문서 분류를 해보자. 

Naive bayes는 bayes 정리의 일부분이다. 앞에 Naive라는 수식어가 붙은 이유는 몇 가지 Naive한 가정을 기반으로 정의된 이론이기 때문에 Naive bayes라고 불린다. 

그렇기 때문에 우선 bayes 정리에 대해서 살펴보자.

A라는 분류 항목을 가지는 p1(x,y) 이라는 확률 방정식과 B라는 분류 항목을 가지는 p2(x,y)라는 확률 방정식이 있다고 가정을 해보자. 아래와 같은 가정이 성립할 것이다.

만약에 p1(x,y) > p2(x,y)이면, x, y는 A에 속한다.

만약에 p1(x,y) < p2(x,y)이면, x, y는 B에 속한다.

분류를 위해 우리는 p1과 p2의 확률을 계산할 수 있어야 하며, 이를 계산하기 위해서 조건부 확률을 이용한다.

항상 조건부 확률과 결합 확률의 차이가 어려웠는데 이번 기회에 개념을 다시 잡아 보고자 한다.

간단히 말해서 조건부 확률은 두 개의 확률이 서로 독립적으로 이루어 지지 않았을 때, 즉 먼저 일어난 확률이 그 다음 오는 확률에 영향을 줄 때 사용되며, 아래의 식으로 표현한다.

p(A|B)


결합 확률은 두 개의 사건이 동시에 발생할 때 (두 개의 사건이 독립적으로 발생할 때) 사용되며, 아래와 같이 사용된다.

p(A and B)


조건부 확률과 결합 확률의 가장 큰 차이는 바로 사건 간의 종속성 여부이다. 가령 예를 들어 주사위를 굴리는 문제를 생각해보자.

주사위 두개를 굴려서 결과 값이 5가 나왔을 때, 첫 번째 주사위가 1일 확률은 두 사건이 독립적이지 않음을 나타내고 이러한 문제는 조건부 확률을 이용해서 해결해야 한다. 즉, 두 개의 주사위를 굴려서 5라는 결과 값이 주어진 확률 내에서 첫 번째 주사위의 확률을 구하는 것이기 때문에 사건이 종속되어 있음을 알 수가 있다.

결합 확률의 경우는 주사위 두개를 동시에 굴리는 경우에 해당한다. 주사위 A와 B는 서로간에 영향을 미치지 않기 때문에 이러한 경우는 결합 확률을 이용해서 해결한다.

조건부 확률 중 유명한 문제가 몬테홀 문제가 있는데, 닫혀진 3개의 문 안에 차 한대가 상품으로 놓여져 있고 참가자는 문을 선택해서 차를 경품으로 선택하거나 아무 것도 없는 문을 선택할 수도 있다. 참가자가 일단 1개의 문을 선택하면 진행자는 나머지 두 문 중 차가 없는 문을 개방한다. 그리고선 참가자는 처음 선택한 문을  바꿀 수 있는 기회가 주어진다.

결합확률로 생각했을 경우 (각각의 문을 여는 사건을 독립이다라고 가정했을 경우) 확률은 진행자가 추가로 문을 열든 말든 1/3이 된다. 하지만 조건부 확률로 생각했을 때, 진행자가 다른 문을 연 순간 확률이 변하게 되는 것이다.

다시 bayes 정리로 돌아가서 우리는 위에서 언급한 조건부 확률을 이용해서 아래의 bayes 이론을 정리할 수 있다.



C는 문서 카테고리, D는 문서라고 가정하자. 우리는 해당 문서가 있을 때, 해당 카테고리인 확률을 계산할 것이다. 즉 P(C1 | D)와 P(C2 | D)를 비교해서 확률이 더 높은 값을 해당 카테고리로 분류할 것이다. 

위와 같은 비교 계산을 할 것이고 P(D)는 공통 분모로 작용할 것이기 때문에 P(D)는 삭제하자.

P(C)는 전체 카테고리 중 해당 카테고리가 발생 한 확률, P(D|C)는 C 카테고리 중 D 문서가 발생한 확률을 나타낸다. 여기서 D 안에 여러 단어가 있다고 가정하고 P(D|C)를 풀어 써보자.

C 카테고리일 때, W1,W2,...Wn 단어가 존재할 확률을 계산하는 것은 계산량이 복잡하기 때문에 각각의 단어가 C에 독립적이라는 나이브한 가정을 둠으로써 계산을 처리하는 게 바로 naive bayes 정리이다. 식은 아래와 같이 정리된다.

파이썬 코드를 이용해서 naive bayes 분류를 살펴보자.




위의 코드를 간략하게 설명하자면, 우선 scikit learn에 있는 naive bayes 모델 코드를 사용할 것이다.

단어들을 Vector로 만들기 위해 3가지 방법을 선언했는데 그 각각의 방법은 아래와 같다.

1. CountVectorizer - word의 count로 벡터를 만들어 준다. 그냥 word 단어 세기

2. HashingVectorizer - hashing trick을 사용해서 count 벡터를 만들어 준다. count vector 방법과 비슷한 것 같은데 hashing 개념이 들어간 것 같다.

3. TfidfVectorizer - word의 count를 세고 tf/idf로 가중치를 줘서 벡터를 만든다.


이렇게 vectorizer 모델을 선언 했다면, 이제는 데이터를 나누자. 데이터는 train data 7 , test data 3 비율로 나누는게 좋다.

데이터를 나눴으면 vectorizer 모델 3가지 중 한 가지 방법을 사용해서 훈련 모델을 만들고 학습시키자. 훈련 모델이 제대로 만들어 졌는지 확인해보기 위해 confusion matrix도 찍어보자. 나같은 경우에는 아래와 같이 높은 성능이 나왔다.

Accuracy on training set:
0.967624446363
Accuracy on testing set:
0.974856629514
Classification Report:
             precision    recall  f1-score   support

          0       0.98      0.92      0.95     24292
          1       0.97      0.99      0.98     71439

avg / total       0.97      0.97      0.97     95731

[[22439  1853]
 [  554 70885]]


이제 실제 데이터를 이용해서 분류 값을 예측해 보자. predict 함수를 사용해서 해당 하는 데이터의 분류값을 예측해보면 된다.