테이블:
소개
Naive Bayes는 Bayes 정리를 기반으로 하는 분류 기계 학습 알고리즘입니다. 특히 감정 분석, 스팸 감지 및 텍스트 분류와 같은 텍스트 데이터를 처리할 때 매우 효율적입니다.
이 알고리즘은 모든 데이터 세트 변수가 독립적이라는 가정 때문에 "Naive"라고 불립니다. 그러나 항상 그런 것은 아닙니다.
Naive Bayes의 작동 방식을 더 자세히 설명하기 전에 다음 사항을 이해하고 있는지 확인하겠습니다.
조건부 확률
Naive Bayes 알고리즘은 조건부 확률에 기초한 Bayes 정리를 기반으로 합니다. 조건부 확률은 사건 B가 이미 발생한 경우 사건 A가 발생할 확률입니다.
예:
색깔 있는 공이 들어 있는 두 개의 병을 만들어 보겠습니다.
-
항아리 1에는 파란색 공 3개, 빨간색 공 2개, 녹색 공 4개가 있습니다.
-
항아리 2에는 파란색 공 1개, 빨간색 공 4개, 녹색 공 3개가 있습니다.
우리는 항아리 중 하나에서 파란색 공을 무작위로 선택할 확률을 계산하려고 합니다.
Jar1이나 Jar2에서 파란 공이 나올 확률의 합이 다름이 아닙니다.
이제 Jar1을 선택한 경우 파란색 공을 선택할 확률을 계산하려고 합니다.
마지막으로 파란색 공을 뽑았을 때 Jar1을 선택할 확률을 계산하려고 합니다. 여기서는 다음과 같이 명시된 Bayes 정리를 사용합니다.
나이브 베이즈 분류
Naive Bayes 분류기에서는 입력 벡터 X가 주어지면 조건부 확률을 최대화하는 클래스를 찾고 싶습니다. 따라서 Naive Bayes는 다음과 같이 공식화될 수 있습니다.
베이즈 정리를 사용하면 함수는 다음과 같습니다.
이 공식에서는 다름 아닌 클래스 Ci의 확률인 P(Ci)를 계산하기 쉽고, 사건 x가 발생할 확률인 P(x)도 쉽게 계산할 수 있습니다.
계산하기 어려운 것은 P(x|Ci)입니다. 클래스 Ci가 주어지면 사건 x의 확률입니다. 이를 더욱 단순화하려면 모든 입력 변수가 독립적이라고 가정해야 합니다. 따라서 우리는 다음과 같이 쓸 수 있습니다:
그리고 실제로 우리가 이 분류기를 "Naive"라고 부르는 것은 이러한 가정 때문입니다. 입력 변수의 독립성을 항상 보장할 수는 없기 때문입니다. Naive Bayes 분류기는 다음과 같습니다.
실제로 P(x)를 제거하여 이 공식을 더욱 단순화할 수 있습니다. 왜냐하면 P(x)는 모든 클래스에 동일하기 때문입니다.
이제 예를 살펴보겠습니다.
| 날씨 | 시간 | 요일 | 저녁 |
| ------- | -------- | --------------- | ------ |
| 지우기 | 저녁 | 주말 | 요리사 |
| 흐림 | 밤 | 평일 | 주문 |
| 비오는 날 | 밤 | 평일 | 주문 |
| 비오는 날 | 정오 | 평일 | 주문 |
| 흐림 | 정오 | 주말 | 요리사 |
| 지우기 | 밤 | 주말 | 요리사 |
| 눈 덮인 | 저녁 | 주말 | 주문 |
| 지우기 | 밤 | 평일 | 요리사 |
| 지우기 | 자정 | 주말 | 주문 |
여기에는 날씨, 시간, 요일이라는 3개의 입력 변수와 사람이 요리를 하는지 또는 저녁 식사를 주문하는지를 나타내는 하나의 목표 변수인 "저녁 식사"가 포함된 작은 데이터 세트가 있습니다. 우리는 입력 x={Clear, Evening, Weekend}의 클래스를 찾고 싶습니다.
입력 x={Clear, Evening, Weekend}에 대해 "Cooks" 클래스와 "Orders" 클래스에 대한 조건부 확률을 계산해야 합니다. 예측 클래스는 조건부 확률이 가장 높은 클래스입니다.
먼저 "Cooks" 클래스의 조건부 확률을 계산합니다.
이제 각 조건부 확률을 자체적으로 계산합니다.
클래스가 "Cooks"인 경우 Weather="Clear"일 확률은 "Cooks" 클래스가 있는 전체 라인 수에 대해 Weather가 "Clear"이고 클래스가 "Cooks"인 라인 수입니다.
다른 조건부 확률도 마찬가지입니다.
이제 확률 P(Cooks)의 경우 전체 라인 수에 대해 클래스가 "Cooks"인 라인 수입니다.
이제 다음 확률의 곱을 계산합니다.
이는 "Cooks" 클래스에 대한 것이었습니다. 이제 "Orders" 클래스에 대해서도 동일한 작업을 수행해야 합니다.
개별 확률을 계산합니다.
그리고 마지막으로 확률의 곱을 계산합니다.
마지막으로 확률이 가장 높은 클래스인 "Cooks" 클래스를 선택합니다.
이 알고리즘의 장점과 한계
장점:
-
매우 빠른 분류기입니다.
-
구현이 쉽습니다.
-
훈련 단계는 없고 추론만 가능합니다.
-
추론을 하기 위해서는 많은 데이터가 필요하지 않습니다.
제한사항:
- Naive Bayes는 입력 변수가 독립적이라고 가정하지만 항상 그렇지는 않습니다.
- Naive Bayes는 제로 빈도 문제를 겪고 있습니다. 이는 입력 변수에 0 확률을 할당하는 경우입니다. 이는 모든 조건부 확률 P(C|x)를 0으로 만듭니다. 이를 방지하는 한 가지 방법은 모든 변수에 최소 빈도 1(0 대신)을 사용하는 것입니다.
운동
다음은 예시에서 본 것과 동일한 데이터세트의 데이터프레임입니다.
귀하의 임무는 Python을 사용하여 Naive Bayes를 직접 구현하는 것입니다.
import pandas as pd
dataset = pd.DataFrame()
dataset['Weather'] = ['Clear', 'Cloudy', 'Rainy', 'Rainy', 'Cloudy', 'Clear', 'Snowy', 'Clear', 'Clear']
dataset['Time'] = ['Evening', 'Night', 'Night', 'Midday', 'Midday', 'Night', 'Evening', 'Night', 'Midnight']
dataset['Day'] = ['Weekend', 'Weekday', 'Weekday', 'Weekday', 'Weekend', 'Weekend', 'Weekend', 'Weekday', 'Weekend']
dataset['Class'] = ['Cooks', 'Orders', 'Orders', 'Orders', 'Cooks', 'Cooks', 'Orders', 'Cooks', 'Orders']
def naive_bayes(weather, time, day):
# res_dict = {class1: probability of class 1, class1: probability of class 1
return res_dict
해결책
def naive_bayes(x_weather, x_time, x_day):
TARGET = 'Dinner' # The name of the target variable
CLASSES = list(dataset['Dinner'].unique()) # The classes of the target variable
len_dataset = len(dataset) # The length of the dataset
res_dict = {} # res_dict = {class1:probability1, ..., class_n:probability_n}
# for each class of the target classes, we calculate the it's conditional probability
for class_name in CLASSES:
# the number of lines that belong to the class "class_name"
len_c = len(dataset[ (dataset[TARGET] == class_name) ])
# the number of lines that belong to the class "class_name" and have weather="x_weather"
n_weather = len(dataset[ (dataset[TARGET] == class_name) & (dataset['Weather'] == x_weather) ])
# the number of lines that belong to the class "class_name" and have time="x_time"
n_time = len(dataset[ (dataset[TARGET] == class_name) & (dataset['Time'] == x_time) ])
# the number of lines that belong to the class "class_name" and have day="x_day"
n_day = len(dataset[ (dataset[TARGET] == class_name) & (dataset['Day'] == x_day) ])
# We calculate the conditional probability:
# P(class|x) = P(weather|class) x P(time|class) x P(day|class) x P(class)
p = (n_weather / len_c) * (n_time / len_c) * (n_day / len_c) * (len_c / len_dataset) res_dict[class_name] = p
return res_dict