樸素貝葉斯的python實現(針對演算法預測類不針對文字)
首先,感謝Chai_zheng博主提供的程式碼思路,本文程式碼基於該博主思路所編寫!!!感謝這個開源的時代。
一、貝葉斯原理:
作為一名研究(雖然是菜鳥級別的,哈哈),那還是用學習貝葉斯的人員來自稱吧,還是要吹一下貝葉斯的幾大優點的。
貝葉斯網路是一種概率圖形模型,廣泛應用於各種人工智慧推理和因果建模中。在眾多的分類模型中,貝葉斯網路對處理不確定性推理有著明顯的優勢。它主要用概率刻畫因果關係,並可以處理存在噪聲資訊或者資料缺失的資料集。最重要的是貝葉斯網路是一種簡單的、可解釋分類模型,可在多場合提供決策支援。貝葉斯網路分為結構學習和引數學習兩個部分。結構學習是形成一個有向無環圖(DAG)的過程,圖中節點代表屬性,有向邊代表屬性間的條件關係或因果關係。
進入正題,在貝葉斯理論中有一個十分重要的假設就是條件獨立性假設,該假設可以描述為除了父節點外,節點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))
結果截圖: