1. 程式人生 > >樸素貝葉斯的python實現(針對演算法預測類不針對文字)

樸素貝葉斯的python實現(針對演算法預測類不針對文字)

首先,感謝Chai_zheng博主提供的程式碼思路,本文程式碼基於該博主思路所編寫!!!感謝這個開源的時代。

一、貝葉斯原理:

作為一名研究(雖然是菜鳥級別的,哈哈),那還是用學習貝葉斯的人員來自稱吧,還是要吹一下貝葉斯的幾大優點的。

貝葉斯網路是一種概率圖形模型,廣泛應用於各種人工智慧推理和因果建模中。在眾多的分類模型中,貝葉斯網路對處理不確定性推理有著明顯的優勢。它主要用概率刻畫因果關係,並可以處理存在噪聲資訊或者資料缺失的資料集。最重要的是貝葉斯網路是一種簡單的、可解釋分類模型,可在多場合提供決策支援。貝葉斯網路分為結構學習和引數學習兩個部分。結構學習是形成一個有向無環圖(DAG)的過程,圖中節點代表屬性,有向邊代表屬性間的條件關係或因果關係。

引數學習以條件概率分佈刻畫屬性對其父節點的依賴關係,通過樣本的頻率表示概率並填充條件概率表。1988Pearl提出貝葉斯網路後,經過近三十年的發展形成了很多新演算法,具有代表性的有樸素貝葉斯(Naive Bayes,NB)、樹增廣樸素貝葉斯模型(Tree-Augmented Naive Bayes,TAN)和K階貝葉斯分類模型(k-dependence Bayesian Cla-ssifier,KDB)【後面的演算法打算自己慢慢的用python實現,敬請期待】

進入正題,在貝葉斯理論中有一個十分重要的假設就是條件獨立性假設,該假設可以描述為除了父節點外,節點Xi與其他節點無依賴關係(即相互獨立),這一點是貝葉斯研究成立的樹根,為了便於理解畫個草圖(如圖1)。X5只與Y有關,X3只與X5和Y有關,與X3相互獨立,但對於樸素貝葉斯來說非類節點之間相互獨立(即沒有弧)。


圖1

貝葉斯網路能處理離散資料和連續資料,不同的平臺處理這兩種資料利用的原理大致相同,利用條件獨立性假設,離散資料的條件概率計算公式如下:

P(Xi|Y)=P(Y)∏P(Xi|Y)

對於任意給定的隨機樣本集x =(x1 ,x2 ,··· ,xn ),其對應的聯合概率分佈表示如下:

P(c,x)
= P(c)P(x1|c)P(x2 |c)···P(xn |c)
= P(c)∏P(x i |c) (i=1...N)

其中P(c)為類先驗概率.

對於連續資料用概率密度函式來計算P(Xi|C),其中μ,σ分別代表資料的均值和標準差


二、建模的基本思路

1、計算先驗概率,離散的就計算條件概率,連續的就計算概率密度

2、根據訓練集訓練模型(樸素貝葉斯就是得到先驗概率Pc,均值,標準差)

3、根據測試集測試模型,和真實標籤值進行比較,預測對了就累加matchCount

4、matchCount/測試集總資料= 準確率

三,python程式碼如下

(程式碼最後自己敲一下沒這樣才有意義,有些地方不懂的自己打印出來看看,理解了才是重點)

好看的程式碼千篇一律,各自的理解萬里無一。(源自:好看皮囊千篇一律,有趣的靈魂萬里無一,^_^)

採用葡萄酒(wine.txt)資料集進行測試,取測試集佔比0.4,在72個測試樣本上正確率為95%-100%(抽取樣本的隨機性導致結果不同),足見其實用性的是下載地址連結: https://pan.baidu.com/s/1i4E78VF 密碼: 5u8x   別人可能需要積分,這個不需要積分,百度分享,本就是uci上捐贈的資料集,【如有侵權請及時私信】

# coding=utf-8
import math
import time
import numpy as np
from collections import Counter
from sklearn import preprocessing
from sklearn.model_selection import train_test_split


def calcProbDensity(meanLabel, stdLabel, test_X):
    numAttributes = len(test_X)
    MultiProbDensity = 1.0
print "this is calcPD"
# print meanLabel
    # print stdLabel
for i in range(numAttributes):
        MultiProbDensity *= np.exp(-np.square(test_X[i] - meanLabel[i]) / (2.0 * np.square(stdLabel[i]))) / (
            np.sqrt(2.0 * math.pi) * stdLabel[i])
    print MultiProbDensity
    return MultiProbDensity


def calcPriorProb(Y_train):  # 計算先驗概率P(c)
i, j = 0, 0
global labelValue, classNum
    numSamples = Y_train.shape[0]  # 讀取Y_train的第一維度的長度,比如多少行。
labelValue = np.zeros((numSamples, 1))  # 用前i行來儲存標籤值
    # print "laV:",labelValue
Y_train_counter = sum(Y_train.tolist(), [])  # 將Y_train轉化為可雜湊的資料結構
cnt = Counter(Y_train_counter)  # 計算標籤值的類別個數{1,2,3}及各類樣例的個數
    # print "cnt",cnt
for key in cnt:
        labelValue[i] = key
        i += 1
classNum = i
    # print "laV2:",labelValue
    # print classNum
Pc = np.zeros((classNum, 1))  # 不同類的先驗概率
eachLabelNum = np.zeros((classNum, 1))  # 每類樣例數,多少行多少列,這裡是classNum行1列
for key in cnt:
        Pc[j] = float(cnt[key]) / numSamples #這裡加float是為了避免/整除號使Pc=0
eachLabelNum[j] = cnt[key]
        j += 1
return labelValue, eachLabelNum, classNum, Pc


def trainBayes(X_train, Y_train):
    startTime = time.time()
    numTrainSamples, numAttributes = X_train.shape
    print "trainBayes"
# print numAttributes,numTrainSamples
labelValue, eachLabelNum, classNum, Pc = calcPriorProb(Y_train)
    meanlabelX, stdlabelX = [], []  # 存放每一類樣本在所有屬性上取值的均值和方差
for i in range(classNum):
        k = 0
labelXMaxtrix = np.zeros((int(eachLabelNum[i]), numAttributes))
        for j in range(numTrainSamples):
            if Y_train[j] == labelValue[i]:
                labelXMaxtrix[k] = X_train[j, :]
                k += 1
meanlabelX.append(np.mean(labelXMaxtrix, axis=0).tolist())  # 求該矩陣的列均值與無偏標準差,append至所有類
stdlabelX.append(np.std(labelXMaxtrix, ddof=1, axis=0).tolist())
    meanlabelX = np.array(meanlabelX).reshape(classNum, numAttributes)
    stdlabelX = np.array(stdlabelX).reshape(classNum, numAttributes)
    # print meanlabelX
    # print "###"
    # print stdlabelX
print('---Train completed.Took %f s.' % ((time.time() - startTime)))
    return meanlabelX, stdlabelX, Pc


def predict(X_test, Y_test, meanlabelX, stdlabelX, Pc):
    numTestSamples = X_test.shape[0]
    matchCount = 0
for m in range(X_test.shape[0]):
        x_test = X_test[m, :]  # 輪流取測試樣本
pred = np.zeros((classNum, 1))  # 對不同類的概率
print "Pc:", Pc
        for i in range(classNum):
            pred[i] = calcProbDensity(meanlabelX[i, :], stdlabelX[i, :], x_test) * Pc[i]  # 計算屬於各類的概率
            # print i
print pred
        predict1 = labelValue[np.argmax(pred)]  # 取最大的類標籤,np.argmax(pred)返回最大資料所在的index
print predict1, "####", Y_test[m]
        if predict1 == Y_test[m]:
            matchCount += 1
print "matchCount", matchCount, numTestSamples
    accuracy = float(matchCount) / numTestSamples #這裡加float是為了避免/整除號使accuracy=0
    # print accuracy
return accuracy


if __name__ == '__main__':
    print('Step 1.Loading data...')
    # 資料集下載http://download.csdn.net/download/chai_zheng/10009919
data = np.loadtxt("data/wine.txt", delimiter=',')  # 載入葡萄酒資料集
print('---Loading completed.')
    x = data[:, 1:14]
    y = data[:, 0].reshape(178, 1)
    # print x
    # print "!!!!"
    # print y
print('Step 2.Splitting and preprocessing data...')
    X_train, X_test, Y_train, Y_test = train_test_split(x, y, test_size=0.4)  # 拆分資料集
scaler = preprocessing.StandardScaler().fit(X_train)  # 資料標準化
X_train = scaler.transform(X_train)
    X_test = scaler.transform(X_test)
    print('---Splittinging completed.\n---Number of training samples:%d\n---Number of testing samples:%d' \
          % (X_train.shape[0], X_test.shape[0]))
    print('Step 3.Training...')
    meanlabelX, stdlabelX, Pc = trainBayes(X_train, Y_train)
    print('Step 4.Testing...')
    accuracy = predict(X_test, Y_test, meanlabelX, stdlabelX, Pc)
    print('---Testing completed.Accuracy:%.3f%%' % (accuracy * 100))

結果截圖: