機器學習之樸素貝葉斯分類器附C++程式碼
一、基本概念:
- 先驗概率(prior probability):是指根據以往經驗和分析得到的概率,如全概率公式,它往往作為"由因求果"問題中的"因"出現的概率。比如,拋一枚硬幣,正面朝上的概率P(A)=1/2,就是先驗概率。
- 聯合概率:表示兩個事件共同發生的概率。A與B的聯合概率表示為 P(AB) 或者P(A,B),或者P(A∩B)。
- 條件概率:已知事件A發生的條件下事件B發生概率,條件概率表示為P(B|A)。
- 後驗概率:例如事件B1、B2、B3等都會導致事件A發生。現在事件A已經發生,求事件A發生是由B1、B2、B3那個事件引起的條件概率P(Bi|A),就是後驗概率。舉個在《概率論》中經常用到的例子,事件B
二、貝葉斯定理:
在現實生活中,我們可以很容易直接得出P(A|Bi),而P(Bi|A)則很難直接得出,但我們更關心P(Bi|A),貝葉斯定理實現了由P(A|Bi)計算P(Bi|A)的方法。
貝葉斯公式:
貝葉斯演算法的基礎是概率推理,是在各種條件的存在不確定、僅知其出現的概率情況下,完成推理和決策任務。而樸素貝葉斯模型(Naive Bayesian Model)是基於獨立假設的,即假設樣本的每一個特徵與其他特徵都不相關。
三、貝葉斯分類器基本原理
此時貝葉斯公式寫為:
訓練:
2. 計算先驗概率P(Ci)。
3. 計算類條件密度:
測試:
2.計算
3.根據貝葉斯定理求後驗概率P(Ci|X),得到X屬於Ci類別的後驗概率;根據最大後驗概率判斷所屬類別。
P(Cα|X)=max{P(Ci|X)} ,則測試樣本屬於Cα四、舉例說明
如圖所示,為某電腦賣家統計的客戶資訊,有14個樣本(X1,X2,...X14),其中每個樣本有四個屬性,{a1(age),a2(income),a3(student),a4
(credit_rating)}。根據以上資訊,如果再給出一個客戶的這四種資訊,如{(<30),medium,no,fair},判斷他會不會買電腦。也是一個簡單的二分類問題。為了便於表示,把年齡<=30、31—40、>40用Tw(Twenty)、Th(Thirty)、F(Forty)來表示。
訓練:
2. 計算先驗概率P(C1)=5/14;P(C2)=9/14。
3. 計算類條件密度:
屬性a1:P(TwC1)=3/14;P(ThC1)=0/14;P(FC1)=2/14;P(TwC2)=2/14;P(ThC2)=4/14;P(FC2)=3/14;
P(Tw|C1)=3/5;P(Th|C1)=0/5;P(F|C1)=2/5;P(Tw|C2)=2/9;P(Th|C2)=4/9;P(F|C2)=3/9;
屬性a2:P(HC1)=2/14;P(MC1)=2/14;P(LC1)=1/14;P(HC2)=2/14;P(MC2)=4/14;P(LC2)=3/14;
P(H|C1)=2/5;P(M|C1)=2/5;P(L|C1)=1/5;P(H|C2)=2/9;P(M|C2)=4/9;P(L|C2)=3/9;
屬性a3:P(NC1)=4/14;P(YC1)=1/14;P(NC2)=3/14;P(YC2)=6/14;
P(N|C1)=4/5;P(Y|C1)=1/5;P(N|C2)=3/9;P(Y|C2)=6/9;
屬性a4:P(FC1)=2/14;P(EC1)=3/14;P(FC2)=6/14;P(EC2)=3/14;
P(F|C1)=2/5;P(E|C1)=3/5;P(F|C2)=6/9;P(E|C2)=3/9;
測試:
1.設X={(<30),medium,no,fair}為待分類項,
2.計算
P(X|C1)P(C1)=P(a1|C1)*P(a2|C1)*P(a3|C1)*P(a4|C1)P(C1)
=P(Tw|C1)*P(M|C1)*P(N|C1)*P(F|C1)*P(C1)=(3/5)*(2/5)*(4/5)*(2/5)*(5/14)= 0.0274;
P(X|C2)P(C2)=P(a1|C2)*P(a2|C2)*P(a3|C2)*P(a4|C2)P(C2)
=P(Tw|C2)*P(M|C2)*P(N|C2)*P(F|C2)*P(C2)=(2/9)*(4/9)*(3/9)*(6/9)*(9/14)= 0.0141;
3.根據貝葉斯定理求後驗概率,得到X屬於Ci類別的後驗概率;根據最大後驗概率判斷所屬類別。
P(Cα|X)=max{P(Ci|X)} ,則測試樣本屬於CαP(X|C1)P(C1)>P(X|C2)P(C2)==>P(C1|X)>P(C2|X),
所以,此人不買電腦的概率大。
五、程式
1.這裡只給出main函式部分,因為這個程式也是本人在網上下載別人的,可以驗證,程式執行結果與計算結果相同
地址:http://download.csdn.net/download/theone_jie/9464087
//樸素貝葉斯分類器程式
#include <cstdio>
#include <Windows.h>
#include "LBayesClassifier.h"
const int NUM =14; //訓練樣本個數
const int Dim =4; //訓練樣本的維數
int main()
{
/*定義樣本矩陣
每一行代表一個樣本
第一列為age,第二列為income,第3列為student,第4列為credit_rating
把個屬性進行了數字化,(<=30:20)、(31-40:30)、(>40:40);
(high:3)(medium:2)(low:1);(no:0)(yes:1);(fair:0)(excellent:1)
*/
int dataList[NUM*Dim] =
{ 20,3,0,0,
20,3,0,1,
30,3,0,0,
40,2,0,0,
40,1,1,0,
40,1,1,1,
30,1,1,1,
20,2,0,0,
20,1,1,0,
40,2,1,0,
20,2,1,1,
30,2,0,1,
30,3,1,0,
40,2,0,1};
LBayesMatrix sampleMatrix(NUM, Dim, dataList);
//定義樣本的類別向量(0:不買電腦;1:買電腦)
int classList[NUM] = {0,0,1,1,1,0,1,0,1,1,1,1,1,0};
LBayesMatrix classVector(NUM, 1, classList);
//定義貝葉斯原始問題
LBayesProblem problem(sampleMatrix, classVector, BAYES_FEATURE_CONTINUS);
//定義貝葉斯分類器, 並且訓練
LBayesClassifier classifier;
classifier.TrainModel(problem);
//輸入新樣本, 並預測新樣本的類別
LBayesMatrix newSample(1, Dim);
newSample[0][0] = 20;
newSample[0][1] = 2;
newSample[0][2] = 0;
newSample[0][3] = 0;
int predictValue ;
classifier.Predict(newSample, &predictValue);
printf("%d\n", predictValue);
system("pause");
return 0;
}
2.最後在附加了opencv自帶的正態貝葉斯分類器
//opencv自帶正態貝葉斯分類器(Normal Bayes Classifier)
#include "opencv2/ml/ml.hpp"
using namespace std;
using namespace cv;
const int NUM=14; //訓練樣本的個數
const int D=4; //維度
//14個維數為4的訓練樣本集
double inputArr[NUM][D] =
{ 20,3,0,0,
20,3,0,1,
30,3,0,0,
40,2,0,0,
40,1,1,0,
40,1,1,1,
30,1,1,1,
20,2,0,0,
20,1,1,0,
40,2,1,0,
20,2,1,1,
30,2,0,1,
30,3,1,0,
40,2,0,1};
//一個測試樣本的特徵向量
double testArr[]={20,3,0,0};
int main()
{
Mat trainData(NUM, D, CV_32FC1);//構建訓練樣本的特徵向量
for (int i=0; i<NUM; i++) {
for (int j=0; j<D; j++) {
trainData.at<float>(i, j) = inputArr[i][j+1];
}
}
Mat trainResponse=(Mat_<float>(NUM,1)<<
0,0,1,1,1,0,1,0,1,1,1,1,1,0);//構建訓練樣本的類別標籤
CvNormalBayesClassifier Mybayes;
bool trainFlag = Mybayes.train(trainData, trainResponse);//進行貝葉斯分類器訓練
if (trainFlag) {
cout<<"train over..."<<endl;
Mybayes.save("normalBayes.txt");
}
else {
cout<<"train error..."<<endl;
system("pause");
exit(-1);
}
CvNormalBayesClassifier Tbayes;
Tbayes.load("normalBayes.txt");
Mat testSample(1, D, CV_32FC1);//構建測試樣本
for (int i=0; i<D; i++) {
testSample.at<float>(0, i) = testArr[i];
}
float flag = Tbayes.predict(testSample);//進行測試
cout<<"flag = "<<flag<<endl;
system("pause");
return 0;
}
本人能力有限,難免有出錯的地方。敬請賜教更多資源:http://blog.csdn.net/lavorange/article/details/17841383