農林漁牧網

您現在的位置是:首頁 > 農業

高斯樸素貝葉斯分類的原理解釋和手寫程式碼實現

2022-04-10由 deephub 發表于 農業

數學標準差是什麼

高斯樸素貝葉斯 (GNB) 是一種基於機率方法和高斯分佈的機器學習的分類技術。 高斯樸素貝葉斯假設每個引數(也稱為特徵或預測變數)具有預測輸出變數的獨立能力。 所有引數的預測組合是最終預測,它返回因變數被分類到每個組中的機率,最後的分類被分配給機率較高的分組(類)。

高斯樸素貝葉斯分類的原理解釋和手寫程式碼實現

什麼是高斯分佈?

高斯分佈也稱為正態分佈,是描述自然界中連續隨機變數的統計分佈的統計模型。 正態分佈由其鐘形曲線定義, 正態分佈中兩個最重要的特徵是均值 (μ) 和標準差 (σ)。 平均值是分佈的平均值,標準差是分佈在平均值周圍的“寬度”。

重要的是要知道正態分佈的變數 (X) 從 -∞ < X < +∞ 連續分佈(連續變數),並且模型曲線下的總面積為 1。

多分類的高斯樸素貝葉斯

匯入必要的庫:

from random import random

from random import randint

import pandas as pd

import numpy as np

import seaborn as sns

import matplotlib。pyplot as plt

import statistics

from sklearn。model_selection import train_test_split

from sklearn。preprocessing import StandardScaler

from sklearn。naive_bayes import GaussianNB

from sklearn。metrics import confusion_matrix

from mlxtend。plotting import plot_decision_regions

現在建立一個預測變數呈正態分佈的資料集。

#Creating values for FeNO with 3 classes:

FeNO_0 = np。random。normal(20, 19, 200)

FeNO_1 = np。random。normal(40, 20, 200)

FeNO_2 = np。random。normal(60, 20, 200)

#Creating values for FEV1 with 3 classes:

FEV1_0 = np。random。normal(4。65, 1, 200)

FEV1_1 = np。random。normal(3。75, 1。2, 200)

FEV1_2 = np。random。normal(2。85, 1。2, 200)

#Creating values for Broncho Dilation with 3 classes:

BD_0 = np。random。normal(150,49, 200)

BD_1 = np。random。normal(201,50, 200)

BD_2 = np。random。normal(251, 50, 200)

#Creating labels variable with three classes:(2)disease (1)possible disease (0)no disease:

not_asthma = np。zeros((200,), dtype=int)

poss_asthma = np。ones((200,), dtype=int)

asthma = np。full((200,), 2, dtype=int)

#Concatenate classes into one variable:

FeNO = np。concatenate([FeNO_0, FeNO_1, FeNO_2])

FEV1 = np。concatenate([FEV1_0, FEV1_1, FEV1_2])

BD = np。concatenate([BD_0, BD_1, BD_2])

dx = np。concatenate([not_asthma, poss_asthma, asthma])

#Create DataFrame:

df = pd。DataFrame()

#Add variables to DataFrame:

df[‘FeNO’] = FeNO。tolist()

df[‘FEV1’] = FEV1。tolist()

df[‘BD’] = BD。tolist()

df[‘dx’] = dx。tolist()

#Check database:

df

高斯樸素貝葉斯分類的原理解釋和手寫程式碼實現

我們的df有 600 行和 4 列。 現在我們可以透過視覺化檢查變數的分佈:

fig, axs = plt。subplots(2, 3, figsize=(14, 7))

sns。kdeplot(df[‘FEV1’], shade=True, color=“b”, ax=axs[0, 0])

sns。kdeplot(df[‘FeNO’], shade=True, color=“b”, ax=axs[0, 1])

sns。kdeplot(df[‘BD’], shade=True, color=“b”, ax=axs[0, 2])

sns。distplot( a=df[“FEV1”], hist=True, kde=True, rug=False, ax=axs[1, 0])

sns。distplot( a=df[“FeNO”], hist=True, kde=True, rug=False, ax=axs[1, 1])

sns。distplot( a=df[“BD”], hist=True, kde=True, rug=False, ax=axs[1, 2])

plt。show()

高斯樸素貝葉斯分類的原理解釋和手寫程式碼實現

透過人肉的檢查,資料似乎接近高斯分佈。 還可以使用 qq-plots仔細檢查:

from statsmodels。graphics。gofplots import qqplot

from matplotlib import pyplot

#q-q plot:

fig, axs = pyplot。subplots(1, 3, figsize=(15, 5))

qqplot(df[‘FEV1’], line=‘s’, ax=axs[0])

qqplot(df[‘FeNO’], line=‘s’, ax=axs[1])

qqplot(df[‘BD’], line=‘s’, ax=axs[2])

pyplot。show()

高斯樸素貝葉斯分類的原理解釋和手寫程式碼實現

雖然不是完美的正態分佈,但已經很接近了。下面檢視的資料集和變數之間的相關性:

#Exploring dataset:

sns。pairplot(df, kind=“scatter”, hue=“dx”)

plt。show()

高斯樸素貝葉斯分類的原理解釋和手寫程式碼實現

可以使用框線圖檢查這三組的分佈,看看哪些特徵可以更好的區分出類別

# plotting both distibutions on the same figure

fig, axs = plt。subplots(2, 3, figsize=(14, 7))

fig = sns。kdeplot(df[‘FEV1’], hue= df[‘dx’], shade=True, color=“r”, ax=axs[0, 0])

fig = sns。kdeplot(df[‘FeNO’], hue= df[‘dx’], shade=True, color=“r”, ax=axs[0, 1])

fig = sns。kdeplot(df[‘BD’], hue= df[‘dx’], shade=True, color=“r”, ax=axs[0, 2])

sns。boxplot(x=df[“dx”], y=df[“FEV1”], palette = ‘magma’, ax=axs[1, 0])

sns。boxplot(x=df[“dx”], y=df[“FeNO”], palette = ‘magma’,ax=axs[1, 1])

sns。boxplot(x=df[“dx”], y=df[“BD”], palette = ‘magma’,ax=axs[1, 2])

plt。show()

高斯樸素貝葉斯分類的原理解釋和手寫程式碼實現

手寫樸素貝葉斯分類

手寫程式碼並不是讓我們重複的製造輪子,而是透過自己編寫程式碼對演算法更好的理解。在進行貝葉斯分類之前,先要了解正態分佈。

正態分佈的數學公式定義了一個觀測值出現在某個群體中的機率:

高斯樸素貝葉斯分類的原理解釋和手寫程式碼實現

我們可以建立一個函式來計算這個機率:

def normal_dist(x , mean , sd):

prob_density = (1/sd*np。sqrt(2*np。pi)) * np。exp(-0。5*((x-mean)/sd)**2)

return prob_density

知道正態分佈公式,就可以計算該樣本在三個分組(分類)機率。 首先,需要計算所有預測特徵和組的均值和標準差:

#Group 0:

group_0 = df[df[‘dx’] == 0]print(‘Mean FEV1 group 0: ’, statistics。mean(group_0[‘FEV1’]))

print(‘SD FEV1 group 0: ’, statistics。stdev(group_0[‘FEV1’]))

print(‘Mean FeNO group 0: ’, statistics。mean(group_0[‘FeNO’]))

print(‘SD FeNO group 0: ’, statistics。stdev(group_0[‘FeNO’]))

print(‘Mean BD group 0: ’, statistics。mean(group_0[‘BD’]))

print(‘SD BD group 0: ’, statistics。stdev(group_0[‘BD’]))

#Group 1:

group_1 = df[df[‘dx’] == 1]

print(‘Mean FEV1 group 1: ’, statistics。mean(group_1[‘FEV1’]))

print(‘SD FEV1 group 1: ’, statistics。stdev(group_1[‘FEV1’]))

print(‘Mean FeNO group 1: ’, statistics。mean(group_1[‘FeNO’]))

print(‘SD FeNO group 1: ’, statistics。stdev(group_1[‘FeNO’]))

print(‘Mean BD group 1: ’, statistics。mean(group_1[‘BD’]))

print(‘SD BD group 1: ’, statistics。stdev(group_1[‘BD’]))

#Group 2:

group_2 = df[df[‘dx’] == 2]

print(‘Mean FEV1 group 2: ’, statistics。mean(group_2[‘FEV1’]))

print(‘SD FEV1 group 2: ’, statistics。stdev(group_2[‘FEV1’]))

print(‘Mean FeNO group 2: ’, statistics。mean(group_2[‘FeNO’]))

print(‘SD FeNO group 2: ’, statistics。stdev(group_2[‘FeNO’]))

print(‘Mean BD group 2: ’, statistics。mean(group_2[‘BD’]))

print(‘SD BD group 2: ’, statistics。stdev(group_2[‘BD’]))

高斯樸素貝葉斯分類的原理解釋和手寫程式碼實現

現在,使用一個隨機的樣本進行測試:

FEV1 = 2。75

FeNO = 27

BD = 125

#Probability for:

#FEV1 = 2。75

#FeNO = 27

#BD = 125

#We have the same number of observations, so the general probability is: 0。33

Prob_geral = round(0。333, 3)

#Prob FEV1:

Prob_FEV1_0 = round(normal_dist(2。75, 4。70, 1。08), 10)

print(‘Prob FEV1 0: ’, Prob_FEV1_0)

Prob_FEV1_1 = round(normal_dist(2。75, 3。70, 1。13), 10)

print(‘Prob FEV1 1: ’, Prob_FEV1_1)

Prob_FEV1_2 = round(normal_dist(2。75, 3。01, 1。22), 10)

print(‘Prob FEV1 2: ’, Prob_FEV1_2)

#Prob FeNO:

Prob_FeNO_0 = round(normal_dist(27, 19。71, 19。29), 10)

print(‘Prob FeNO 0: ’, Prob_FeNO_0)

Prob_FeNO_1 = round(normal_dist(27, 42。34, 19。85), 10)

print(‘Prob FeNO 1: ’, Prob_FeNO_1)

Prob_FeNO_2 = round(normal_dist(27, 61。78, 21。39), 10)

print(‘Prob FeNO 2: ’, Prob_FeNO_2)

#Prob BD:

Prob_BD_0 = round(normal_dist(125, 152。59, 50。33), 10)

print(‘Prob BD 0: ’, Prob_BD_0)

Prob_BD_1 = round(normal_dist(125, 199。14, 50。81), 10)

print(‘Prob BD 1: ’, Prob_BD_1)

Prob_BD_2 = round(normal_dist(125, 256。13, 47。04), 10)

print(‘Prob BD 2: ’, Prob_BD_2)

#Compute probability:

Prob_group_0 = Prob_geral*Prob_FEV1_0*Prob_FeNO_0*Prob_BD_0

print(‘Prob group 0: ’, Prob_group_0)

Prob_group_1 = Prob_geral*Prob_FEV1_1*Prob_FeNO_1*Prob_BD_1

print(‘Prob group 1: ’, Prob_group_1)

Prob_group_2 = Prob_geral*Prob_FEV1_2*Prob_FeNO_2*Prob_BD_2

print(‘Prob group 2: ’, Prob_group_2)

高斯樸素貝葉斯分類的原理解釋和手寫程式碼實現

可以看到,這個樣本具有屬於第 2 組的機率最高。這就是樸素貝葉斯手動計算的的流程,但是這種成熟的演算法可以使用來自 Scikit-Learn 的更高效的實現。

Scikit-Learn的分類器樣例

Scikit-Learn的GaussianNB為我們提供了更加高效的方法,下面我們使用GaussianNB進行完整的分類例項。首先建立 X 和 y 變數,並執行訓練和測試拆分:

#Creating X and y:

X = df。drop(‘dx’, axis=1)

y = df[‘dx’]

#Data split into train and test:

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0。30)

在輸入之前還需要使用 standardscaler 對資料進行標準化:

sc = StandardScaler()

X_train = sc。fit_transform(X_train)

X_test = sc。transform(X_test)

現在構建和評估模型:

#Build the model:

classifier = GaussianNB()

classifier。fit(X_train, y_train)

#Evaluate the model:

print(“training set score: %f” % classifier。score(X_train, y_train))

print(“test set score: %f” % classifier。score(X_test, y_test))

下面使用混淆矩陣來視覺化結果:

# Predicting the Test set results

y_pred = classifier。predict(X_test)

#Confusion Matrix:

cm = confusion_matrix(y_test, y_pred)

print(cm)

高斯樸素貝葉斯分類的原理解釋和手寫程式碼實現

透過混淆矩陣可以看到,的模型最適合預測類別 0,但類別 1 和 2 的錯誤率很高。為了檢視這個問題,我們使用變數構建決策邊界圖:

df。to_csv(‘data。csv’, index = False)

data = pd。read_csv(‘data。csv’)

def gaussian_nb_a(data):

x = data[[‘BD’,‘FeNO’,]]。values

y = data[‘dx’]。astype(int)。values

Gauss_nb = GaussianNB()

Gauss_nb。fit(x,y)

print(Gauss_nb。score(x,y))

#Plot decision region:

plot_decision_regions(x,y, clf=Gauss_nb, legend=1)

#Adding axes annotations:

plt。xlabel(‘X_train’)

plt。ylabel(‘y_train’)

plt。title(‘Gaussian Naive Bayes’)

plt。show()

def gaussian_nb_b(data):

x = data[[‘BD’,‘FEV1’,]]。values

y = data[‘dx’]。astype(int)。values

Gauss_nb = GaussianNB()

Gauss_nb。fit(x,y)

print(Gauss_nb。score(x,y))

#Plot decision region:

plot_decision_regions(x,y, clf=Gauss_nb, legend=1)

#Adding axes annotations:

plt。xlabel(‘X_train’)

plt。ylabel(‘y_train’)

plt。title(‘Gaussian Naive Bayes’)

plt。show()

def gaussian_nb_c(data):

x = data[[‘FEV1’,‘FeNO’,]]。values

y = data[‘dx’]。astype(int)。values

Gauss_nb = GaussianNB()

Gauss_nb。fit(x,y)

print(Gauss_nb。score(x,y))

#Plot decision region:

plot_decision_regions(x,y, clf=Gauss_nb, legend=1)

#Adding axes annotations:

plt。xlabel(‘X_train’)

plt。ylabel(‘y_train’)

plt。title(‘Gaussian Naive Bayes’)

plt。show()

gaussian_nb_a(data)

gaussian_nb_b(data)

gaussian_nb_c(data)

高斯樸素貝葉斯分類的原理解釋和手寫程式碼實現

透過決策邊界我們可以觀察到分類錯誤的原因,從圖中我們看到,很多點都是落在決策邊界之外的,如果是實際資料我們需要分析具體原因,但是因為是測試資料所以我們也不需要更多的分析。

https://www。overfit。cn/post/0457f85f2c184ff0864db5256654aef1

作者:Carla Martins