728x90

2023-10-20 32nd Class

Bayes Theorem 정리

  • 베이즈 정리는 피처가 누적될 수록 진실에 가까워짐
  • 최신 정보가 가장 영향을 많이 줌

#️⃣ Bayes Theorem 기본 개념

베이즈 정리에서는 Hypothesis, Evidence가 존재함
베이즈정리에는 아래의 3가지 개념을 사용

  • prior
  • likelihood=P(E|H)
  • posterior=P(H|E)

이중 posterior 값은

  1. likelihood를 이용해 joint probability 값을 구하고
  2. 구한 joint 값을 이용해 도출 할수 있음
  3. posterior : P(H|E) = P(E|H) x P(H) / P(E)

#️⃣ 2가지 evidence가 있는 경우

Hypothesis
L, W => P(S|L∩W)
P(H|E1∩E2) = P(E1∩E2|H) x P(H) / P(E1∩E2)

머신러닝에서는 아래의 식으로 대체
P(H1|E1∩E2) = P(H) x P(E1|H) x P(E2|H) / P(E1∩E2)

conditional independent
P(E1|H) x P(E2|H)

  • conditional indepenent란
  • 기존의 P(H1|E1∩E2) 식에서 P(E1∩E2|H)부분을
  • P(E1|H) x P(E2|H)로 대체한 것

P(H|E1∩E2∩ … En) = P(H) x P(E1|H) x … x P(En|H) / P(E1∩E2∩…En)

  • gaussian naive bayes에서는 P(E1|H) x … x P(En|H) 이 값을
  • gaussian distribution 값을 likelihood로 상정하여 likelihood 끼리 곱하여 계산

Multinomial Naive Bayes & Gaussian Naive Bayes

Multinomial Naive Bayes

  • 멀티노미얼 나이브 베이즈에서는
  • Feature(=outlook, temperature…)와, State(=sunny, overcast, rain)를 사용
  • Descrete(이산형) 데이터를 다룸
Outlook Temperature Humidity Wind Play Tennis
Sunny Hot High Weak No
Sunny Hot High Strong No
Overcast Hot High Weak Yes
Rain Mild High Weak Yes
Rain Cool Normal Weak Yes
Rain Cool Normal Strong No
Overcast Cool Normal Strong Yes
Sunny Mild High Weak No
Sunny Cool Normal Weak Yes
Rain Mild Normal Weak Yes
Sunny Mild Normal Strong Yes
Overcast Mild High Strong Yes
Overcast Hot Normal Weak Yes
Rain Mild High Strong No

Gaussian Naive Bayes

  • Continuous(연속형) 데이터를 다룸
  • 데이터가 정규분포를 따른다고 가정
  • 정규분포를 따르기 때문에 확률값을 likelihood로 사용 (적분하지 않고 그대로 사용)

정규분포 공식


Gaussian Naive Bayes 코드 구현

#️⃣ 데이터셋

Iris.csv

#️⃣ Gaussian Naive Bayes 구현 방법

  1. Iris 데이터의 첫 번째 데이터는 test data로 분리
  2. 각 feature 별 를 계산하고, 각 feature 별 likelihood 구하기
    gaussian naive bayes에서의 likelihood는 정규분포의 확률밀도 값
  3. posterior 값을 비교하여 test data의 분류결과 확인
  4. 각 feature 별 정규분포 그래프 plot하기
  5. 각 feature 별 정규분포 그래프에 test data를 plot하기
import pandas as pd  
import numpy as np  
import matplotlib.pyplot as plt  
  
DATA_FILE_PATH = "../data/Iris.csv"  
  
  
def get_gaussian_dist(x, mu, sigma):  
    coefficient = 1 / np.sqrt(2 * np.pi * (sigma ** 2))  
    exponent = np.e ** (-(x - mu) ** 2 / (2 * sigma ** 2))  
    return coefficient * exponent  
  
  
def classify_data(test_data, te_likely_by_cls):  
    te_df = pd.DataFrame(te_likely_by_cls)  
    cls_names = [name for name, _ in te_df[0]]  
    te_df = te_df.applymap(lambda x: x[1])  
    simp_posterior = te_df.apply(np.prod)  
    print(f"simp_posterior of test data: \n {simp_posterior.map('{:,.2f}'.format)}")  
    max_idx = np.argmax(simp_posterior)  
    prod = cls_names[max_idx]  
    print(f"test data({test_data.to_list()}) is classified as {prod}")  
  
  
def get_grid_data(x_min, x_max, x_mean_std_by_cls):   
    x_grid = np.linspace(x_min, x_max, 1000)  
    y_grid = list()  
    for x in x_grid:  
        curr = [get_gaussian_dist(x, mean, std) for i, mean, std in x_mean_std_by_cls]  
        y_grid.append(curr)  
  
    y_grid = pd.DataFrame(y_grid)  
    return x_grid, y_grid  
  
  
def plot_gaussian_distribution(idx, col, x_grid, y_grid, te_likely_by_cls, test_data, axes):  
    for i in range(y_grid.shape[1]):  
        axes[idx].plot(x_grid, y_grid.iloc[:, i])  
  
    for cls, likelihood in te_likely_by_cls[idx]:  
        axes[idx].scatter(test_data[idx], likelihood, label=f"{cls} = {likelihood:.3f}")  
  
    axes[idx].set_title(col, weight='bold', fontsize=20)  
    axes[idx].legend()  
  
  
def gaussian_naive_bayes():  
    df = pd.read_csv(DATA_FILE_PATH, index_col=0)  
  
    # separate test data  
    test_data = df.iloc[0, :]  
    y_name = df.columns[-1]  
    te_likely_by_cls = list()  
  
    # figures setting  
    fig, axes = plt.subplots(nrows=4, figsize=(10, 15))  
  
    # feature iteration  
    for idx, col in enumerate(df.columns.to_list()[:-1]):  
        # subsets  
        curr_df = df[[col, y_name]]  
        y_uniques = curr_df.iloc[:, -1].unique()  
        x_by_cls = [curr_df[curr_df[y_name] == y] for y in y_uniques]  
  
        # calculate mean and std by class  
        x_mean_std_by_cls = [(c.iloc[0, 1], c.iloc[:, 0].mean(), c.iloc[:, 0].std()) for c in x_by_cls]  
        print(f"mean and std of {col}: ", x_mean_std_by_cls)  
  
        # gaussian distribution(likelihood) for test data  
        te_gs_by_cls = [(cls, get_gaussian_dist(test_data[col], mu, sigma)) for cls, mu, sigma in x_mean_std_by_cls]  
        te_likely_by_cls.append(te_gs_by_cls)  
  
        # linspace data for plotting  
        curr_min = curr_df.iloc[:, 0].min()  
        curr_max = curr_df.iloc[:, 0].max()  
        x_grid, y_grid = get_grid_data(curr_min, curr_max, x_mean_std_by_cls)  
  
        # plot gaussian distribution  
        plot_gaussian_distribution(idx, col, x_grid, y_grid, te_likely_by_cls, test_data, axes)  
  
    # classify test data  
    classify_data(test_data, te_likely_by_cls)  
    fig.tight_layout()  
  
  
if __name__ == '__main__':  
    gaussian_naive_bayes()  
    plt.show()

28_gaussian_naive_bayes.png|600

mean and std of SepalLengthCm:  [('Iris-setosa', 5.006, 0.35248968721345136), ('Iris-versicolor', 5.936, 0.5161711470638634), ('Iris-virginica', 6.587999999999998, 0.6358795932744322)]
mean and std of SepalWidthCm:  [('Iris-setosa', 3.418, 0.38102439795469095), ('Iris-versicolor', 2.7700000000000005, 0.3137983233784114), ('Iris-virginica', 2.974, 0.32249663817263746)]
mean and std of PetalLengthCm:  [('Iris-setosa', 1.464, 0.17351115943644546), ('Iris-versicolor', 4.26, 0.46991097723995795), ('Iris-virginica', 5.5520000000000005, 0.5518946956639834)]
mean and std of PetalWidthCm:  [('Iris-setosa', 0.244, 0.1072095030816784), ('Iris-versicolor', 1.3259999999999998, 0.19775268000454405), ('Iris-virginica', 2.0260000000000002, 0.2746500556366674)]
simp_posterior of test data: 
 0    8.21
1    0.00
2    0.00
dtype: object
test data([5.1, 3.5, 1.4, 0.2, 'Iris-setosa']) is classified as Iris-setosa
  • posterior 공식에서 분자의 좌측 부분인 prior과, 분모인 normalization constant는 동일하기 때문에
  • 분자의 우측 부분인 x1~x4까지의 likelihood를 곱한 값만을 simp_posterior로 설정해 각 클래스 별로 비교함
  • 3개의 simp_posterior 값 중 Iris-setosa(0)가 8.21로 가장 높게 나옴
  • 따라서 테스트 데이터는 Iris-setosa로 올바르게 분류되었음
반응형