愛林

[Python/ML] 분류 알고리즘 (Classification Algorithm) : 나이브 베이즈 (Naive Bayes) 본문

Data Science/Machine Learning

[Python/ML] 분류 알고리즘 (Classification Algorithm) : 나이브 베이즈 (Naive Bayes)

愛林 2022. 8. 31. 23:32
반응형

 

 

이전에는 분류에 대해서 알아보았다.

https://wndofla123.tistory.com/48?category=1078831 

 

분류 알고리즘 (Classification Algorithm), 분류 알고리즘의 종류

이전에는 회귀모델들에 대해 알아보았다. 회귀가 궁금하다면 여기로 https://wndofla123.tistory.com/43 Python으로 배우는 데이터분석 이해 - 회귀분석 (Regression Analysis) 설명 회귀분석 (Regression Analysi..

wndofla123.tistory.com

 

분류란, 변수의 범주를 예측하는 기법으로,

다수의 속성이나 변수를 가지는 객체들을 사전에 정해놓은 그룹이나 범주 중의 하나로 분류하는 것이다.

분류 알고리즘에는 나이브 베이즈, SVM, LDA, 로지스틱 회귀 등이 있다.

 

먼저 나이브 베이즈에 대해서 알아보자.

 


나이브 베이즈 (Naive Bayes)

 

 

나이브(Naive)  하다는 것은 무슨 말일까?

나이브 하다는 것은 '소박하고 천진한' 것을 표현하는 말이다.

나이브 베이즈 모델이 어떤 것을 간단하고 소박하게 정의하고 가지 않을까?

라고 예측할 수 있다.

 

그렇다면 베이즈(Bayes) 는 무슨 말일까?

나이브 베이즈 모델에 대해서 알기 위해서는, Bayes 정리라는 것을 알아야 한다.

베이즈 정리를 사용해서 간접적으로 조건부 확률을 구하는 것을

확률적 생성 모델이라고 한다.

 

나이브 베이즈 분류 모델은 모든 차원의 개별 독립 변수가 서로 조건부 독립이라는 가정을 사용한다.

독립변수들 간에 서로 조건부 독립이라는 가정이 조건이 나이브(순진)하게 만들어지게 하고,

베이즈 정리를 사용해서 MLE(최대 가능도)를 통해 가장 큰 확률값을 갖는 모수를

추정해내는 모델이다.

 

나이브 베이즈 모델의 종류에는 가우시안 나이브 베이즈, 다항 나이브 베이즈, 베르누이 나이브 베이즈가 있다

.

가우시안 나이브 베이즈는 독립변수가 연속형 변수일 때 사용하며,

표본 평균과 표본 분산을 가진 정규분포 하에서 베이즈 정리를 사용한다.

 

다항  나이브 베이즈는 독립변수가 범주형 변수일 때 사용한다.

 

베르누이 나이브 베이즈는 독립변수가 범주형 변수일때, 범주가 2개밖에 없는 이진형일 때 사용한다.

베르누이 시행이 성공과 실패 2개밖에 없었던 것과 같다.

 

 


베이즈 정리

 

조건부 확률(Conditional probability) 란, 

시간의 관점에서 A라는 사건이 이루어진 이후에 B라는 사건이 발생할 확률이다.

조건부 확률은 위의 식으로 인해서 곱의 법칙을 가진다.

 

https://sagohak.tistory.com/190

 

 

독립사건(Independent Event) 란,

두 사건중 하나의 사건이 일어난 확률이 나머지 다른 하나의 사건이 일어날 확률에

영향을 미치지 않는다는 것이다.

예를 들어, 비 오는 날 주사위를 던진다면, 비가 온다는 것의 사건은 주사위를 던지는 사건에

영향을 주지 않는다.

 

독립사건의 조건부 확률은 아래와 같다.

독립변수가 조건부독립이라는 말은 독립사건의 조건부 확률을 말한다.

B가 일어날 때 사건A가 발생할 확률은 그냥 사건 A가 발생하는 확률과 같다.

사건A와 B가 함께 일어날 확률은 사건A가 일어날 확률과

사건 B가 일어날 확률의 곱과 같다.

 

베이즈정리는 

모든 차원의 개별 독립변수가 조건부 독립이라는 가정을 한다.

그로 인해 아래와 같은 식이 만들어진다.

사건 A가 발생했을 때 사건 B가 일어날 확률은,

사건 B가 발생했을 때 A가 일어난 확률(사건A가 일어날 확률과 같다.)과 사건B가

발생할 확률에 사건 A가 일어날 확률을 나눈 것과 같다. (사실상 사건B확률)

여기서 독립변수들은 모두 독립적으로 추출되기 때문에,

서로 영향을 끼치지 않는다. (그래서 Naive함)

 

 

 


나이브 베이즈 실습

 

 

가우시안 나이브 베이즈

 

가우시안 나이브 베이즈는 모든 변수가 연속형의 값을 가질 때 사용했다.

 

import numpy as np
import pandas as pd
import scipy as sp
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
## 가우시안 나이브 베이즈
from sklearn.naive_bayes import GaussianNB

## iris 데이터셋 로드
iris = load_iris()
df_X = pd.DataFrame(iris.data, columns=iris.feature_names)
df_Y = pd.DataFrame(iris.target, columns = ['target'])

iris 데이터를 사용했다.

 

# 테스터셋 분리
X_train, test_X, y_train, test_y = train_test_split(df_X, df_Y, train_size = 0.8,
                                                   test_size = 0.2, random_state = 123)
X_train.tail()

 

## 나이브 베이즈는 가우시안 나이브 베이즈
gnb = GaussianNB()

## 학습
# train 데이터로 학습을 진행 후, X_test 데이터로 결과를 예측하여 y_pred 입력
fitted = gnb.fit(X_train, y_train)
y_pred = fitted.predict(test_X)
y_pred
print(y_pred)
[1 2 2 1 0 2 1 0 0 1 2 0 1 2 2 2 0 0 1 0 0 1 0 2 0 0 0 2 2 0]
# 실제값과 y의 예측값을 비교하여 틀린 개수 확인
print("테스트 데이터 수 : %d, 틀린개수 : %d" % (test_X.shape[0],
                                     (np.array(test_y.target.tolist()) != y_pred).sum()))
테스트 데이터 수 : 30, 틀린개수 : 1

 

## 예측한 클래스와 해당 예측 데이터의 클래스별 확률
# 클래스
print(fitted.classes_)

# 분류된 클래스 수
print(fitted.class_count_)

# 테스트 데이터
print(test_X[:1], "\n")

# 테스트 데이터 1개에 대한 클래스가 나온 확률
print(fitted.predict_proba(test_X)[:1], "\n")

# 테스트 데이터 1개의 클래스
print(fitted.predict(test_X)[:1], "\n")
[0 1 2]
[37. 44. 39.]
    sepal length (cm)  sepal width (cm)  petal length (cm)  petal width (cm)
72                6.3               2.5                4.9               1.5 

[[7.24143720e-126 9.23061979e-001 7.69380215e-002]] 

[1] 

클래스는 0,1,2가 있다.

분류는 클래스 0에 37개, 클래스1에 44개, 클래스2에 39개로 분류되었다.

테스트 데이터의 1번째는 72번째 데이터로 위와 같은 값을 가지고 있었다.

각각의 확률은 아래와 같이 나왔다.

클래스 1일 확률 92%이다.

결론적으로는 가장 높은 확률인 1클래스로 분류되었다는 것을 알 수 있다.

 

## 특정 값의 클래스별 확률 확인
print(fitted.predict_proba(test_X)[[1,20]])

# 특정 변수의 범주별 클래스 확인
fitted.predict(test_X)[[1,20]]
[[1.81805757e-197 1.22131524e-005 9.99987787e-001]
 [1.00000000e+000 8.57846082e-017 1.77097412e-025]]
array([2, 0])

 

1번째 데이터는 2클래스일 확률이 99%,

20번째 데이터는 0클래스일 확률이 100%이므로

2, 0 으로 분류되었다.

 

# Confusion matrix 확인
from sklearn.metrics import confusion_matrix

confusion_matrix(test_y, y_pred)
array([[13,  0,  0],
       [ 0,  6,  0],
       [ 0,  1, 10]], dtype=int64)

혼동행렬(Confusion Matrix) 를 사용하여 확인해봤을 때,

0클래스는 모두 잘 분류했다.

1클래스 또한 모두 잘 분류했다.

2클래스는 1개의 오류를 제외하고는 모두 잘 분류했다.

 

 

 

다항 나이브 베이즈

 

다항 나이브 베이즈는 독립변수가 범주형 변수일 때 사용한다.

 

## Multinomial Naive Bayes
from sklearn.naive_bayes import MultinomialNB

# 난수 생성
import numpy as np

# 0부터 3까지 난수 생성, 변수 10개 , 샘플 사이즈 4개
mNB_train_X  = np.random.randint(4, size = (4,10))
mNB_train_y = np.array([1,2,3,4])
mNB_train_X
array([[1, 3, 0, 1, 0, 0, 0, 2, 1, 2],
       [2, 1, 0, 0, 1, 1, 3, 3, 0, 3],
       [0, 2, 2, 0, 3, 1, 2, 1, 0, 2],
       [1, 1, 2, 3, 3, 3, 1, 3, 3, 2]])
mNB_train_y
array([1, 2, 3, 4])
# 학습 
mNB = MultinomialNB()

fitted_mNB = mNB.fit(mNB_train_X, mNB_train_y)

# 첫 번째 값의 예측 결과 확인
print(fitted_mNB.predict(mNB_train_X[:1]))

# 첫 번째 값의 각 클래스별 확률 확인
fitted_mNB.predict_proba(mNB_train_X[:1])
[1]
 
array([[0.96357258, 0.02305516, 0.00558235, 0.0077899 ]])

 

첫 번째 값을 예측했을 때, 1이 나왔다.

1일 확률이 0.96% 라는 결과가 나왔다.

 

# 사전 확률 설정
# class가 발생되는 사전 확률을 미리 알고 있었던 경우라고 설정
clmNB_2 = MultinomialNB(class_prior = [0.1,0.5,0.1, 0.1])
clmNB_2.fit(mNB_train_X, mNB_train_y)

class 가 발생되는 사전 확률을 10%, 50%, 10%, 10% 로 설정하여

다시 학습시켰다.

 

clmNB_2.predict_proba(mNB_train_X[:1])
array([[0.88221421, 0.10554261, 0.00511101, 0.00713217]])

1일 확률 88%, 2일 확률 10%라는 결과가 나왔다.

 

Comments