1. 程式人生 > >機器學習之樸素貝葉斯分類器附C++程式碼

機器學習之樸素貝葉斯分類器附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
    1、B2、B3代表三個不同的工廠生產零件,事件A是生產次品的事件,P(A|Bi)是三個工廠的次品率。現在事件A發生了,判斷是由那個工廠生產的這個次品P(Bi|A)

二、貝葉斯定理:

在現實生活中,我們可以很容易直接得出P(A|Bi),而P(Bi|A)則很難直接得出,但我們更關心P(Bi|A),貝葉斯定理實現了由P(A|Bi)計算P(Bi|A)的方法。

貝葉斯公式: 

          

貝葉斯演算法的基礎是概率推理,是在各種條件的存在不確定、僅知其出現的概率情況下,完成推理和決策任務。而樸素貝葉斯模型(Naive Bayesian Model)是基於獨立假設的,即假設樣本的每一個特徵與其他特徵都不相關。

三、貝葉斯分類器基本原理

此時貝葉斯公式寫為:


訓練:

1.  設樣本集 ,其中。所有類別集合

2.  計算先驗概率P(Ci)。

3.  計算類條件密度:

    

測試:

1.設為待分類項,而每個ai為X的一個特徵屬性

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)來表示。


訓練:

1. 設樣本集 ,其中。所有類別集合

    

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