1. 程式人生 > >OpenCV實現樸素貝葉斯分類器診斷病情

OpenCV實現樸素貝葉斯分類器診斷病情

貝葉斯定理由英國數學家托馬斯.貝葉斯(Thomas Baves)在1763提出,因此得名貝葉斯定理。貝葉斯定理也稱貝葉斯推理,是關於隨機事件的條件概率的一則定理。

對於兩個事件A和B,事件A發生則B也發生的概率記為P(B|A),事件B發生則A也發生的概率記為P(A|B),這樣如果A發生B也必然發生或者B發生A也必然發生,則有P(B|A)=P(A|B)=1,這種情況是一種確定性推理。

更多的情況下,概率推理是不確定性推理,AB之間是一種不確定性概率關係,例如條件A發生時B會發生的概率計算公式為:

這種情況在現實中一般是容易推導計算出來的,或者根據先驗知識是可以獲取到的,例如如下兩種情況:

1.條件A:一個人感冒了;條件B:這個人會發燒

2.條件A:一個人是女生;條件B:這個人會留長髮

根據先驗知識,條件B發生的概率是可以根據條件A推理得出的。在另一種更普遍的情況下,我們更加關心的是如果條件B發生,那麼條件A發生的概率是多少?

1.條件B:一個人發燒了;條件A:這個人感冒了

2.條件B:一個人留長髮;條件A:這個人是女生

這個問題稱為“逆概率推理”,即已知A發生時B發生的概率,那麼如果B已經發生,A發生的概率P(A|B)=?

貝葉斯公式

設有一個樣本空間S,劃分為B1,B2,....Bc一共c 類,或者成為c個事件,A為引發S中各個事件發生的事件,貝葉斯公式定義為:


其中P(Bi|A)稱為後驗概率,表示時間A發生後,各不相容的條件Bi發生的概率,它是在A的結果出現之後才能計算的,所以稱為後驗概率。

P(A|Bj)稱為類條件概率,表示在各條件Bi存在時,事件A發生的概率。

P(Bj)稱為先驗概率,表示各不相容的條件Bi出現的概率,它與結果A是否出現無關,僅表示根據先驗知識或者主觀推斷,認為總體上各個條件出現的可能性之間的差別。

貝葉斯是一位牧師,據不可靠訊息,貝葉斯提出貝葉斯公式的目的是為了從統計理論上證明上帝的存在,嘗試以一個科學的東西證明一個非科學的東西的科學性,這不科學。

樸素貝葉斯分類器(Naive Baves classifier)的“樸素”(Naive)之處在於,其假設了各個特徵之間是獨立的,簡化了貝葉斯各個特徵之間的相互關聯,更易於推廣應用。

以下程式碼是使用Opencv中正態貝葉斯Normal BavesClassifier 類建立的一個簡單的病情診斷功能。假定以下是根據警院歷來可靠資料獲取的體溫、咳嗽、流涕三個症狀的嚴重程度判定的三類病情,分別是冷感冒、肺炎、熱感冒。樸素貝葉斯根據這10組資料進行訓練,然後輸入一位病人的資料,自動進行診斷,以下是訓練資料:


Opencv程式碼實現:

#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/ml/ml.hpp"

#include <iostream>
using namespace cv;
using namespace std;

int main( int argc, char** argv )
{   
	float trainingData[10][3] = { {34, 1, 1}, {35, 2, 2}, {36, 3,3},{37,8,4},{38,9,5},
	{39,10,6},{40,7,7},{41,4,8},{42,5,9},{43,6,10}};
	Mat trainingDataMat(10, 3, CV_32FC1, trainingData); 

	float responses[10] = {1,1,1,2,2,2,3,3,3};
	Mat responsesMat(10, 1, CV_32FC1, responses);

	NormalBayesClassifier nbc;
	nbc.train(trainingDataMat, responsesMat); 

	float myData[3] = {40, 8, 10}; //病人發燒、咳嗽、流涕資料
	Mat myDataMat(1, 3, CV_32FC1, myData);
	float r = nbc.predict( myDataMat );
	int result=r;
	string output;
	switch(result)
	{
	case 1:
		output="冷感冒";
		break;
	case 2:
		output="肺炎";
		break;
	case 3:
		output="熱感冒";
		break;
	default:
		output="健康";
		break;
	}
	cout<<endl<<"該病人診斷為:  "<<output<<endl<<endl;
	system("pause");
	return 0;

}
輸入病人的資料為:發燒-40、咳嗽-8、流涕-10,診斷結果為: