基于二值概率的朴素贝叶斯分类器(最小错误率贝叶斯分类器)在手写数字识别中的应用
-
- 一、 mnist数据集下载并保存至文件夹
- 二、算法原理
- 三、代码
一、 mnist数据集下载并保存至文件夹
- 下载数据集,下载下图四个包并解压
- 对网上下载的数据集进行处理,分别保存到0-9对应的文件夹
from PIL import Image
import struct
def read_image(filename_img,filename_label):
f_img = open(filename_img, 'rb')
index_img = 0
buf_img = f_img.read()
f_img.close()
f_label = open(filename_label, 'rb')
index_label = 0
buf_label = f_label.read()
f_label.close()
magic, labels = struct.unpack_from('>II', buf_label, index_label)
index_label += struct.calcsize('>II')
labelArr = [0] * labels
magic, images, rows, columns = struct.unpack_from('>IIII', buf_img, index_img)
index_img += struct.calcsize('>IIII')
for i in range(images):
image = Image.new('L', (columns, rows))
for x in range(rows):
for y in range(columns):
image.putpixel((y, x), int(struct.unpack_from('>B', buf_img, index_img)[0]))
index_img += struct.calcsize('>B')
labelArr[i] = int(struct.unpack_from('>B', buf_label, index_label)[0])
index_label += struct.calcsize('>B')
image.save('./data/test/' + str(labelArr[i]) + '/' + str(i) + '.png')
if __name__ == '__main__':
read_image('./dataset/t10k-images.idx3-ubyte','./dataset/t10k-labels.idx1-ubyte')
二、算法原理
- 求单张图片特征:将2828的手写数字区域划分成77的大块,每块的特征根据此块内黑色像素点的比例阈值化为0或1;那么就有49个0/1特征,这样就完成了特征表示。
- 将训练集和测试集图片遍历得到其特征。
- 模型训练:计算类条件概率分布即某一类数字的图像上,这49个特征取0/1 的概率,根据朴素贝叶斯方法,变成49个独立的量的联合概率分布。具体是从特定大小的样本集中统计频数,最终以频数来代替概率。
- 模型预测:就是根据上面训练出来的朴素贝叶斯模型,对任一个新的样本 x ,分别计算它是类别 j 的条件下的后验概率,取最大后验概率的类别即可。
三、代码
import numpy as np
import matplotlib.pyplot as plt
import cv2
import os
import math
train_path = './data_2400_600/train/'
test_path = './data_2400_600/test/'
class_num = 10
feature_len = 49
train_label=[0,1,2,3,4,5,6,7,8,9]
test_label=[0,1,2,3,4,5,6,7,8,9]
train_num = 2400
test_num = 600
def initArr(path):
feature=[]
pos = 0
folders=os.listdir(path)
for folder in folders:
files=os.listdir(path+folder)
for file in files:
img=cv2.imread(path+folder+'/'+file)
h,w=img.shape[0],img.shape[1]
ret, img= cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
img= np.array(img,dtype='float64')/255
x=0
for m in range(4,w+4-1,4):
y=0
for n in range(4,h+4-1,4):
k=0
for i in range(x,m):
for j in range(y,n):
if(img[i][j] == 1).all():
k=k+1
p=k/16
if(p>0.1):
feature.append(1)
else:
feature.append(0)
y+=4
x+=4
return feature
def devide(train_feature,test_feature):
train_data=[]
test_data=[]
for i in range(0, len(train_feature), 49):
train_data.append(train_feature[i:i+49])
for i in range(0, len(test_feature), 49):
test_data.append(test_feature[i:i+49])
return train_data,test_data
def train(train_data):
print('start training...')
prior_probability = np.zeros(class_num)
conditional_probability = np.zeros((class_num,feature_len,2))
s=0
for i in range(len(train_label)):
for k in range(train_num):
img=train_data[s+k]
label = train_label[i]
prior_probability[label] += 1
for j in range(feature_len):
conditional_probability[label][j][img[j]] += 1
s += train_num
for i in range(class_num):
for j in range(feature_len):
pix_0 = conditional_probability[i][j][0]
pix_1 = conditional_probability[i][j][1]
probalility_0 = (float(pix_0)/float(pix_0+pix_1))*1000000 + 1
probalility_1 = (float(pix_1)/float(pix_0+pix_1))*1000000 + 1
conditional_probability[i][j][0] = probalility_0
conditional_probability[i][j][1] = probalility_1
return prior_probability,conditional_probability
def calculate_probability(img,label):
probability = int(prior_probability[label])
for i in range(len(img)):
probability *= int(conditional_probability[label][i][img[i]])
return probability
def predict(test_data,prior_probability,conditional_probability):
print('start predicting...')
predict = []
for img in test_data:
max_label = 0
max_probability = calculate_probability(img,0)
for j in range(1,10):
probability = calculate_probability(img,j)
if max_probability < probability:
max_label = j
max_probability = probability
predict.append(max_label)
return np.array(predict)
def accuracy_score(test_predict):
acc = 0
for i in range(0,len(test_label)):
label = test_label[i]
for j in range(0,test_num):
if(label == test_predict[i*test_num+j]):
acc += 1
print('real num is:',label,' predict num is:',test_predict[i*test_num+j])
print('Test accuracy is: %f' % (acc/(class_num*test_num)))
if __name__ == '__main__':
print('start extracting feature...')
train_feature=initArr(train_path)
test_feature=initArr(test_path)
train_data,test_data=devide(train_feature,test_feature)
prior_probability,conditional_probability = train(train_data)
test_predict = predict(test_data,prior_probability,conditional_probability)
accuracy_score(test_predict)