2025. 3. 18. 21:54ㆍ머신러닝, 딥러닝 개념/지도 학습
이번 포스팅은 다음 교재의 내용을 참고해서 작성했다.
https://web.stanford.edu/~jurafsky/slp3/4.pdf
① 베이즈 정리(Bayes' Theorem)
조건부확률(Conditional Probability)
두 사건 $A$, $B$가 있다고 하자. 사건 $A$가 일어났다는 조건 하에 사건 $B$가 일어날 확률을 '사건 $B$에 대한 사건 $A$의 조건부확률'이라 하며, 기호로는 $P(B|A)$와 같이 표시한다. $P(B|A)$를 구하는 공식은 다음과 같다.
$$P(B|A) = \frac{P(B \cap A)}{P(A)}$$
베이즈 정리(Bayes' Theorem)
$P(B|A)$를 다음과 같이 쓸 수도 있다.
$$P(B|A) = \frac{P(A|B)P(B)}{P(A)}$$
이 공식 자체가 베이즈 정리이다. $P(A|B)= \frac{P(A \cap B)}{P(B)}$라는 점만 이용하면 공식 유도 자체는 매우 쉽다. 따라서 베이즈 정리에서는 공식 유도보다 공식이 어떤 의미를 가지는지를 파악하는 것이 훨씬 중요하다. 기본 개념만으로 1~2줄만에 증명되는 공식에 '정리'라는 명칭이 붙은 것은 그만한 이유가 있기 때문이다. 다음 예제를 풀어보면서
예제
- 어떤 희귀병 검사기의 정확도는 95%라고 한다(양성을 양성으로 판정할 확률과 음성을 음성으로 판정할 확률이 똑같이 95%라고 가정).
- 어떤 집단에서 이 희귀병에 걸린 사람의 비율은 0.1%에 불과하다고 한다.
- 이 집단에 속한 사람들 중 어떤 한 명이 양성(positive) 판정을 받았다고 하자. 이 사람이 실제로 희귀병에 걸렸을 확률은 몇 %일까?
얼핏 보면 희귀병 검사기의 정확도가 95%라니까, 양성 판정을 받은 사람이 실제로 양성일 확률도 95%일 것 같다. 하지만 실제로는 양성 판정을 받아도 실제로 양성일 확률은 2%도 채 안 된다고 한다. 검사기 정확도가 95%라는데 이게 말이 되는 소리인가?
테스트 결과가 양성인 사건을 $A$, 실제로 희귀병에 걸린 사건을 $B$라고 하자. 문제에서 구하고자 하는 것은 $P(B|A)$이다.
$P(B|A)$는 베이즈 정리에 따르면 다음과 같다.
$$P(B|A) = \frac{P(A|B)P(B)}{P(A)}$$
여기서 $P(A)$를 한 번 더 분해해서 다음과 같이 써보자.
$$P(B|A) = \frac{P(A|B)P(B)}{P(A|B)P(B) + P(A|B^{\rm C})P(B^{\rm C})}$$
분해 결과를 분석해보면 다음과 같다.
- $ P(A|B)P(B) $ : $A$도 일어나고 $B$도 일어날 확률 (아래 그림에서 ①)
- $ P(A|B^{\rm C})P(B^{\rm C}) $ : $A$는 일어났는데 $B$는 일어나지 않을 확률 (아래 그림에서 ②)
따라서 $ P(A) = ① + ② = P(A|B)P(B) + P(A|B^{\rm C})P(B^{\rm C})$이다.
그러면 이제 $P(B|A) = \frac{P(A|B)P(B)}{P(A|B)P(B) + P(A|B^{\rm C})P(B^{\rm C})}$를 계산해보자.
- $P(A|B)$ : '실제로 양성인 사람이 양성 판정을 받을 확률'인데, 이는 검사기의 정확도가 95%라고 했기 때문에 $P(A|B)=0.95$이다.
- $P(B)$ : '어떤 사람이 실제로 양성일 확률'인데, 집단 내에서 희귀병에 걸린 사람의 비율은 0.1%라고 했으므로 $P(B)=0.001$이다.
- $P(A|B^{\rm C})$ : '실제로 음성인 사람이 양성 판정을 받을 확률'인데, 정확도가 95%인 검사기에서 틀린 판정을 내릴 확률은 5%이다. 따라서 $P(A|B^{\rm C})=0.05$이다.
- $P(B^{\rm C}) = 1 - P(B) = 1 - 0.001 = 0.999$
따라서 계산 결과는 다음과 같다.
$$P(B|A) = \frac{0.95 \times 0.001}{0.95 \times 0.001 + 0.05 \times 0.999} = \frac{0.00095}{0.00095 + 0.04995} \approx 0.01866$$
즉, 양성 판정을 받았어도 실제 양성일 확률은 약 1.866% 정도에 불과한 것이다.
여전히 이해가 안 된다면 이렇게 생각해보면 어떨까?
희귀병 양성자 비율이 0.1%라고 했으니까 전체 인구가 10,000명이라고 하면 실제로 희귀병이 있는 사람은 10명 뿐이다. 하지만 검사기의 정확도가 95%이기 때문에 희귀병이 없는 나머지 9,990명 중에서도 5%는 양성 판정을 받게 되는데, 9,990명 중에 5%이면 499.5명이다. 즉, 애초에 희귀병 걸린 사람이 너무 적다보니 실제로 희귀병에 걸린 사람 수보다도 오진으로 양성 뜨는 사람이 약 50배나 더 많은 것이다. 이 정도 설명이면 이해가 충분히 됐으리라 생각한다.
그렇다면 이 예제를 통해 베이즈 정리의 용어와 의미를 살펴보자.
$$P(B|A) = \frac{P(A|B)P(B)}{P(A)}$$
- 사전 확률(prior) : 위 공식에서 $P(B)$가 사전 확률에 해당한다. 사건 $A$의 발생 여부를 아직 따져보지 않은 상태에서 사건 $B$가 일어날 확률을 의미한다. 위 예제에서는 아직 검사를 해보지 않은 상태에서 사건 $B$가 일어날 확률을 따져보는 것인데, 희귀병 양성자 비율이 0.1%이므로 희귀병에 걸렸을 확률 $P(B)$ 또한 0.1%이다.
- 사후 확률(posterior) : 위 공식에서 $P(B|A)$가 사후 확률에 해당한다. 사건 $A$가 발생한 후 갱신된 사건 $B$의 확률을 의미한다. 위 예제에서는 검사를 하지 않았을 때 희귀병에 걸릴 확률(사전 확률)은 0.1%였지만, 사건 $A$(판정 결과 양성)가 발생한다면 사건 $B$의 확률은 약 1.866%로 갱신된다.
- 가능도(likelihood) : 위 공식에서 $P(A|B)$가 가능도에 해당한다. 사건 $B$가 발생했을 때 사건 $A$의 발생 확률을 의미 한다. 위 예제에서는 검사기의 정확도에 근거하여 실제로 희귀병에 걸린 사람이 양성 판정을 받을 가능도를 95%로 하였다. 나이브 베이즈에서 가장 핵심이 되는 부분이다.
- 증거(evidence) : 위 공식에서 $P(A)$가 증거에 해당한다. 데이터를 기반으로 검사기에 의해 양성 판정을 받는 비율이 5%가 살짝 넘는다는 것을 알았고, 이는 실제로 희귀병에 걸린 사람의 비율 0.1%에 비해 훨씬 큰 비율이기 때문에 양성 판정을 받아도 실제로 희귀병에 걸렸을 확률은 생각보다 매우 낮다는 것을 알 수 있다.
따라서 베이즈 정리는 증거(evidence)를 기반으로 사전 확률(prior)을 업데이트 해서 사후 확률(posterior)을 계산하는 데 의의가 있다. 이는 새로운 정보(증거)가 기존의 추론에 어떻게 영향을 미치는지를 나타낸다.
이제 베이즈 정리에 대해 알았다면 나이브 베이즈를 이해할 수 있는 기본은 다진 것이다. 이제 본격적으로 나이브 베이즈에 대한 설명으로 들어가보자.
② 나이브 베이즈(Naive Bayes)
어떤 영화 리뷰가 긍정적인지 부정적인지를 나이브 베이즈 분류로 한다고 하자.
테스트하고자 하는 리뷰를 document의 앞 글자를 딴 $d$라 하고, 이 리뷰의 분류 결과(class)를 $c$라 하자. class는 긍정적인지와 부정적인지로 나뉘기 때문에 $c \in \rm \{positive, negative\}$이다. 여기서 구하고자 하는 것은 리뷰 $d$가 클래스 $c$에 해당할 확률 $P(c|d)$가 최대가 되도록 하는 클래스 $c$를 구하는 것이다. 이를 $\hat{c}$이라고 하자.
앞에서 공부한 베이즈 정리에 따르면, $P(c|d)=\frac{P(d|c)P(c)}{P(d)}$인데, 여기서 $P(d|c)$는 다음과 같이 구할 것이다.
테스트(Test) 리뷰 $d$에 있는 단어를 $w_1$, $w_2$, $\cdots$, $w_n$이라 하자. 그렇다면 리뷰 안에 있는 각각의 단어들이 독립이라고 간주하여 $P(d|c) = P(w_1|c) \times P(w_2|c) \times \cdots \times P(w_n|c)$로 바꿀 것이다. 사실 naive bayes에서 naive(단순한)라는 단어가 붙은 이유가 이렇게 문장 내 단어 간 관계를 무시하고 모두 독립적인 것으로 간주하는 확률 계산 방식 때문이다.
$ P(w_i|c)$는 클래스가 $c$인 리뷰에서 $w_i$라는 단어가 등장할 확률을 의미한다. 이는 훈련(Train) 리뷰들에 근거하여 계산하는데 구체적인 계산 방법은 뒤에서 제시한다.
$P(c)$는 사전 확률이므로, 리뷰의 내용을 보지 않고 단순히 훈련(Train) 리뷰들의 클래스 분포만 보고 계산되는 확률이다.
$P(d)$는 여기서 필요가 없는데, 어차피 $c$가 positive이든 negative이든 같은 리뷰에 대한 확률을 예측하는 것이기 때문에 둘이 $P(d)$ 값은 똑같다. 따라서 대소비교만 하는 것이 목적이라면 $P(d)$를 비교할 필요는 없기 때문에 $P(d)$는 계산 대상에서 제외한다.
따라서 우리가 구해야 하는 $\hat{c}$은 다음과 같다.
$$\begin{align} \hat{c} &= \underset{c}{\arg\max} P(d|c)P(c) \\\\ &= \underset{c}{\arg\max} P(w_1|c)P(w_2|c) \cdots P(w_n|c)P(c) \\\\ &= \underset{c}{\arg\max} P(c) \prod_{i=1}^{n} P(w_i|c) \end{align}$$
수열의 합 $a_1 + a_2 + \cdots + a_n$을 간단히 $\displaystyle \sum_{i=1}^{n} a_i$로 쓰는 것처럼, 수열의 곱 $a_1 \times a_2 \times \cdots \times a_n$을 간단하게 쓰면 $ \displaystyle \prod_{i=1}^{n} a_i$가 된다.
지금까지 뭔 말인지 몰랐어도 괜찮다. 예제를 통해 분류 방법을 직접 이해해보기로 하자.
예제
긍정적(+)인지 부정적(-)인지 라벨링 되어있는 5개의 Train 리뷰가 주어져 있고, 이들을 기반으로 Test 리뷰의 긍정/부정 여부를 예측할 것이다. 먼저 Test 리뷰에는 predictable, with, no, fun이라는 4개의 단어가 주어져 있다. 그런데 with는 Train 리뷰에 아예 안 나오는 단어이므로 이는 제외한다. 따라서 predictable, no, fun을 각각 $w_1$, $w_2$, $w_3$라고 하자.
$w_1$(predictable)을 먼저 보자. Training 리뷰들 중 부정적인 리뷰들의 총 단어 개수는 14개(just, plain, boring, entirely, ..., laughs)인데, 이 중에서 predictable이라는 단어가 1개 존재하므로 부정적인 리뷰에 predictable이라는 단어가 존재할 확률은 $\frac{1}{14}$이다. 즉, $P(w_1|\rm negative) = \frac{1}{14}$이다. 그러나 긍정적인 리뷰에는 predictable이라는 단어가 없다. 따라서 긍정적인 리뷰에 predictable이라는 단어가 존재할 확률 $P(w_1|\rm positive) = 0$이 된다.
그런데 이렇게 확률이 하나라도 0이 되면 문제가 생긴다. 구하고자 하는 것이 $P(w_1|c)P(w_2|c) \cdots P(w_n|c)P(c)$이 최대가 되도록 하는 클래스 $c$인데, $P(w_1|\rm positive)$가 이미 0이므로 c가 positive이면 $P(w_1|c)P(w_2|c) \cdots P(w_n|c)P(c)=0$이라는 결론이 나와버린다. 그러면 negative일 때는 문제가 없는가? negative일 때는 $P(w_3|\rm negative)$가 0이므로 역시나 0이 나온다. 이렇게 되면 리뷰가 긍정적인지 부정적인지를 판단할 수가 없기 때문에 $P(w_i|c)$의 계산 방법을 수정하기로 하자.
원래는 $P(w_i|c)$를 다음과 같이 계산했었다.
$$P(w_i|c) = \frac{{\rm count}(w_i,c)}{\sum_{w \in V}{\rm count}(w, c)}$$
여기서 $V$는 Train 리뷰들에 등장하는 모든 단어들의 집합이다. 만약에 c가 negative라면, 분모는 부정적인 리뷰들에 나오는 단어의 총 개수로, 분자는 부정적인 리뷰에 $w_i$라는 단어가 나오는 횟수로 두고 계산했었다.
문제는 $ {\rm count}(w_i,c)=0$이면 나머지 확률은 구해볼 필요도 없이 결괏값이 0으로 결론나버려서 분류를 할 수가 없다는 점이었다. 따라서 우리는 $P(w_i|c)$를 구하는 방법을 다음과 같이 수정한다.
$$P(w_i|c) = \frac{{\rm count}(w_i,c)+1}{\sum_{w \in V}{(\rm count}(w, c)+1)} = \frac{{\rm count}(w_i,c)+1}{\sum_{w \in V}{\rm count}(w, c)+|V|} $$
이 공식대로 $P(w_i|c)$를 각각 계산한 결과는 다음과 같다.
여기서 $|V|$가 14+9=23이 아니라 20인 이유는 3개 단어(and, very, the)가 Train 리뷰에서 두 번씩 나오기 때문임을 유의한다(집합은 기본적으로 중복이 없다).
그리고 5개의 Train 리뷰들 중 긍정적인(+) 리뷰는 2개이므로 $P(+)=\frac{2}{5}$, 부정적인(-) 리뷰는 3개이므로 $P(-)=\frac{3}{5}$이다.
따라서 c가 -라면
$$P({\rm predictable }|-) \times P({\rm no}|-) \times P({\rm fun}|-) \times P(-) = \frac{2 \times 2 \times 1}{34^3}\times \frac{3}{5} \approx 6.1 \times 10^{-5}$$
c가 +라면
$$P({\rm predictable}|+) \times P({\rm no}|+) \times P({\rm fun}|+) \times P(-) = \frac{1 \times 1 \times 2}{29^3} \times \frac{2}{5} \approx 3.2 \times 10^{-5}$$
$6.1 \times 10^{-5} > 3.2 \times 10^{-5}$이므로 Test 리뷰는 부정적인 리뷰로 분류된다.
③ 슈도 코드(Pseudo Code) 구현하기
교재에 나이브 베이즈의 슈도 코드가 있어서 이를 파이썬으로 구현해볼 것이다.
그런데 프로그래밍할 때는 주의할 점이 있다. 곱하는 확률의 개수가 많아질수록 $ P(c) \prod_{i=1}^{n} P(w_i|c) $는 0에 수렴할 정도로 작아지는데, 이렇게 값이 한없이 작아지게 되면 언더플로우(underflow)가 발생할 수 있다. 따라서 우리는 $ P(c) \prod_{i=1}^{n} P(w_i|c) $에 로그를 취한 값 $\log P(c) \prod_{i=1}^{n} P(w_i|c) $를 구하려고 한다. (여기서 $\log$는 상용로그가 아니라 자연로그($\ln$)이다. 공학 계열에서는 $\log$가 자연로그를 의미하는 경우가 많으니 참고할 것)
$\log P(c) \prod_{i=1}^{n} P(w_i|c) $를 구하는 방법은 다음과 같다.
$$ \log P(c) \prod_{i=1}^{n} P(w_i|c) = \log P(c) + \sum_{i=1}^{n} \log P(w_i|c) $$
즉, (사전 확률(prior)의 로그값) + (모든 가능도(likelihood)의 로그값의 합)을 구해주면 된다. 슈도 코드의 내용은 다음과 같다.
이를 그대로 파이썬으로 옮겨보았다.
import numpy as np
import pandas as pd
def train_naive_bayes(documents, classes):
log_prior = {}
log_likelihood = {}
voca = documents["document"].str.split().explode().unique()
for c in classes:
n_doc = len(documents)
n_c = np.sum(documents["class"] == c)
log_prior[c] = np.log(n_c / n_doc)
big_doc = documents[documents["class"] == c]["document"].str.split().explode().to_numpy()
for word in voca:
count = sum(1 for w in big_doc if w == word)
log_likelihood[(word, c)] = np.log((count + 1) / (len(big_doc) + len(voca)))
return log_prior, log_likelihood, voca
def test_naive_bayes(test_doc, log_prior, log_likelihood, classes, voca):
total = {}
for c in classes:
total[c] = log_prior[c]
test_doc_words = test_doc.split()
for i in range(len(test_doc_words)):
word = test_doc_words[i]
if word in voca:
total[c] += log_likelihood[(word, c)]
return max(total, key=total.get)
# negative:-, positive:+
documents = pd.DataFrame([
["just plain boring", "-"],
["entirely predictable and lacks energy", "-"],
["no surprises and very few laughs", "-"],
["very powerful", "+"],
["the most fun film of the summer", "+"]
], columns=["document", "class"])
classes = documents["class"].unique()
log_prior, log_likelihood, voca = train_naive_bayes(documents, classes)
test_doc1 = "predictable with no fun"
print(f"{test_doc1}:", test_naive_bayes(test_doc1, log_prior, log_likelihood, classes, voca))
test_doc2 = "very fun film"
print(f"{test_doc2}:", test_naive_bayes(test_doc2, log_prior, log_likelihood, classes, voca))
실행 결과
predictable with no fun: -
very fun film: +
간단한 리뷰 2개를 테스트 해 본 결과, 분류가 잘 됐음을 확인할 수 있다. 물론 훈련 데이터가 너무 적기 때문에 다른 리뷰로 테스트 하면 분류 결과가 틀리게 나올 수도 있고, 훈련 데이터에 없는 단어들만으로 이루어진 리뷰라면 아예 분류 자체가 불가능할 수도 있다. 하지만 데이터가 많이 모인다면 꽤 쓸만한 분류기가 될 것으로 예상할 수 있다.
④ 가우시안 나이브 베이즈(Gaussian Naive Bayes)
가우시안 분포
가우시안 분포(Gaussian Distribution)는 고등학교 확률과 통계 시간에 '정규 분포(Normal Distribution)'라는 이름으로 배운 분포이다. 즉, 다음 사진과 같은 예쁜 종 모양 분포가 가우시안 분포인 것이다.
가우시안 나이브 베이즈
가우시안 나이브 베이즈(Gaussian Naive Bayes)는 가능도(likelihood)를 가우시안 분포 함수로 사용하는 것이다. 가우시안 분포가 좌우 대칭 종 모양인건 알겠는데, 이 종 모양 그래프의 확률 밀도 함수(Probability Density Function, PDF)가 뭔지 알고 있는가? 물론 고등학교 확률과 통계 교과서에 함수식도 언급이 되어있긴 하지만 외우기엔 너무 어렵고 사실 외울 필요가 전혀 없어서 대부분은 모르고 있다. 하지만 여기서 쓰려면 알아야 하니까 잠깐 언급하고 넘어가자. 가우시안 분포의 PDF는 다음과 같다.
$$N(x; \mu, \sigma)=\frac{1}{\sqrt{2 \pi \sigma^2}} \exp \left( -\frac{(x-\mu)^2}{2 \sigma^2} \right)$$
이 식을 가능도(likelihood)로 사용한다. 그러면 이제 가우시안 나이브 베이즈가 어떤 원리로 동작하는지 알아보자.
데이터가 위와 같이 주어져 있을 때, $(x_1,x_2)=(5,5)$인 테스트 데이터의 클래스($y$)를 추정한다고 해보자. 클래스를 추정하는 방법은 $\displaystyle P(c) \prod_{i=1}^{n} P(x_i|y)$의 값이 더 크게 나오는 $y$를 선택하는 것이다. 먼저 8개의 데이터 중에 클래스가 0인 것은 3개, 클래스가 1인 것은 5개이므로 사전 확률(prior) $P(y=0)$과 $P(y=1)$은 다음과 같다.
$$P(y=0)=\frac{3}{8}=0.375, \ \ \ \ P(y=1)=\frac{5}{8}=0.625$$
다음으로는 가능도(likelihood)를 구해야 하는데, 가능도는 가우시안 분포를 사용한다고 했다. 그러기 위해서는 클래스 0과 클래스 1의 데이터들에 대해 각각 $x_1$의 평균($\mu$) 및 분산($\sigma^2$), $x_2$의 평균 및 표준편차를 모두 구해야 한다. 먼저 클래스 0에 대해서 구해보자.
$$\mu_{x_1|y=0}=5, \ \ \ \ \sigma^2_{x_1|y=0} = \frac{2}{3} \\\\ \mu_{x_2|y=0}=\frac{11}{3} \ \ \ \ \sigma^2_{x_2|y=0} = \frac{2}{9} $$
테스트 데이터는 $(x_1,x_2)=(5,5)$이므로, 두 가능도 $P(y=0|x_1=5)$과 $P(y=0|x_2=5)$를 각각 가우시안 분포 함수에 대입하여 구해준다.
$$P(y=0|x_1=5) =\frac{1}{\sqrt{2 \pi \cdot \frac{2}{3} }} \exp \left( -\frac{(5-5)^2}{2 \cdot \frac{2}{3}} \right) \approx 0.489 \\\\ P(y=0|x_2=5) =\frac{1}{\sqrt{2 \pi \cdot \frac{2}{9} }} \exp \left( -\frac{(5-\frac{11}{3})^2}{2 \cdot \frac{2}{9} } \right) \approx 0.0155 $$
따라서
$$ P(y=0) \prod_{i=1}^{2} P(x_i|y=0) = 0.375 \times 0.489 \times 0.0155 \approx 2.84 \times 10^{-3}$$
이다.
이번엔 클래스가 1일 때 $ P(y=1) \prod_{i=1}^{2} P(x_i|y=1) $의 값을 구해보자.
$$\mu_{x_1|y=1}=2.6, \ \ \ \ \sigma_{x_1|y=1} = 1.04 \\\\ \mu_{x_2|y=1}=6 \ \ \ \ \sigma_{x_2|y=1} = 3.6 $$
$$P(y=1|x_1=5) =\frac{1}{\sqrt{2 \pi \cdot 1.04 }} \exp \left( -\frac{(5-2.6)^2}{2 \cdot 1.04} \right) \approx 0.0245 \\\\ P(y=1|x_2=5) =\frac{1}{\sqrt{2 \pi \cdot 3.6 }} \exp \left( -\frac{(5-6)^2}{2 \cdot 3.6 } \right) \approx 0.183 $$
$$ P(y=1) \prod_{i=1}^{2} P(x_i|y=1) = 0.625 \times 0.0245 \times 0.183 \approx 2.81 \times 10^{-3}$$
간발의 차로 $ P(y=0) \prod_{i=1}^{2} P(x_i|y=0) > P(y=1) \prod_{i=1}^{2} P(x_i|y=1) $이므로 테스트 데이터는 클래스 0으로 분류된다. 그림으로 보면 다음과 같다.
세모 점이 테스트 데이터인데, 그림에서 보는 것처럼 테스트 데이터가 클래스 0으로 분류되었음을 확인할 수 있다.
⑤ 다항 분포 나이브 베이즈(Multinomial Naive Bayes)
'이게 뭐지...' 하고 한참을 들여다 봤는데 알고 보니 리뷰 긍정/부정 분류기 예제에서 사용한 기법이 Multinomial Naive Bayes였다.
Multinomial Naive Bayes에서는 가능도(likelihood)를 다음과 같이 정한다.
$$P(x_i|y) = \frac{{\rm count}(x_i,y)+\alpha}{\sum_{x \in T}{\rm count}(x, y)+\alpha |T|} $$
분류기 예제와 비교하면 기호 $d$가 $x$로 바뀌고, $c$가 $y$로 바뀌고, $V$가 $T$로 바뀌었다.
- ${\rm count}(x_i, y)$ : $x_i$가 $y$ 클래스의 훈련 데이터에 등장한 횟수
- $\alpha$ : 확률이 0이 되는 것을 방지하기 위한 스무딩(smoothing) 상수이다. 분류기 예제에서는 $\alpha=1$로 설정했었다. $\alpha=1$인 스무딩을 라플라스 스무딩(Laplace smoothing)이라고 하고, $\alpha<1$인 스무딩을 리드스톤 스무딩(Lidstone smoothing)이라고 한다.
- $ \sum_{x \in T}{\rm count}(x, y)$ : 테스트 데이터의 집합 $T$의 모든 요소 $x$가 $y$ 클래스에 등장하는 총 횟수를 의미한다.
- $ \alpha |T|$ : 테스트 데이터 집합 $T$의 크기
예제는 앞에서 들었기 때문에 생략한다.
⑥ 베르누이 나이브 베이즈(Bernoulli Naive Bayes)
베르누이 분포(Bernoulli Distribution)는 [지도 학습(4) : 로지스틱 회귀] 포스팅에서 잠깐 언급한 바 있다. 간단히 얘기하자면 타깃값 $y \in \{0, 1\}$에 대해 $P(y=1)=p$이고 $P(y=0)=1-p$인 분포를 베르누이 분포라고 한다. 베르누이 나이브 베이즈에서 사용하는 가능도 식은 다음과 같다.
$$P(x_i|y)=P(x_i=1|y)x_i + (1 - P(x_i=1|y) )(1-x_i)$$
⑦ 실습
간단한 코드로 실습을 하고 포스팅을 마치려 한다.
실습 코드 : https://www.geeksforgeeks.org/gaussian-naive-bayes-using-sklearn/
from sklearn.datasets import make_classification
import matplotlib.pyplot as plt
# Generate a synthetic dataset
X, y = make_classification(n_samples=100, n_features=2,
n_redundant=0, n_clusters_per_class=1,
random_state=42)
# Visualize the dataset
plt.scatter(X[:, 0], X[:, 1], c=y, cmap='viridis', edgecolor='k')
plt.title('Synthetic Dataset')
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.show()
먼저 make_classification() 함수로 선형 분리 가능한(linearly seperable) 데이터셋을 만든다. 그래프 생성 결과는 다음과 같다.
이제 이를 대상으로 가우시안 나이브 베이즈 분류를 시행하자. 가우시안 나이브 베이즈 모델은 sklearn.naive_bayes 모듈에서 GaussianNB라는 이름의 클래스로 제공하고 있다. 다항 분포 나이브 베이즈 모델은 MultinomialNB, 베르누이 나이브 베이즈 모델은 BernoulliNB이다.
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import GaussianNB
from sklearn.metrics import accuracy_score
# Split the dataset into training and testing sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# Initialize the Gaussian Naive Bayes classifier
gnb = GaussianNB()
# Train the model
gnb.fit(X_train, y_train)
# Predict the labels for the test set
y_pred = gnb.predict(X_test)
# Calculate the accuracy
accuracy = accuracy_score(y_test, y_pred)
print(f'Accuracy: {accuracy}')
실행 결과
Accuracy: 0.9666666666666667
분류 결과 96.67%의 정확도가 나왔음을 알 수 있다.
'머신러닝, 딥러닝 개념 > 지도 학습' 카테고리의 다른 글
지도 학습(6+) : 서포트 벡터 머신 심화 (1) | 2025.03.15 |
---|---|
지도 학습(6) : 서포트 벡터 머신 (1) | 2025.03.14 |
지도 학습(5) : k-최근접 이웃 (3) | 2025.03.10 |
지도 학습(4) : 로지스틱 회귀 (3) | 2025.03.10 |
지도 학습(3) : 다항 회귀, 릿지 회귀, 라쏘 회귀, 엘라스틱 넷 (1) | 2025.03.05 |