1. 설명
Naive Bayes classification 사용해서 간단하게 댓글을 긍정, 부정, 중립으로 분류하도록 구현해보겠습니다.
보통 P(A|B)라고 할 수 있는데 B가 나왔을 때 A일 확률을 구하는 것입니다.
조건부 확률이라고 하고 있습니다.
베이지슷 정리를 수학적으로 보면 아래 식(1)과 같습니다.
아래 식에서 x는 분류될 문장이고, c는 분류할 class 라고 생각했습니다.
x의 확률은 계산하기 어렵기 때문에 베이즈 룰을 통해 아래와 같이 바꿀 수 있습니다.
(1)
클래스가 여러 개고 입력되는 문장의 확률은 다 같은 조건이기 때문에 날려버릴 수 있습니다.
각 클래스에서 가장 높은 값을 가지는 class에 x가 속하기 때문에 가장 큰 값을 얻습니다.
입력 문장이 여러 개의 단어로 이루어져 있기 때문에 개수를 n으로 놓고 P(x|c)는 아래식으로 변형할 수 있습니다.
변형된 조건부확률을 통해 가장 큰 확률을 얻는 식은 아래와 같습니다.
판별할 클래스는 Class = [긍정, 부정, 중립] 3가이 입니다.
확률 P(c), P(x|c)는 빈도수로 계산을 했습니다.
P(c) = 1/3
P(x|c) = count(클래스 c에 있는 x 단어 수) / count(클래스 단어 수)
예)
Class | Word |
Positive | 최고, 좋다, 굿, 너무, 짱, 예뻐, …. |
Negative | 최악, 너무, 짜증, 싫다, …. |
Neutral | 그냥, 왜, 할까, … |
test = [너무 예뻐, 좋아] 라는 단어가 들어왔을 경우
1) P(pos|t) = P (t1|pos)*P(t2|pos)*P(t3|pos)*P(pos)
2) P(neg|t) = P (t1|neg)*P(t2|neg)*P(t3|neg)*P(neg)
3) P(neu|t) = P (t1|neu)*P(t2|neu)*P(t3|neu)*P(neu)
로 계산을 했습니다.
1번, 2번만 계산 해보면
P(pos|t) = 1/6 * 1/6 * 1/6 * 1/3 = 0.0015432… 의 확률이 나옵니다.
P(neg|t) = 1/4 * 0/4 * 0/4 * 1/3 = 0
여기서 생기는 0의 확률문제는 전체 count에 1씩을 더해서 확률이 0이 되는 것을 방지합니다.
smoothing 방법
P(x|c) = count(클래스 c에 있는 x 단어 수) + 1 / count(클래스 단어 수) + count(모든 클래스 단어 수 중복x)
다시 계산하면
1) P(pos|t) = 2/18 * 2/18 * 2/18 * 1/3 = 4.572473…e-4
2) P(neg|t) = 2/16 * 1/16 * 1/16 * 1/3 = 1.627604…e-4
결과 1번 값이 크기 때문에 긍정으로 분류될 수 있습니다.
2. 생각:
인터넷에서 총 200개의 문장을 가져왔고
태그는 (보통명사, 동사, 형용사, 보조동사, 명사추정범주) 를 사용해서
['NNG', 'VV', 'VA', 'VXV', 'UN']
참고:https://docs.google.com/spreadsheets/d/1OGAjUvalBuX-oZvZ_-9tEfYD2gQe7hTGsgUpiiBSXI8/edit#gid=0
긍정, 부정, 중립으로 나눴습니다.
많은 문장을 사용한 것은 아니지만 생각보다 정확하게 분류를 했습니다.
bayesian classification은 간단하면서 굉장히 효과적인 방법인 것 같습니다.
3. 테스트 방법 :
먼저 KoNLPy 패키지가 설치되어 있어야 합니다.
(한국어 형태소 분석을 하기 위해 설치했습니다. )
http://konlpy.readthedocs.org/en/latest/
설치 후
test.txt에 판별하고 싶은 문장을 저장합니다.
tester.py를 실행시킵니다.
4. 소스
이론을 알아보기 위한 소스이기 때문에 테스트 용입니다.
- #-*- coding: utf-8 -*-
- from konlpy.tag import *
- from konlpy.utils import pprint
- #make lists
- def getting_list(filename, listname):
- while 1:
- line = filename.readline()
- str = unicode(line, 'utf-8')
- line_parse = kkma.pos(str)
- for i in line_parse:
- if i[1] == u'SW':
- if i[0] in [u'♡', u'♥']:
- listname.append(i[0])
- if i[1] in list_tag:
- listname.append(i[0])
- if not line:
- break
- return listname
- #naive bayes classifier + smoothing
- def naive_bayes_classifier(test, train, all_count):
- counter = 0
- list_count = []
- for i in test:
- for j in range(len(train)):
- if i == train[j]:
- counter = counter + 1
- list_count.append(counter)
- counter = 0
- list_naive = []
- for i in range(len(list_count)):
- list_naive.append((list_count[i]+1)/float(len(train)+all_count))
- result = 1
- for i in range(len(list_naive)):
- result *= float(round(list_naive[i], 6))
- return float(result)*float(1.0/3.0)
- # get the data
- kkma = Kkma()
- f_pos = open('positive.txt', 'r')
- f_neg = open('negative.txt', 'r')
- f_neu = open('neutral.txt', 'r')
- f_test = open('test.txt', 'r')
- # tag list (보통명사, 동사, 형용사, 보조동사, 명사추정범주)
- list_tag = [u'NNG', u'VV', u'VA', u'VXV', u'UN']
- list_positive=[]
- list_negative=[]
- list_neutral=[]
- # extract test sentence
- test_line = f_test.readline()
- test_s = unicode(test_line, 'utf-8')
- test_list=kkma.pos(test_s)
- test_output=[]
- for i in test_list:
- if i[1] == u'SW':
- if i[0] in [u'♡', u'♥']:
- test_output.append(i[0])
- if i[1] in list_tag:
- test_output.append(i[0])
- # getting_list함수를 통해 필요한 tag를 추출하여 list 생성
- list_positive = getting_list(f_pos, list_positive)
- list_negative = getting_list(f_neg, list_negative)
- list_neutral = getting_list(f_neu, list_neutral)
- ALL = len(set(list_positive))+len(set(list_negative))+len(set(list_neutral)) #전체 카운트, 함수에 들어가야한다. (all_count)
- # naive bayes 값 계산
- result_pos = naive_bayes_classifier(test_output, list_positive, ALL)
- result_neg = naive_bayes_classifier(test_output, list_negative, ALL)
- result_neu = naive_bayes_classifier(test_output, list_neutral, ALL)
- if (result_pos > result_neg and result_pos > result_neu):
- print u'긍정'
- elif (result_neg > result_pos and result_neg > result_neu):
- print u'부정'
- else:
- print u'중립'
- f_pos.close()
- f_neg.close()
- f_neu.close()
- f_test.close()
'IT > Python' 카테고리의 다른 글
윈도우환경 Docker에서 Tensorflow 사용하기 (0) | 2016.06.22 |
---|---|
color histogram 연습 (0) | 2015.06.02 |
[자연어처리] a little spell-checker using string edit distance (0) | 2014.12.19 |
파일을 만들기 전에 파일 존재 확인하는 코드 (0) | 2014.12.19 |
python beautifulsoap - table parsing (0) | 2014.12.19 |