1. 程式人生 > >貝葉斯決策分類器 MNIST手寫數據集 分類 python實現

貝葉斯決策分類器 MNIST手寫數據集 分類 python實現

row 出了 net 訓練集 貝葉斯公式 影響 集中 oat blog

轉載: (1) https://zhuanlan.zhihu.com/p/51200626

   (2) 菊安醬的機器學習第三期

   (3) 代碼來自:https://github.com/WenDesi/lihang_book_algorithm

    (4) https://blog.csdn.net/taiji1985/article/details/73657994

貝葉斯:

  首先,貝葉斯分類算法是統計學中的一種概率分類方法,樸素貝葉斯分類是貝葉斯分類中的一種,其分類原理就是利用貝葉斯公式根據某特征的先驗概率計算出後驗概率,然後選擇最大後驗概率的類作為該特征所屬的類。

 在生活中常常用貝葉斯做決策,先看一下公式:

          技術分享圖片

  技術分享圖片

  光看公式不知道咋用,舉個例子說明一下:

  這個例子是女生根據男生的三個特征來確定是不是嫁給他。

技術分享圖片

技術分享圖片

技術分享圖片

樸素貝葉斯:

  技術分享圖片

  分子上的式子為什麽能連乘?

  概率老師不是說過只有相互獨立才能直接拆嗎?是的,樸素貝葉斯分類器對條件概率分布做出了條件獨立性的假設。為啥?因為這樣能算,就這麽簡單,如果條件都不獨立,後面咋整?(讀者:那你這不嚴謹啊)。emmm….事實上是這樣,向量的特征之間大概率是不獨立地,如果我們假設獨立了,會無法避免地拋棄一些前後連貫的信息(比方說我說“好事成_”,後面大概率就是個”雙“,這個雙明顯依賴於前面的三個字)。在建立模型時如果這些都考慮進去,會讓模型變得很復雜。後來前人說那我們試試不管它們,強行獨立。誒發現效果還不錯誒,那就這麽用吧。這就是計算機科學家和數學家的分歧所在。

  上圖中P(X=x|Y=Ck)轉換成能求的式子了以後,那麽就是比較Y為不同Ck的情況下哪個概率最大,那就表示屬於哪個類的可能性最大。所以前頭式子前頭加上一個argmax,表示求讓後式值最大的Ck。

  技術分享圖片

  然後由於下圖中圈出來這一項是在Y為不同Ck情況下的連乘,所以不管k為多少,所有Ck連乘結果肯定是一致的,在比較誰的值最大時,式子裏面的常數無法對結果的大小造成影響,可以去掉。

  技術分享圖片

  變成了這樣:

  技術分享圖片

使用樸素貝葉斯分類MNIST手寫數據集:

  在數據集中,每個圖片作為一個樣本,它的分類結果共有10類,分別為0,1,2,3,…9 。 數據集中每張圖片的的每個像素采用灰度值,我們為了方便下面處理將它變成二值圖像。即將非0的點置為1。這樣處理後,我們可以認為一個像素是否為1變成一個0-1分布。

我們計算這樣一個概率值:

   技術分享圖片

技術分享圖片

技術分享圖片 一些其他處理: (1)拉普拉斯平滑處理 (2)數據取對數log處理

技術分享圖片

代碼實現:

import pandas as pd
import numpy as np
import cv2
import random
import time

from sklearn.cross_validation import train_test_split
from sklearn.metrics import accuracy_score

# 二值化
def binaryzation(img):
    cv_img = img.astype(np.uint8)
    cv2.threshold(cv_img,50,1,cv2.THRESH_BINARY_INV,cv_img)
    return cv_img

def Train(trainset,train_labels):
    prior_probability = np.zeros(class_num)     # 預設先驗概率  p(y = j)
    conditional_probability = np.zeros((class_num,feature_len,2)) # 預設條件概率  p(xk | y) 


    # 計算先驗概率及條件概率
    for i in range(len(train_labels)):  #訓練集標簽的數量 

        img = binaryzation(trainset[i]) # 圖片二值化   對每一個圖片進行二值化
        
        label = train_labels[i]      #對每一張圖片賦予標簽

        prior_probability[label] += 1  #先驗概率,總要計算出訓練集中同一種標簽的數量,比如說是數字1的圖片有多少張

        for j in range(feature_len):#對每一張圖片的每一個像素進行操作,統計同一種標簽下的圖像中各像素取值的數量
            conditional_probability[label][j][img[j]] += 1  #屬於第i類的圖像中像素j為0和1的數量
    
    prior_probability =np.log((prior_probability + 1) / (len(trainset)))  #先驗概率平滑
    # 將概率歸到[1,10000]
    for i in range(class_num):
        for j in range(feature_len):
            
            # 經過二值化後圖像只有0,1兩種取值
            pix_0 = conditional_probability[i][j][0]# 得到屬於第i類的圖像中第j個像素像素值為0的數量 
            pix_1 = conditional_probability[i][j][1]# 得到屬於第i類的圖像中第j個像素像素值為1的數量 

            # 計算0,1像素點對應的條件概率  後驗概率平滑
            probalility_0 = (float(pix_0)+1)/(float(pix_0+pix_1)+2)*1000000 # 拉普拉斯平滑
            probalility_1 = (float(pix_1)+1)/(float(pix_0+pix_1)+2)*1000000

            conditional_probability[i][j][0] = np.log(probalility_0)  # 得到 P(Xk|y)
            conditional_probability[i][j][1] = np.log(probalility_1)

    return prior_probability,conditional_probability   

# 計算概率
def calculate_probability(img,label):
    probability = prior_probability[label]  #先驗概率  
    sum = 0
    for i in range(len(img)):      # 取log變為相加
        sum += int(conditional_probability[label][i][img[i]])    
    probability =  probability + sum
    return probability

def Predict(testset,prior_probability,conditional_probability):
    predict = []

    for img in testset:

        # 圖像二值化
        img = binaryzation(img)

        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)

class_num = 10
feature_len = 784

if __name__ == __main__:

    print(Start read data)

    time_1 = time.time()

    raw_data = pd.read_csv(mnist_train.csv,header=0)
    data = raw_data.values
    
    imgs = data[0::,1::]   #取出像素值
    labels = data[::,0]     #取出標簽值
    
    time_2 = time.time()
    print(read data cost ,time_2 - time_1, second,\n)

    print(Start training)
    prior_probability,conditional_probability = Train(imgs,labels)
    time_3 = time.time()
    print(training cost ,time_3 - time_2, second,\n)
    
    test_data = pd.read_csv(mnist_test.csv,header=0)

    test_data = test_data.values
    
    test_imgs = test_data[0::,1::]   #取出測試集像素值
    test_labels = test_data[::,0]     #取出測試集標簽值

    print(Start predicting)
    test_predict = Predict(test_imgs,prior_probability,conditional_probability)
    time_4 = time.time()
    print(predicting cost ,time_4 - time_3, second,\n)

    score = accuracy_score(test_labels,test_predict)
    print("The accruacy socre is ", score)

測試結果:

技術分享圖片

貝葉斯決策分類器 MNIST手寫數據集 分類 python實現