機器學習作業4——樸素貝葉斯分類器

目錄

一、理論

一個例子:

二、代碼

對于代碼的解釋:

1.fit函數:

2.predict函數:

三、實驗結果

原因分析:


一、理論

樸素貝葉斯分類器基于貝葉斯定理進行分類,通過后驗概率來判斷將新數據歸為哪一類。通過利用貝葉斯定理計算后驗概率,并選擇具有最高后驗概率的類別作為預測結果,樸素貝葉斯分類器能夠在考慮了先驗概率和觀察到的數據特征后,做出基于統計推斷的分類決策,從而實現有效的分類。

步驟:

1.計算先驗概率:先驗概率表示了在沒有任何其他信息的情況下,一個數據點屬于每個類別的概率。

2.計算條件概率:條件概率表示了在給定某一類別的情況下,某個特征取某個值的概率。

3.計算后驗概率:當有一個新的數據點需要分類時,樸素貝葉斯根據該數據點的特征值,利用貝葉斯定理計算每個類別的后驗概率。后驗概率表示了在考慮了新的觀察結果后,每個類別的概率。

4.做出分類:根據計算得到的后驗概率,選擇具有最高后驗概率類別作為預測結果

先驗概率:

P(Y=c_k) = \frac{|D_{c_k}|}{|D|}

其中:ck是類別,D是數據數量,Dck是類別為ck的數據數量。

條件概率:

P(X^{(i)}=a_{i,j}|Y=c_k) = \frac{|D_{c_k}^{(i)}(a_{i,j})|}{|D_{c_k}|}

其中:Xi代表第i個特征,ai,j代表第i個特征中第j個類型,D_{c_k}^{(i)}(a_{i,j})代表在類別為ck時,在第i個特征中的第j個類型的數量。

后驗概率:

P(Y=c_k|X=x) = \frac{P(Y=c_k) \cdot \prod_{j=1}^{n} P(X^{(j)}=x^{(j)}|Y=c_k)}{\sum_{i=1}^{K} P(Y=c_i) \cdot \prod_{j=1}^{n} P(X^{(j)}=x^{(j)}|Y=c_i)}

因為我們只需要分類,因為不同后驗概率分母都相同,所以可以把分母去掉只需要比較分子的大小即可,即:

P(Y=c_k|X=x) = {P(Y=c_k) \cdot \prod_{i=1}^{n} P(X^{(i)}=x^{(i)}|Y=c_k)}

其中:\prod_{i=1}^{n} P(X^{(i)}=x^{(i)}|Y=c_k)代表當前測試數據的每個類型為xi,在ck類別下的條件概率的連乘積。

可以看到公式簡潔了不少。

一個例子:

假設數據集:

特征1特征2類別
11A
10A
01B
01A
10B

現在預測一個特征11特證21的測試元組是什么類別。

首先計算類別的先驗概率和所有條件概率:

P(A)=?3/5,P(B)=?2/5

對于特征1:
P1(1∣A)=?2/3,P1(1 | B)= 1/2,

對于特征2:

P2(1?| A) = 2/3,P2(1?| B) = 1/2

然后計算預測為A和B的后驗概率,并比較大小,得出結果

P(A|X) = P(A)*P1(1∣A)*P2(1?| A) = 4/15
P(B|X) = P(B)*P1(1 | B)*P2(1 | B) = 1/10

可以看到P(A|X)比較大,所以是A類?

?

二、代碼

import numpy as np  
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, f1_score, precision_score, recall_score class NaiveBayesClassifier:def __init__(self):self.class_prior = {}  # 存儲類別的先驗概率self.feature_prob = {}  # 存儲特征在各個類別下的條件概率def fit(self, X, y):n_samples, n_features = X.shape  # 獲取樣本數和特征數self.classes = np.unique(y)  # 獲取目標標簽中的唯一類別值print("計算先驗概率:")for c in self.classes:# 統計每個類別在目標標簽中的出現次數,并除以樣本總數,得到先驗概率self.class_prior[c] = np.sum(y == c) / n_samplesprint("先驗概率: 類別, 概率 "+repr(c)+" "+repr(self.class_prior[c]))# 外層循壞遍歷類別,內層循環遍歷每個特征,內層循環每次要計算出每個特征下不同取值的在當前類別下的條件概率,存放到[c][feature_index]下print("計算條件概率:")for c in self.classes:self.feature_prob[c] = {}  # 初始化存儲特征條件概率的字典for feature_index in range(n_features):# 對于每個特征,統計在當前類別下的取值及其出現次數,并除以總次數,得到條件概率# values是feature_index列中不同的取值,counts是這些不同取值的個數(在類別為C下的)values, counts = np.unique(X[y == c, feature_index], return_counts=True)self.feature_prob[c][feature_index] = dict(zip(values, counts / np.sum(counts)))#dict是變為以values和counts/np.sum的字典,zip就是一個方便的操作for i in range(len(counts)):print("條件概率:P(" + repr(values[i]) + "|" + repr(c) + ") = " + repr(self.feature_prob[c][feature_index][values[i]]))def predict(self, X):predictions = []  # 存儲預測結果的列表#對于測試集中的每個元素cnt = 0for x in X:print("\n對于第" + repr(cnt) + "個測試集:")cnt+=1max_posterior_prob = -1  # 最大后驗概率初始化為-1predicted_class = None  # 預測類別初始化為空#對于每個類別for c in self.classes:# 計算后驗概率,先驗概率乘以各個特征的條件概率posterior_prob = self.class_prior[c]print("對于類別"+repr(c)+" = "+"[先驗"+repr(self.class_prior[c])+"]", end = '')#對于每個特征for feature_index, feature_value in enumerate(x):if feature_value in self.feature_prob[c][feature_index]:print(" * [P("+ repr(feature_value) + "|" + repr(c) + ") = " + repr(self.feature_prob[c][feature_index][feature_value]) + "]", end = '')posterior_prob *= self.feature_prob[c][feature_index][feature_value]else:print(" * 1")# 更新預測值print(" = " + repr(posterior_prob))if posterior_prob > max_posterior_prob:max_posterior_prob = posterior_probpredicted_class = cpredictions.append(predicted_class)  # 將預測結果添加到列表中return predictions  # 返回預測結果列表data = {'outlook': ['sunny', 'sunny', 'overcast', 'rain', 'rain', 'rain', 'overcast', 'sunny', 'sunny', 'rain', 'rain', 'overcast', 'overcast', 'rain'],'temperature': ['hot', 'hot', 'hot', 'mild', 'cool', 'cool', 'cool', 'mild', 'cool', 'mild', 'mild', 'mild', 'hot', 'mid'],'humidity': ['high', 'high', 'high', 'high', 'normal', 'normal', 'normal', 'high', 'normal', 'normal', 'normal', 'high', 'normal', 'high'],'wind': ['weak', 'strong', 'weak', 'weak', 'weak', 'strong', 'strong', 'weak', 'weak', 'weak', 'strong', 'strong', 'weak', 'strong'],'playtennis': ['no', 'no', 'yes', 'yes', 'yes', 'no', 'yes', 'no', 'yes', 'yes', 'yes', 'yes', 'yes', 'no']
}
#創建DataFrame
df = pd.DataFrame(data)
X = df.drop('playtennis', axis=1)#axis=1刪除列,=0刪除行
y = df['playtennis']# 將數據集分為訓練集和測試集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=3)
X_train = X_train.values#化為二維數組,便于遍歷
X_test = X_test.values
y_train = y_train.values
y_test = y_test.valuesprint("訓練集:")
for i in range(len(y_train)):print(repr(i)+": "+repr(X_train[i])+"  "+repr(y_train[i]))
print("測試集:")
for i in range(len(y_test)):print(repr(i)+": "+repr(X_test[i])+"  "+repr(y_test[i]))nb_classifier = NaiveBayesClassifier()
nb_classifier.fit(X_train, y_train)y_pred = nb_classifier.predict(X_test)
print("預測結果:")
for i in range(len(y_pred)):print(repr(i)+"正確,預測: "+repr(y_test[i])+", "+repr(y_pred[i]))accuracy = accuracy_score(y_test, y_pred)
precision = precision_score(y_test, y_pred, pos_label='yes')
recall = recall_score(y_test, y_pred, pos_label='yes')
f1 = f1_score(y_test, y_pred, pos_label='yes')
print("準確率:", accuracy)  
print("精確率:", precision)  
print("召回率:", recall)  
print("f1:", f1)  

對于重要代碼的解釋:

1.fit函數:

? ? ? 訓練測試集的主要代碼,先把訓練集中所有的條件概率和先驗概率算出來,在后面的預測中會使用到。

先驗概率:

print("計算先驗概率:")for c in self.classes:# 統計每個類別在目標標簽中的出現次數,并除以樣本總數,得到先驗概率self.class_prior[c] = np.sum(y == c) / n_samplesprint("先驗概率: 類別, 概率 "+repr(c)+" "+repr(self.class_prior[c]))

所有條件概率:

print("計算條件概率:")for c in self.classes:self.feature_prob[c] = {}  # 初始化存儲特征條件概率的字典for feature_index in range(n_features):# 對于每個特征,統計在當前類別下的取值及其出現次數,并除以總次數,得到條件概率# values是feature_index列中不同的取值,counts是這些不同取值的個數(在類別為C下的)values, counts = np.unique(X[y == c, feature_index], return_counts=True)self.feature_prob[c][feature_index] = dict(zip(values, counts / np.sum(counts)))for i in range(len(counts)):print("條件概率:P(" + repr(values[i]) + "|" + repr(c) + ") = " + repr(self.feature_prob[c][feature_index][values[i]]))

?結果:

2.predict函數:

這個函數用于測試集的預測,對于測試集中的每個元組,都要對于所有類別,計算一次該類別下的后驗概率,然后選擇所有類別中后驗概率最大的,作為預測結果,而每個后驗概率,通過該元組下的每個特征下的類型對應的條件概率的累乘和該類別的先驗概率的乘積來確定。

對于每個元組:

for x in X:print("\n對于第" + repr(cnt) + "個測試集:")cnt+=1max_posterior_prob = -1  # 最大后驗概率初始化為-1predicted_class = None  # 預測類別初始化為空

對于每個類別:

for c in self.classes:posterior_prob = self.class_prior[c]

對于每個特征:

for feature_index, feature_value in enumerate(x):if feature_value in self.feature_prob[c][feature_index]:print(" * [P("+ repr(feature_value) + "|" + repr(c) + ") = " + repr(self.feature_prob[c][feature_index][feature_value]) + "]", end = '')posterior_prob *= self.feature_prob[c][feature_index][feature_value]else:print(" * 1")

每次計算完后,維護最大值以及類型:

if posterior_prob > max_posterior_prob:max_posterior_prob = posterior_probpredicted_class = c

每個元組計算完后,添加到預測數組中,最后返回預測數組即可。

三、實驗結果

上圖是最好的一個實驗結果,所有指標為1,其他的實驗結果準確率較低

原因分析:

? ? ? ? 這個訓練集數據過小,但是特征和每個特征中的類型又比較多,再加上測試集一共就13條,數據使用不同的隨機種子會使得一些測試集中的特征在不同類別下的條件概率沒有出現過,因為沒有出現過,直接就不處理這個特征了,就容易出現誤差。

例如:

當隨機種子為1時:

當隨機種子為4時:

樸素貝葉斯分類器優缺點分析:

優點:

  1. 適用廣:樸素貝葉斯算法在處理大規模數據時表現良好,適用于許多實際問題。

  2. 對小規模數據表現良好:即使在小規模數據集上,樸素貝葉斯分類器也能有好的結果。

  3. 對缺失數據不敏感:樸素貝葉斯算法對缺失數據不敏感,即使有部分特征缺失或者未出現,仍然可以有效地進行分類。

缺點:

  1. 假設過于簡化:樸素貝葉斯假設特征之間相互獨立,在現實中,數據一般難以是真正獨立的,因此會導致結果不準確。

  2. 處理連續性特征較差:樸素貝葉斯算法通常假設特征是離散的,對于連續性特征的處理不夠靈活,可能會影響分類性能。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/10969.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/10969.shtml
英文地址,請注明出處:http://en.pswp.cn/web/10969.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

MFC的CPen與CBush畫圖對象使用步驟

在MFC中,CPen和CBrush是兩個常用的繪圖對象,分別用于定義畫筆和畫刷,可以用于繪制圖形、填充區域等。下面我會詳細介紹如何在MFC中使用CPen和CBrush來繪制和填充圖形。 使用 CPen 繪制圖形: 創建 CPen 對象: 首先&am…

橋梁監控可視化大屏:現代橋梁管理的必備呀。

橋梁監控上可視化有幾個重要的原因: 01.實時監控: 可視化的監控系統可以實時顯示橋梁的各項監測數據,包括結構變形、振動、溫度等,使監控人員能夠實時了解橋梁的狀態,及時發現異常情況并采取相應的措施。 02.數據分析…

MySQL前綴索引、臟頁和干凈頁、COUNT(*)討論、表刪除內存問題

文章目錄 如何加索引如何給身份證號添加索引 SQL語句變慢臟頁 (Dirty Pages)干凈頁 (Clean Pages)為何區分臟頁和干凈頁處理臟頁管理策略 flush如何控制 為什么刪除表數據后表文件大小不變問題背景核心原因數據存儲方式參數影響 解決方案1. 調整innodb_file_per_table設置2. 使…

C#之三目運算、三元運算

三目運算也叫三元運算是一種簡單的條件語句,也稱為條件運算符。它可以根據一個表達式的結果確定另一個表達式的值。三目運算符使用“?”和“:”來表示。 注意使用bool值進行運算 三目運算符: 套路 三個空位 兩個符號 固定寫法 : 空位1 ? 空位2 : 空位3; 關鍵…

2024.5.8 —— LeetCode 高頻題復盤

目錄 檢測循環依賴7. 整數反轉LCR 170. 交易逆序對的總數55. 跳躍游戲45. 二叉樹的后序遍歷50. Pow(x, n)40. 組合總和 II74. 搜索二維矩陣26. 刪除有序數組中的重復項61. 旋轉鏈表 檢測循環依賴 題目鏈接 def haveCircularDependency(self, n: int, prerequisites):g [[]for…

MATLAB實現遺傳算法優化選址-路徑LRP問題(Location-Routing Problem)

MATLAB實現遺傳算法優化選址-路徑LRP問題(Location-Routing Problem) 一、模型 選址車輛路徑問題(Location-Routing Problem, LRP)是一個組合優化問題,旨在同時優化設施位置的選擇和車輛的配送路徑。在這個問題中,我們考慮一個由…

機器學習 - 決策樹

1. 決策樹基礎 定義與概念 決策樹是一種監督學習算法,主要用于分類和回歸任務。它通過學習從數據特征到輸出標簽的映射規則,構建一個樹形結構。在分類問題中,決策樹的每個葉節點代表一個類別。 案例分析 假設我們有一個關于天氣和是否進行…

linux防火墻的操作

linux防火墻的操作 前言1查看防火墻狀態2暫時關閉防火墻3永久關閉防火墻4開啟防火墻5開啟指定端口6關閉指定端口7立即生效8查看開放的端口前言 systemctl是管理linux中服務的命令,可以對服務進行啟動、停止、重啟、查看狀態等操作 firewall-cmd是linux中專門用于控制防火墻的…

并發-守護線程setDaemon()

目錄 為什么存在 什么是守護線程 創建守護線程 在使用守護線程時需要注意以下幾點 可以使用isDaemon()方法來檢查線程是否是守護線程 例1:上面提到當JVM中只剩下守護線程的時候,JVM就會退出,那么寫段代碼測試下 例2:thread…

小紅的字符串構造和小紅的排列構造

小紅的字符串構造 小紅希望你構造一個長度為nnn的、僅包含小寫字母的字符串,其中恰好有kkk個長度大于1的回文子串。你能幫幫她嗎?輸入兩個整數n,k,用空格隔開。 1≤n≤10^5,0≤k≤n/2.一個字符串。如果有多解輸出任意即可。 可以證明&#x…

[Bug]:由于中國防火墻,無法連接 huggingface.co

問題描述 : OSError: We couldnt connect to https://huggingface.co to load this file, couldnt find it in the cached files and it looks like youscan/ukr-roberta-base is not the path to a directory containing a file named config. Json. Checkout your internet …

[AIGC] 幾道 redis數據結構相關面試題

文章目錄 7. 數據類型的實現8. 什么是空間預分配以及惰性空間釋放,SDS 是怎么實現的9. 為什么說 SDS 是二進制安全的呢10. 說說 redis 里的對象11. 使用 RedisObject 的好處12. RedisObject 的具體結構是什么 7. 數據類型的實現 8. 什么是空間預分配以及惰性空間釋放…

Vue3實戰筆記(16)—pinia基本用法--Getter

文章目錄 前言一、pinia的getter簡單理解二、訪問其他 store 的 getter總結 前言 在 Pinia 中,getter 類似于 Vuex 中的 getter,允許你從 store 中派生出一些狀態,而不需要修改原始狀態。這使得我們可以創建基于現有狀態的計算屬性。 一、pi…

練習題(2024/5/12)

1二分查找 給定一個 n 個元素有序的(升序)整型數組 nums 和一個目標值 target ,寫一個函數搜索 nums 中的 target,如果目標值存在返回下標,否則返回 -1。 示例 1: 輸入: nums [-1,0,3,5,9,12], target 9 輸出: 4…

樹莓派C語言開發

安裝C語言編譯器和開發工具 sudo apt update sudo apt install build-essential 此命令會安裝GCC編譯器以及make等其他工具,這些都是C語言程序開發過程中必需的。 配置文本編輯器 樹莓派默認安裝了幾個文本編輯器,如Nano和Vim。如果你對這些編輯器不熟…

如何遠程訪問?

遠程訪問是指在不同的地理位置之間通過網絡連接來實現對目標設備或系統的訪問。無論是在個人生活還是商業領域,遠程訪問都起到了重要的作用,幫助人們實現高效的工作和便捷的生活。本文將介紹一款名為【天聯】的組網產品,它是一款強大的異地組…

Linux與Windows互傳文件【筆記】

Linux與Windows互傳文件【筆記】 前言前言推薦Linux與Windows互傳文件首先確保Windows安裝ssh如何傳送文件問題 最后 前言 這是陳舊已久的草稿2023-05-10 00:01:24 這個是準備把計組課程華為智能計組的,傳輸文件。 最后發現,好像沒有實現了。 現在202…

汽車線控轉向系統介紹

汽車線控轉向系統由方向盤總成、轉向執行總成和主控制器(ECU)三個主要部分以及自動防故障系統、電源等輔助系統組成。 線控轉向系統(Steering-By-Wire),取消了方向盤和轉向車輪之間的機械連接部件,徹底擺脫了機械固件的限制,完全由電能來實現…

【LeetCode】數組——hashmap的妙用

在遇到一類題目時,通過雙for循環也可暴力破解,但我們可以通過用hashmap來代替一次for循環節約時間開支,在算法上屬于用空間換時間,也能幫助我們更好的理解hashmap這一種重要數據結構,并熟悉hashmap的重要方法。 1.兩數…

31Windows精簡系統下載推薦

Windows精簡系統下載推薦 世界上有很多人在做Windows精簡系統,去掉了他們認為不必要的功能和插件,達到了減小系統安裝包體積,提升系統運行流暢度和穩定性的目的。 筆者推薦使用大佬不忘初心制作的精簡版系統,最精簡windows10系統安…