樸素貝葉斯算法是基於條件概率的一種分類算法,通過概率大小來進行分類,經常用於分類文檔。本文用python實現樸素貝葉斯算法,並用kaggle識別手寫數字的數據集來訓練,得到81%的準確率。雖然準確率可能比不上其它如SVM、神經網絡等算法,但是樸素貝葉斯算法相對來說簡單,計算速度也較快。
樸素貝葉斯理論說明
樸素貝葉斯的基本公式:
,則w樣本屬於 類別;
,則w樣本屬於 類別。
同樣在多分類問題中, 最大時表示樣本 屬於 分類。其中 表示挑選出來的樣本 屬於 的概率。
通常 難以直接求得,可用條件概率間接求,公式如下:
其中 表示從 類中取出樣本 的概率, 表示類別 的概率,以上公式的由來相信學過概率論的同學應該都比較清楚這是條件概率。主要過程
- 計算條件概率 ,假設各特徵相互獨立,則
- 對於一個數據集,取出每一個樣本概率 值是一樣的,因此只需要比較 的值,最大值條件下的 即分類結果
- 爲防止概率數值過小(接近於0)而出現下溢,因而採用 來表示概率。
python實現
通過Kaggle識別手寫數字來實現樸素貝葉斯算法。
- 訓練數據集
import numpy as np
def trainMethod(dataSet, classesLabel):
m,n = dataSet.shape
labelSet = set(classesLabel)
numLabel = len(labelSet)
numFeat = np.ones((numLabel,n))
piLabel = np.zeros(numLabel)
piDenom = np.ones(numLabel)+1
for label in labelSet:
for i in range(m):
if classesLabel[i] == label:
numFeat[label] += dataSet[i]
piDenom[label] += sum(dataSet[i])
piLabel[label] +=1
for j in labelSet:
numFeat[j] = np.log(numFeat[j]/piDenom[j])
piLabel = piLabel/m
return numFeat, piLabel
- 測試算法
import numpy as np
import pandas as pd
import csv
#預測函數
def predict(testVec, piFeat, piLabel):
maxPi = sum(testVec * piFeat[0]) + np.log(piLabel[0]) # 初始化
maxIndex = 0
for i in range(len(piLabel)):
currentPi = sum(testVec * piFeat[i]) + np.log(piLabel[i])
if currentPi > maxPi:
maxPi = currentPi
maxIndex = i
return maxIndex
#圖片二像素化,即把圖片變爲黑白,沒有灰度
def normalizing(array):
m,n = array.shape
for i in range(m):
for j in range(n):
if array[i, j]!=0:
array[i, j]=1 #非零全部轉化爲1
return array
# 定義數據集加載函數
def loadTrainData():
csv_data = np.array(pd.read_csv('kaggle_dataset/digit_recognize/train.csv'))
label = csv_data[:,0] #取值label
data = csv_data[:,1:] #取像素質值
return label, normalizing(data)
# 加載測試數據,測試數據中沒有label
def loadTestData():
csv_test = np.array(pd.read_csv('kaggle_dataset/digit_recognize/test.csv'))
return csv_test
# 將數據寫入到csv中,python3讀寫
def saveResultCsv(result, csvName):
with open(csvName, 'w', newline='') as myFile:
writer = csv.writer(myFile)
heads = ['ImageId', 'Label']
writer.writerow(heads)
j = 1
for i in result:
temp = [j, i]
writer.writerow(temp)
j += 1
label,dataSet= loadTrainData()
dataTest = loadTestData()
piFeat, piLabel = trainMethod(dataSet, label)
result = []
for i in range(len(dataTest)):
result.append(predict(dataTest[i], piFeat, piLabel))
saveResultCsv(result, 'kaggle_dataset/digit_recognize/result_NB.csv')
- 提交結果,準確率爲81%