机器学习_朴素贝叶斯算法识别手写数字

朴素贝叶斯算法是基于条件概率的一种分类算法,通过概率大小来进行分类,经常用于分类文档。本文用python实现朴素贝叶斯算法,并用kaggle识别手写数字的数据集来训练,得到81%的准确率。虽然准确率可能比不上其它如SVM、神经网络等算法,但是朴素贝叶斯算法相对来说简单,计算速度也较快。

朴素贝叶斯理论说明

朴素贝叶斯的基本公式:
P ( c 1 | w ) > P ( c 0 | w ) ,则w样本属于 c 1 类别;
P ( c 1 | w ) < P ( c 0 | w ) ,则w样本属于 c 0 类别。
同样在多分类问题中, P ( c i | w ) 最大时表示样本 w 属于 c i 分类。其中 P ( c i | w ) 表示挑选出来的样本 w 属于 c i 的概率。

  • 通常 P ( c i | w ) 难以直接求得,可用条件概率间接求,公式如下:
    P ( c i | w ) = P ( w | c i ) P ( c i ) P ( w )
    其中 P ( w | c i ) 表示从 c i 类中取出样本 w 的概率, P ( c i ) 表示类别 c i 的概率,以上公式的由来相信学过概率论的同学应该都比较清楚这是条件概率。

  • 主要过程

    1. 计算条件概率 P ( w | c i ) P ( c i ) ,假设各特征相互独立,则 P ( w | c i ) = P ( w 0 | c i ) P ( w 1 | c i ) . . . . P ( w n | c i )
    2. 对于一个数据集,取出每一个样本概率 P ( w ) 值是一样的,因此只需要比较 P ( c i | w ) 的值,最大值条件下的 c i 即分类结果
    3. 为防止概率数值过小(接近于0)而出现下溢,因而采用 l o g P ( w | c i ) P ( c i ) 来表示概率。

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%

朴素贝叶斯分类结果

猜你喜欢

转载自blog.csdn.net/ljyhust/article/details/75269629