正态贝叶斯
1.概率
1.1随机事件与概率
随机事件a是指可能发生也不可能发生的事情,它有个发生概率
ρ
(
a
)
\rho(a)
ρ(a),且该概率值将满足如下约束:
0
≤
ρ
(
a
)
≤
1
0\leq \rho(a)\leq 1
0≤ρ(a)≤1
既概率值为0~1之间,这个值越大,事件就越可能发生。如果一个随机事件发生概率为0,则成为不可能事件;如果一个随机事件发生的概率为1,则称为必然事件。
1.2条件概率
对于两个相关的随机事件a和b,在事件a发生的条件下事件b发生的概率称为条件概率
ρ
(
a
∣
b
)
\rho(a|b)
ρ(a∣b),定义为
ρ
(
b
∣
a
)
=
ρ
(
a
,
b
)
ρ
(
a
)
\rho(b|a)=\frac{\rho(a,b)}{\rho(a)}
ρ(b∣a)=ρ(a)ρ(a,b)
既a和b同时发生的概率与a发生的概率的比值。如果事件a是因,事件b是果,则概率
ρ
(
b
∣
a
)
\rho(b|a)
ρ(b∣a)称为先验概率。则后验概率定义为
ρ
(
a
∣
b
)
=
ρ
(
a
,
b
)
ρ
(
b
)
\rho(a|b)=\frac{\rho(a,b)}{\rho(b)}
ρ(a∣b)=ρ(b)ρ(a,b)
1.3贝叶斯公式
贝叶斯公式指出
ρ
(
a
)
ρ
(
b
∣
a
)
=
ρ
(
b
)
ρ
(
a
∣
b
)
\rho(a)\rho(b|a)=\rho(b)\rho(a|b)
ρ(a)ρ(b∣a)=ρ(b)ρ(a∣b)
变形为
ρ
(
a
∣
b
)
=
ρ
(
a
)
ρ
(
b
,
a
)
ρ
(
b
)
\rho(a|b)=\frac{\rho(a)\rho(b,a)}{\rho(b)}
ρ(a∣b)=ρ(b)ρ(a)ρ(b,a)
则如果有
ρ
(
a
∣
b
)
=
ρ
(
a
)
\rho(a|b)=\rho(a)
ρ(a∣b)=ρ(a)或
ρ
(
b
∣
a
)
=
ρ
(
b
)
\rho(b|a)=\rho(b)
ρ(b∣a)=ρ(b)则称随机事件a和b独立。如事件独立则有
ρ
(
a
,
b
)
=
ρ
(
a
)
ρ
(
b
)
\rho(a,b)=\rho(a)\rho(b)
ρ(a,b)=ρ(a)ρ(b)
1.4贝叶斯推广定义
如果有n个随机事件
a
i
a_{i}
ai,i=1,2,3,4,5,······,n互相独立,则它们同时发生的概率等于它们各自发生的概率乘积,则
ρ
(
a
1
,
a
2
,
⋅
⋅
⋅
,
a
n
)
=
∏
n
i
=
1
ρ
(
a
i
)
\rho(a_{1},a_{2},···,a_{n})=\prod_{n}^{i=1}\rho(a_{i})
ρ(a1,a2,⋅⋅⋅,an)=n∏i=1ρ(ai)
2.贝叶斯决策
2.1贝叶斯分类器
贝叶斯公式描述了两个相关的的随机事件或随机变量之间的概率关系。贝叶斯分类器使用贝叶斯公式计算样本属于某一类的条件概率值,并将样本判为概率值最大的那个类。
ρ
(
b
∣
a
)
\rho(b|a)
ρ(b∣a)定义为在事件a发生的前提下事件b发生的概率。贝叶斯公式说明了两个随机事件的关系
ρ
(
b
∣
a
)
=
ρ
(
b
)
ρ
(
a
∣
b
)
ρ
(
a
)
\rho(b|a)=\frac{\rho(b)\rho(a|b)}{\rho(a)}
ρ(b∣a)=ρ(a)ρ(b)ρ(a∣b)
把这个结论推广到随机的变量中。分类问题中样本特征向量取值x与样本所属类型y具有因果关系。因为样本属于类型y,所以具有特征值x。那么我们回到下面的代码问题,我们要区分男性与女性,选用的特征为身高体重。一般情况下男性比女性高并且重,因为一个人是男性才会有这种特征。分类器要做的则是反其道而行,是在已知样本的特征向量为x的条件下反推样本的所属的类别。则根据贝叶斯公式有
ρ
(
y
∣
x
)
=
ρ
(
y
)
ρ
(
x
∣
y
)
ρ
(
x
)
\rho(y|x)=\frac{\rho(y)\rho(x|y)}{\rho(x)}
ρ(y∣x)=ρ(x)ρ(y)ρ(x∣y)
只要知道特征向量的概率分布
ρ
(
x
)
\rho(x)
ρ(x),每一类出现的概率
ρ
(
y
)
\rho(y)
ρ(y),以及每一类样本的条件概率
ρ
(
x
∣
y
)
\rho(x|y)
ρ(x∣y),就可以计算出样本属于每一类的概率
ρ
(
y
∣
x
)
\rho(y|x)
ρ(y∣x)。分类问题只要预测类别,比较样本属于每一类的概率大小,找出该值最大的那一类即可。
因为实现贝叶斯分类器需要知道每类样本特征向量所服从的概率分布。而现实中很多随意变量都近似与服从正态分布,因此,使用正态分布来表示特征向量的概率分布。
2.2正态贝叶斯分类器
训练算法
ρ
(
x
∣
c
)
=
1
(
2
π
)
n
2
∣
∑
∣
1
2
)
e
(
−
1
2
(
x
−
μ
)
τ
∑
−
1
(
x
−
μ
)
)
\rho(x|c)=\frac{1}{(2\pi )^{\frac{n}{2}}\left | \sum \right |^{\frac{1}{2}})}e^{(-\frac{1}{2}(x-\mu )^{\tau }\sum ^{-1}(x-\mu ))}
ρ(x∣c)=(2π)2n∣∑∣21)1e(−21(x−μ)τ∑−1(x−μ))
- μ \mu μ为均值向量
- ∑ \sum ∑为协方差矩阵
- ∣ ∑ ∣ \left | \sum \right | ∣∑∣是协方差矩阵的行列式
- ∑ − 1 \sum ^{-1} ∑−1是协方差矩阵的逆矩阵
2.3代码所用公式
对于二维正态随机变量(X,Y),X和Y相互独立的充要条件是参数ρ=0。也即二维正态随机变量独立和不相关可以互推。
f
(
x
,
y
)
=
1
2
π
σ
1
σ
2
e
[
−
1
2
(
(
x
−
μ
1
)
2
σ
2
1
+
(
y
−
μ
2
)
2
σ
2
2
)
]
f(x,y)=\frac{1}{2\pi \sigma _{1}\sigma _{2}}e^{\left [ -\frac{1}{2}\left ( \frac{\left ( x-\mu _{1} \right )^{2}}{\sigma _{2}^{1}}+\frac{\left ( y-\mu _{2} \right )^{2}}{\sigma _{2}^{2}} \right ) \right ]}
f(x,y)=2πσ1σ21e[−21(σ21(x−μ1)2+σ22(y−μ2)2)]
- μ \mu μ为对x和y的期望 期望公式为: E ( x ) = ∑ n i = 1 x i ρ i E(x)=\sum_{n}^{i=1}x_{i}\rho _{i} E(x)=∑ni=1xiρi
- σ \sigma σ为x,y的均方差
- ρ \rho ρ为x,y的相关系数
3代码
3.1 util.h
#ifndef DICHOTOMY_UTIL_H
#define DICHOTOMY_UTIL_H
const int MAX=1000;
const double pi=3.1415926;
const double p=0.5;
#endif //DICHOTOMY_UTIL_H
3.2 people.h
#ifndef DICHOTOMY_PEOPLE_H
#define DICHOTOMY_PEOPLE_H
#include "util.h"
struct HUMAN{
double height;
double weight;
};
HUMAN man[MAX];
HUMAN woman[MAX];
#endif //DICHOTOMY_PEOPLE_H
3.3 algorithm.h
#ifndef DICHOTOMY_ALGORITHM_H
#define DICHOTOMY_ALGORITHM_H
#include "people.h"
#include<iostream>
#include <math.h>
#include <fstream>
using namespace std;
struct NORMAL{
double mu_1;
double mu_2;
double delta_1;
double delta_2;
double rho;
};
NORMAL manNormal;
NORMAL womanNormal;
ifstream input_1("man.TXT");
ifstream input_2("woman.TXT");
ifstream input_3("test.txt");
int woman_num;
int man_num;
double mu[2];
double delate[2];
/*
* 读入样本
*/
void input(){
woman_num=0;
man_num=0;
while (input_2>>woman[woman_num+1].height>>woman[woman_num+1].weight){
woman_num++;
}
while (input_1>>man[man_num+1].height>>man[man_num+1].weight){
man_num++;
}
}
/*
* 计算mu
*/
double *normalMu(struct HUMAN *people,int people_num){
double mu_1=0;
double mu_2=0;
for(int i=1;i<=people_num;i++){
mu_1+=people[i].height;
mu_2+=people[i].weight;
}
mu_2/=people_num;
mu_1/=people_num;
mu[0]=mu_1;
mu[1]=mu_2;
return mu;
}
/*
* 计算delta
*/
double *normalDelta(struct HUMAN *people,int people_num,double mu_1,double mu_2){
double delate_1=0;
double delate_2=0;
for(int i=1;i<=people_num;i++){
delate_1+=(people[i].height-mu_1)*(people[i].height-mu_1);
delate_2+=(people[i].weight-mu_2)*(people[i].weight-mu_2);
}
delate_2/=people_num;
delate_1/=people_num;
delate_1=sqrt(delate_1);
delate_2=sqrt(delate_2);
delate[0]=delate_1;
delate[1]=delate_2;
return delate;
}
/*
* 计算rho
*/
double normalRho(struct HUMAN *people,int people_num,double mu_1,double mu_2,double delate_1,double delate_2){
double rho=0;
for(int i=1;i<=people_num;i++){
rho+=people[i].height*people[i].weight;
}
rho/=people_num;
rho-=mu_2*mu_1;
rho/=delate_2*delate_1;
return rho;
}
void NormalFun(struct HUMAN *people,int people_num,struct NORMAL &peopleNormal){
double *mu;
double *delate;
double rho=0;
mu=normalMu(people,people_num);
delate=normalDelta(people,people_num,mu[0],mu[1]);
rho=normalRho(people,people_num,mu[0],mu[1],delate[0],delate[1]);
peopleNormal.mu_1=mu[0];
peopleNormal.mu_2=mu[1];
peopleNormal.delta_1=delate[0];
peopleNormal.delta_2=delate[1];
peopleNormal.rho=rho;
}
/*
* 计算条件概率
*/
double P(struct NORMAL &normal,double x1,double x2){
double result;
double mu1=normal.mu_1;
double mu2=normal.mu_2;
double delta1=normal.delta_1;
double delta2=normal.delta_2;
double rho=normal.rho;
rho=0;
result=(1/(2*pi*delta1*delta2*sqrt(1-rho*rho)))*exp(-1/(2*sqrt(1-rho*rho))*(((x1-mu1)*(x1-mu1))/(delta1*delta1)+((x2-mu2)*(x2-mu2))/(delta2*delta2)-(2*rho*(x1-mu1)*(x2-mu2))/(delta1*delta2)));
return result;
}
/*
* 计算后验概率
* judge为0为女,1为男
*/
double posteriorProbability(double x1,double x2,bool judge){
if(judge==0){
return (P(womanNormal,x1,x2)*p)/(P(womanNormal,x1,x2)*p+P(manNormal,x1,x2)*p);
}
else {
return (P(manNormal,x1,x2)*p)/(P(womanNormal,x1,x2)*p+P(manNormal,x1,x2)*p);
}
}
/*
* 判断男女,0为女,1为男
*/
bool classifyCategorize(double x1,double x2){
if(posteriorProbability(x1,x2,0)>=posteriorProbability(x1,x2,1)){
return 0;
}
else {
return 1;
}
}
void results(){
double heigth,weight;
char sex;
while (input_3>>heigth>>weight>>sex){
if(sex=='f'&&classifyCategorize(heigth,weight)==0){
cout<<"正确"<<endl;
} else if(sex=='m'&&classifyCategorize(heigth,weight)==0){
cout<<"正确"<<endl;
} else{
cout<<"错误"<<endl;
}
}
}
#endif //DICHOTOMY_ALGORITHM_H
3.4 main.cpp
#include "algorithm.h"
int main(){
input();
NormalFun(woman,woman_num,womanNormal);
NormalFun(man,man_num,manNormal);
results();
return 0;
}