Notice
Recent Posts
Recent Comments
Link
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
Archives
Today
Total
관리 메뉴

이지훈님의 블로그

Naive Bayesian Classification (python code) 본문

ML

Naive Bayesian Classification (python code)

개발자입니다. 2017. 7. 18. 17:57

Naive Bayesian Classification < 위키피디아 >


나이브 베이즈 분류는 특성들 사이의 독립을 가정하는 베이즈 정리를 적용한 확률 분류기의 일종이다.

베이즈 정리 설명 전에 기본적인 확률에 개념을 확인해보자. 


조건부 확률 (Conditional probability) < 위키피디아 >

어떤 사건 B가 일어났을 때 사건 A가 일어날 확률을 의미한다. 사건 B가 발생했을 때 사건 A가 발생할 확률은 사건 B의 영향을 받아 변하는데 이를 조건부 확률이라 한다. 



사건 A와 B가 독립사건일 경우




결합 확률 (Joint Probability)

두 사건이 동시에 일어날 확률이다. 



두 사건이 서로 독립이라면 



독립이 아니라면 



아래 그림은 Probability Tree이다. 




우도 (Likelihood) < AI_STUDY >

가설 (hypothesis) H 에 대한 우도란, 어떤 시행의 결과 (Evidence) E 가 주어졌다 할 때, 만일 주어진 가설 H 가 참이라면, 그러한 결과 E 가 나올 정도는 얼마나 되겠느냐 하는 것이다.  우도는 관찰되지 않는 요인에 대해 영향을 받지 않는다.


사전확률(Priori)

특정 사상이 일어나기 전의 확률을 뜻한다. 베이즈 추론에서 관측자가 관측을 하기 전에 가지고 있는 확률 분포를 의미한다.


사후확률(Posteriori)

확률변수 관측에 대한 조건부 확률, 어떤 사건이 발생하였고, 이 사건이 나온 이유가 무엇인지 식으로 나타낸 것이다. P(A|B)로 표현한다. 

(B는 관측한 사건, A는 B가 나올 수 있게 한 과거의 사건)


베이즈 정리 < 위키피디아 >

두 확률 변수의 사전 확률과 사후 확률 사이의 관계를 나타내는 정리다. 베이즈 확률론 해석에 따르면 베이즈 정리는 사전확률로 부터 사후확률을 구할 수 있다.


P(B)는 B의 사전확률, 정규화 상수의 역할을 한다.

P(A)는 A의 사전확률로

P(B|A)는 우도, 사건 A가 발생한 경우 사건 B의 확률

P(A|B)는 B값이 주어진 경우에 대한 A의 사후확률


Naive Bayes





likelihood를 구하면서 분자, 분모에 +1, +2를 더해주었다. 위의 그림처럼 likelihood를 구하는 중 학습데이터가 없는 곳을 그냥 지나친다면 당연히 P(X|Y)는 0이 나온다. 때문에 특정 값을 더하여 0이 나오는 것을 방지해한다. 또한 분모에 2를 더하여 likelihood가 1이 되는 것을 막는다. 


underflow 방지

likelihood는 0~1 사이의 실수이다. likelihood를 수십번 곱하다보면 underflow가 발생할 수 있다. 

때문에 로그를 취하여 log( P(X|C ) + log( P(X|C ) log( P(X|C )... 으로 계산될 수 있게 바꿔주자.



Train 과정을 통해 label 1에 대한 likelihood가 위와 같다면 계산은

log(1-0.1) + log(1-0.1) + log(1-0.1)+ log(1-0.1) + log(1-0.1)+ log(1-0.1) + log(0.8) +.... + log(P(1)) 이 된다.

1-likelihood 에 대한  계산도 필요하다. 


Code < Github >

train acc는 83%, test acc는 84%이다. 

import numpy as np
from pathlib import Path
import os

class Naive_Bayes:
    def __init__(self, input_size, label_size):
        self.input_size = input_size
        self.label_size = label_size

    def add_label_index(self, Y):
        label_index = np.hstack( (np.arange(Y.shape[0]).reshape(Y.shape), Y) )
        return label_index

    def get_count(self, X, label_index):
        likelihood = np.ones((self.label_size, self.input_size), dtype=np.float)
        priori = np.ones((self.label_size), dtype=np.float)

        for i in range(self.label_size):
            indices = (np.where(label_index[:,1]==i)[0])
            priori[i] += len(indices)
            total = priori[i] + 1
            likelihood[i] += np.sum(X[indices], axis=0)
            likelihood[i] /= total
        priori /= label_index.shape[0]
        return likelihood, priori

    def train(self, X, Y):
        label_idnex = self.add_label_index(Y)
        likelihood, priori = self.get_count(X, label_idnex)
        self.likelihood = np.log(likelihood)
        self.zero_likelihood = np.log(1-likelihood)
        self.priori = np.log(priori)

    def test(self, X, Y):
        predict = np.zeros( (X.shape[0], self.label_size) )
        for i in range(self.label_size):
            score = np.multiply (X, self.likelihood[i])
            score += np.multiply (X==0, self.zero_likelihood[i])
            score = np.sum(score, axis=1) + self.priori[i]
            predict[:, i] = score
        predict = (np.argmax(predict, axis=1) == Y.flatten())
        acc =  len(np.where(predict == True)[0]) / Y.shape[0]
        return acc

def load(path):
    train_data = np.genfromtxt(path+'/train_data.csv', delimiter=',', dtype=float)
    train_label = np.genfromtxt(path+'/train_label.csv', delimiter=',', dtype=float)

    test_data = np.genfromtxt(path+'/test_data.csv', delimiter=',', dtype=float)
    test_label = np.genfromtxt(path+'/test_label.csv', delimiter=',', dtype=float)
    return train_data, train_label.reshape(train_label.shape[0],1), test_data, test_label.reshape(test_label.shape[0],1)


path = Path(os.path.dirname(os.path.abspath(__file__))).parent
train_data, train_label, test_data, test_label = load(str(path) + '/data')

inpust_size = train_data.shape[1]
label_size = 10
nb = Naive_Bayes(inpust_size, label_size)
nb.train(train_data, train_label)
print ('train acc > %f' %(nb.test(train_data, train_label)))
print ('test acc > %f' %(nb.test(test_data, test_label)))



'ML' 카테고리의 다른 글

Logistic Regression  (0) 2017.07.10
Decision Tree + C4.5알고리즘  (0) 2017.07.03
Decision Tree + ID3알고리즘  (0) 2017.07.01
Linear Regression  (0) 2017.04.20
Linear Classifier  (0) 2016.07.13
Comments