가우시안 나이브 베이즈, 설명

가우시안 나이브 베이즈, 설명

소스 노드 : 2021431

가우시안 나이브 베이즈, 설명
가우시안 나이브 베이즈 분류기의 결정 영역입니다. 저자의 이미지.

 

나는 이것이 각 데이터 과학 경력의 시작 부분에 있는 고전이라고 생각합니다. 나이브 베이 즈 분류기. 아니면 차라리 가족 나이브 베이즈 분류기의 특징은 다양합니다. 예를 들어, 다항 나이브 베이즈, 베르누이 나이브 베이즈, 가우시안 나이브 베이즈 분류기가 있으며, 각각은 하나의 작은 세부 사항만 다릅니다. 나이브 베이즈 알고리즘은 디자인이 매우 단순하지만 많은 복잡한 실제 상황에서 유용한 것으로 입증되었습니다.

이 기사에서 배울 수 있습니다.

  • 순진한 베이즈 분류기가 작동하는 방식,
  • 왜 그들을 있는 그대로 정의하는 것이 이치에 맞고
  • NumPy를 사용하여 Python에서 구현하는 방법.

에서 코드를 찾을 수 있습니다. 내 Github.

베이지안 통계에 대한 내 입문서를 확인하는 데 약간 도움이 될 수 있습니다. 베이지안 추론에 대한 부드러운 소개 Bayes 공식에 익숙해지기 위해 scikit 학습 준수 방식으로 분류기를 구현할 것이므로 내 기사를 확인하는 것도 좋습니다. 나만의 맞춤형 scikit-learn 회귀 구축. 그러나 scikit-learn 오버헤드는 매우 작으며 어쨌든 따를 수 있어야 합니다.

Naive Bayes 분류의 놀랍도록 간단한 이론을 탐색한 다음 구현으로 전환합니다.

분류할 때 우리가 정말로 관심을 갖는 것은 무엇입니까? 우리는 실제로 무엇을 하고 있으며 입력과 출력은 무엇입니까? 답은 간단합니다.

데이터 포인트 x가 주어지면 x가 어떤 클래스 c에 속할 확률은 얼마입니까?

그게 우리가 대답하고 싶은 전부입니다 어떤 분류. 이 명령문을 조건부 확률로 직접 모델링할 수 있습니다. p(c|x).

예를 들어

  • 3 클래스 씨₁c₃
  • 2가지 기능으로 구성 x₁,

분류기의 결과는 다음과 같을 수 있습니다. p(씨₁|x₁) = 0.3, p(|x₁)=0.5 및 p(c₃|x₁)=0.2. 출력으로 단일 레이블을 관리하는 경우 확률이 가장 높은 레이블을 선택합니다.  여기서 50%의 확률로.

나이브 베이즈 분류기는 이러한 확률을 직접 계산하려고 시도합니다.

나이브 베이 즈

좋아, 그래서 주어진 데이터 포인트 x, 우리는 계산하고 싶습니다 p(c|x) 모든 클래스 그런 다음 출력 c 가장 높은 확률로. 수식에서 종종 다음과 같이 표시됩니다.

 

가우시안 나이브 베이즈, 설명
저자의 이미지.

 

참고 : 최대 p(c|x)는 최대 확률을 반환하고 argmax는 p(c|x) 반환 c 이 가장 높은 확률로.

하지만 최적화하기 전에 p(c|x), 우리는 그것을 계산할 수 있어야 합니다. 이를 위해 우리는 베이즈의 정리:

 

가우시안 나이브 베이즈, 설명
베이즈 정리. 저자의 이미지.

 

이것은 나이브 베이즈의 베이즈 부분입니다. 그러나 이제 다음과 같은 문제가 있습니다. p(x|c) and p(c)?

이것이 나이브 베이즈 분류기의 훈련에 관한 모든 것입니다.

트레이닝

모든 것을 설명하기 위해 다음과 같은 장난감 데이터 세트를 사용하겠습니다. 두 가지 실제 기능 x₁및 세 가지 수업 씨₁c₃ 다음에서.

 

가우시안 나이브 베이즈, 설명
시각화된 데이터. 저자의 이미지.

 

다음을 통해 이 정확한 데이터 세트를 만들 수 있습니다.

from sklearn.datasets import make_blobs X, y = make_blobs(n_samples=20, centers=[(0,0), (5,5), (-5, 5)], random_state=0)

우리는 클래스 확률 p(c), 어떤 클래스가 c 레이블이 지정된 데이터 세트에서 관찰됩니다. 이를 추정하는 가장 간단한 방법은 클래스의 상대 빈도를 계산하고 확률로 사용하는 것입니다. 데이터 세트를 사용하여 이것이 정확히 무엇을 의미하는지 확인할 수 있습니다.

7점 중 20점이 등급으로 표시되어 있습니다. 씨₁ (파란색) 데이터 세트에서, 따라서 우리는 p(씨₁)=7/20. 우리는 수업에 7 점을 가지고 있습니다  (빨간색)도 있으므로 설정합니다. p()=7/20. 마지막 수업 c₃ (노란색)은 6점만 있으므로 p(c₃)=6/20.

클래스 확률의 이 간단한 계산은 최대 우도 접근법과 유사합니다. 그러나 다른 것을 사용할 수도 있습니다. 이전에 원하는 경우 배포. 예를 들어, 이 데이터 세트가 실제 모집단을 대표하지 않는다는 것을 알고 있는 경우 c₃ 사례의 50%에 나타나야 합니다. 그런 다음 설정합니다. p(씨₁) = 0.25, p()=0.25 및 p(c₃)=0.5. 테스트 세트의 성능을 향상시키는 데 도움이 되는 모든 것.

우리는 이제 있을 수 있는 일 p(x|c)=p(x₁|c). 이 가능성을 계산하는 한 가지 방법은 레이블이 있는 샘플의 데이터 세트를 필터링하는 것입니다. 그런 다음 기능을 캡처하는 분포(예: 2차원 가우시안)를 찾으려고 합니다. x₁.

불행하게도 일반적으로 우도를 적절하게 추정하기 위해 클래스당 샘플이 충분하지 않습니다.

보다 강력한 모델을 구축할 수 있도록 순진한 가정 그 특징 x₁ are 확률적으로 독립, 주어진 c. 이것은 수학을 더 쉽게 만드는 멋진 방법입니다.

 

가우시안 나이브 베이즈, 설명
저자의 이미지

 

모든 수업에 c. 이것은 소박한 Naive Bayes의 일부는 이 방정식이 일반적으로 유지되지 않기 때문에 발생합니다. 그럼에도 불구하고 순진한 Bayes는 실제로 훌륭하고 때로는 뛰어난 결과를 산출합니다. 특히 bag-of-words 기능이 있는 NLP 문제의 경우 다항 나이브 베이즈가 빛을 발합니다.

위에 주어진 인수는 찾을 수 있는 모든 나이브 베이즈 분류기에 대해 동일합니다. 이제 모델링 방법에 따라 다릅니다. p(x₁|c₁), p(xXNUMX|c₁), p(x₁|cXNUMX), p(xXNUMX|cXNUMX), p(x₁|c₃) 및 p(x²|c₃).

기능이 0과 1이면 베르누이 분포. 정수인 경우 다항 분포. 그러나 우리는 실제 특성 값을 가지고 있으며 가우시안 따라서 이름은 Gaussian naive Bayes입니다. 우리는 다음과 같은 형식을 가정합니다

 

가우시안 나이브 베이즈, 설명
저자의 이미지.

 

어디에 μᵢ,ⱼ 는 평균이고 σᵢ,ⱼ 데이터에서 추정해야 하는 표준 편차입니다. 이것은 우리가 각 기능에 대해 하나의 평균을 얻는다는 것을 의미합니다. i 클래스와 결합 ㄷⱼ, 우리의 경우 2*3=6은 의미합니다. 표준 편차도 마찬가지입니다. 여기에는 예가 필요합니다.

추정해보자 μ²,₁ 및 σXNUMX,₁. 때문에 j=1, 클래스에만 관심이 있습니다. 씨₁, 이 레이블이 있는 샘플만 보관하겠습니다. 다음 샘플이 남아 있습니다.

# samples with label = c_1 array([[ 0.14404357, 1.45427351], [ 0.97873798, 2.2408932 ], [ 1.86755799, -0.97727788], [ 1.76405235, 0.40015721], [ 0.76103773, 0.12167502], [-0.10321885, 0.4105985 ], [ 0.95008842, -0.15135721]])

지금 때문에 i=2 두 번째 열만 고려하면 됩니다. μ²,₁는 평균이고 σ²,₁ 이 열의 표준 편차, 즉 μ²,₁ = 0.49985176 및 σ²,₁ = 0.9789976.

이 숫자는 위에서 산점도를 다시 보면 의미가 있습니다. 특징  수업 샘플 중 씨₁ 그림에서 볼 수 있듯이 약 0.5입니다.

이제 다른 다섯 가지 조합에 대해 이것을 계산하면 완료됩니다!

파이썬에서는 다음과 같이 할 수 있습니다.

from sklearn.datasets import make_blobs
import numpy as np # Create the data. The classes are c_1=0, c_2=1 and c_3=2.
X, y = make_blobs( n_samples=20, centers=[(0, 0), (5, 5), (-5, 5)], random_state=0
) # The class probabilities.
# np.bincounts counts the occurence of each label.
prior = np.bincount(y) / len(y) # np.where(y==i) returns all indices where the y==i.
# This is the filtering step.
means = np.array([X[np.where(y == i)].mean(axis=0) for i in range(3)])
stds = np.array([X[np.where(y == i)].std(axis=0) for i in range(3)])

우리는 받는다

# priors
array([0.35, 0.35, 0.3 ])
# means array([[ 0.90889988, 0.49985176], [ 5.4111385 , 4.6491892 ], [-4.7841679 , 5.15385848]])
# stds
array([[0.6853714 , 0.9789976 ], [1.40218915, 0.67078568], [0.88192625, 1.12879666]])

이것은 Gaussian Naive Bayes 분류기의 학습 결과입니다.

예측하기

완전한 예측 공식은 다음과 같습니다.

 

가우시안 나이브 베이즈, 설명
저자의 이미지.

 

새로운 데이터 포인트를 가정해 보겠습니다. 엑스*=(-2, 5)가 들어옵니다.

 

가우시안 나이브 베이즈, 설명
저자의 이미지.

 

어떤 클래스에 속하는지 확인하기 위해 다음을 계산해 보겠습니다. p(c|x*) 모든 클래스. 그림에서 클래스에 속해야 합니다. c₃ = 2, 그러나 보자. 분모는 무시하자 p(x) 잠시만요. 다음 루프를 사용하여 후보를 계산했습니다. j = 1, 2, 3.

x_new = np.array([-2, 5]) for j in range(3): print( f"Probability for class {j}: {(1/np.sqrt(2*np.pi*stds[j]**2)*np.exp(-0.5*((x_new-means[j])/stds[j])**2)).prod()*p[j]:.12f}" )

우리는 받는다

Probability for class 0: 0.000000000263
Probability for class 1: 0.000000044359
Probability for class 2: 0.000325643718

물론 확률 (그렇게 부르면 안 됩니다.) 분모를 무시했기 때문에 0.00032569이 되지 않습니다. 그러나 이것은 정규화되지 않은 확률을 합으로 나누면 XNUMX이 되기 때문에 문제가 되지 않습니다. 따라서 이 세 값을 합계 약 XNUMX로 나누면

 

가우시안 나이브 베이즈, 설명
저자의 이미지.

 

예상대로 확실한 승자. 이제 구현해 봅시다!

이 구현은 훨씬 효율적이지 않고 수치적으로 안정적이지 않으며 교육 목적으로만 사용됩니다. 우리는 대부분의 사항에 대해 논의했으므로 이제 쉽게 따라할 수 있습니다. 당신은 모두 무시할 수 있습니다 check 기능 또는 내 기사 읽기 나만의 맞춤형 scikit-learn 구축 그들이 정확히 무엇을하는지 관심이 있다면.

내가 구현했다는 점에 유의하십시오. predict_proba 먼저 확률을 계산하는 방법. 방법 predict 이 메서드를 호출하고 argmax 함수를 사용하여 확률이 가장 높은 인덱스(=클래스)를 반환합니다(또 있습니다!). 수업은 0부터 수업을 기다리고 있습니다. k-1, 여기서 k 클래스의 수입니다.

import numpy as np
from sklearn.base import BaseEstimator, ClassifierMixin
from sklearn.utils.validation import check_X_y, check_array, check_is_fitted class GaussianNaiveBayesClassifier(BaseEstimator, ClassifierMixin): def fit(self, X, y): X, y = check_X_y(X, y) self.priors_ = np.bincount(y) / len(y) self.n_classes_ = np.max(y) + 1 self.means_ = np.array( [X[np.where(y == i)].mean(axis=0) for i in range(self.n_classes_)] ) self.stds_ = np.array( [X[np.where(y == i)].std(axis=0) for i in range(self.n_classes_)] ) return self def predict_proba(self, X): check_is_fitted(self) X = check_array(X) res = [] for i in range(len(X)): probas = [] for j in range(self.n_classes_): probas.append( ( 1 / np.sqrt(2 * np.pi * self.stds_[j] ** 2) * np.exp(-0.5 * ((X[i] - self.means_[j]) / self.stds_[j]) ** 2) ).prod() * self.priors_[j] ) probas = np.array(probas) res.append(probas / probas.sum()) return np.array(res) def predict(self, X): check_is_fitted(self) X = check_array(X) res = self.predict_proba(X) return res.argmax(axis=1)

구현 테스트

코드는 매우 짧지만 우리가 어떤 실수도 하지 않았다는 것을 완전히 확신하기에는 여전히 너무 깁니다. 그럼, 우리는 그것이 어떻게 비교 요금을 확인하자 scikit-learn GaussianNB 분류기.

my_gauss = GaussianNaiveBayesClassifier()
my_gauss.fit(X, y)
my_gauss.predict_proba([[-2, 5], [0,0], [6, -0.3]])

출력

array([[8.06313823e-07, 1.36201957e-04, 9.99862992e-01], [1.00000000e+00, 4.23258691e-14, 1.92051255e-11], [4.30879705e-01, 5.69120295e-01, 9.66618838e-27]])

를 이용한 예측 predict 방법은

# my_gauss.predict([[-2, 5], [0,0], [6, -0.3]])
array([2, 0, 1])

이제 scikit-learn을 사용해 봅시다. 몇 가지 코드를 던져

from sklearn.naive_bayes import GaussianNB gnb = GaussianNB()
gnb.fit(X, y)
gnb.predict_proba([[-2, 5], [0,0], [6, -0.3]])

산출량

array([[8.06314158e-07, 1.36201959e-04, 9.99862992e-01], [1.00000000e+00, 4.23259111e-14, 1.92051343e-11], [4.30879698e-01, 5.69120302e-01, 9.66619630e-27]])

숫자는 분류기의 숫자와 비슷해 보이지만 표시된 마지막 몇 자릿수에서 약간 다릅니다. 우리가 잘못한 것이 있습니까? 그렇지 않습니다. scikit-learn 버전은 단순히 다른 하이퍼파라미터를 사용합니다. var_smoothing=1e-09 . 이걸로 설정하면 제로, 우리는 정확히 숫자를 얻습니다. 완벽한!

분류기의 결정 영역을 살펴보십시오. 또한 테스트에 사용된 세 지점을 표시했습니다. 경계에 가까운 그 한 지점은 56.9%의 확률로 레드 클래스에 속할 수 있습니다. predict_proba 출력. 다른 두 지점은 훨씬 높은 신뢰도로 분류됩니다.

 

가우시안 나이브 베이즈, 설명

3개의 새로운 점이 있는 결정 영역. 저자의 이미지.

 

이 기사에서 우리는 Gaussian naive Bayes 분류기가 어떻게 작동하는지 배웠고 그것이 왜 그렇게 설계되었는지에 대한 직관을 제공했습니다. 관심 확률을 모델링하는 직접적인 접근 방식입니다. 이를 로지스틱 회귀와 비교하십시오. 거기에서 확률은 시그모이드 함수가 적용된 선형 함수를 사용하여 모델링됩니다. 여전히 쉬운 모델이지만 나이브 베이즈 분류기만큼 자연스럽지 않습니다.

계속해서 몇 가지 예를 계산하고 유용한 코드를 수집했습니다. 마지막으로 scikit-learn과 잘 작동하는 방식으로 완전한 가우시안 나이브 베이즈 분류기를 구현했습니다. 즉, 예를 들어 파이프라인이나 그리드 검색에서 사용할 수 있습니다.

결국, 우리는 scikit-learns 자체의 Gaussian naive Bayes 분류기를 가져오고 우리와 scikit-learn의 분류기가 모두 동일한 결과를 산출하는지 테스트하여 작은 온전성 검사를 수행했습니다. 이 테스트는 성공적이었습니다.

 
 
로버트 퀴블러 박사 Publicis Media의 데이터 과학자이자 Towards Data Science의 저자입니다.

 
실물. 허가를 받아 다시 게시했습니다.
 

타임 스탬프 :

더보기 너 겟츠