高斯判别算法是一个典型的生成学习算法(关于生成学习算法可以参考我的另外一篇博客)。在这个算法中,我们假设 p(x|y) 服从多元正态分布。
注:在判别学习算法中,我们假设 p(y|x) 服从一维正态分布,这个很好类比,因为在模型中输入数据 X 通常是拥有很多维度的,所以对于 X 的条件概率建模时要取多维正态分布。
多元正态分布也叫多元高斯分布,这个分布的两个参数分别是平均向量 μ∈ℝn 和一个协方差矩阵 ∑∈ℝn×n
关于协方差矩阵的定义;假设 X 是由 n 个标量随机变量组成的列向量,并且 μk 是第 k 个元素的期望值,即 μk=E(Xk) ,那么协方差矩阵被定义为
矩阵第 (i,j) 个元素表示 Xi 与 Xj 的协方差。协方差矩阵是对称而且是半正定的。
多元高斯分布可以记为 N(u⃗ ,∑) ,其概率密度的具体表达式为(比较复杂,但知道形式就好,具体推导中用处较少)
在上面的公式中, |Σ| 表示的是协方差矩阵的行列式,对一个随机变量 X 服从 N(u⃗ ,Σ) ,它的数学期望是:
下面是一些二维高斯分布的概率密度图像:
最右边的图像展现的二维高斯分布的均值是零向量(2x1的零向量),协方差矩阵 Σ=I (2x2的单位矩阵),像这样以零向量为均值以单位阵为协方差的多维高斯分布称为标准正态分布,中间的图像以零向量为均值, Σ=0.6I ;最右边的图像中 Σ=2I ,观察发现当 Σ 越大时,高斯分布越“铺开”,当 Σ 越小时,高斯分布越“收缩”。
让我们看一些其他例子对比发现规律
上图中展示的三个高斯分布对应的均值均为零向量,协方差矩阵分别对应与下面三个
再看最后一组通过改变不同的 Σ 得到的例子
上面三幅图对应的 Σ 分别是
在最后的例子中,我们固定 Σ=I ,变动 μ ,从而可以移动概率密度图像的均值。
上图中对应的 μ 分别是
当我们处理输入特征是连续随机变量 x 时的分类问题时,我们可以使用高斯判别分析模型(GDA),用多元正态分布模型来描述 p(x|y) ,模型的具体数学表达式是这样的:
y∼Bernoulli(ϕ)
x|y=0∼N(μ0,Σ)
x|y=1∼N(μ1,Σ)
写出他们的概率分布为:
p(y)=ϕy(1−ϕ)1−y
p(x|y=0)=1(2π)n/2|Σ|12exp(−12(x−μ0)TΣ−1(x−μ0))
p(x|y=1)=1(2π)n/2|Σ|12exp(−12(x−μ1)TΣ−1(x−μ1))
现在我们的模型有四个参数 ϕ,Σ,μ0,μ1 (两个不同的均值向量分别对应与 y=0 和 y=1 两种情况,但是通常使用同一个协方差矩阵 Σ ),下面极大似然函数来估计四个参数。
通过最大化似然函数 l 可以得到上面四个参数的估计值:
ϕ=1m∑i=1m1{y(i)=1}
μ0=∑mi=11{y(i)=0}xi∑mi=11{y(i)=0}
μ1=∑mi=11{y(i)=1}xi∑mi=11{y(i)=1}
Σ=1m∑i=1m(x(i)−μy(i))(x(i)−μy(i))T
在图像中展示的是我们的训练数据集,并且在图上画出了两类分类数据的拟合出得高斯分布的等高线,两个等高线的轮廓和旋转方向相同,因为两个高斯分布的协方差矩阵 Σ 相同,但是他们的均值 μ0 和 μ1 不同,图中的直线是决策边界,落在这条直线上得点满足 p(y=1|x)=0.5 ,如果点落在直线上侧,我们预测 y=1 ,落在直线下侧,预测 y=0 。
python的实现demo 如下:
第57的高斯概率密度函数用矩阵运算写有bug没跑通,又因为实验数据只有二维,于是在纸上对上文中矩阵运算公式进行了化简至最后结果写在了函数里。如有疑问可以拿出笔来演算一下。
#GDA
#author:Xiaolewen
import matplotlib.pyplot as plt
from numpy import *
#Randomly generate two cluster data of Gaussian distributions
mean0=[2,3]
cov=mat([[1,0],[0,2]])
x0=random.multivariate_normal(mean0,cov,500).T #The first class point which labael equal 0
y0=zeros(shape(x0)[1])
#print x0,y0
mean1=[7,8]
cov=mat([[1,0],[0,2]])
x1=random.multivariate_normal(mean1,cov,300).T
y1=ones(shape(x1)[1]) #The second class point which label equals 1
#print x1,y1
x=array([concatenate((x0[0],x1[0])),concatenate((x0[1],x1[1]))])
y=array([concatenate((y0,y1))])
m=shape(x)[1]
#print x,y,m
#Caculate the parameters:\phi,\u0,\u1,\Sigma
phi=(1.0/m)*len(y1)
#print phi
u0=mean(x0,axis=1)
#print u0
u1=mean(x1,axis=1)
#print u1
xplot0=x0;xplot1=x1 #save the original data to plot
x0=x0.T;x1=x1.T;x=x.T
#print x0,x1,x
x0_sub_u0=x0-u0
x1_sub_u1=x1-u1
#print x0_sub_u0
#print x1_sub_u1
x_sub_u=concatenate([x0_sub_u0,x1_sub_u1])
#print x_sub_u
x_sub_u=mat(x_sub_u)
#print x_sub_u
sigma=(1.0/m)*(x_sub_u.T*x_sub_u)
#print sigma
#plot the discriminate boundary ,use the u0_u1's midnormal
midPoint=[(u0[0]+u1[0])/2.0,(u0[1]+u1[1])/2.0]
#print midPoint
k=(u1[1]-u0[1])/(u1[0]-u0[0])
#print k
x=range(-2,11)
y=[(-1.0/k)*(i-midPoint[0])+midPoint[1] for i in x]
#plot contour for two gaussian distributions
def gaussian_2d(x, y, x0, y0, sigmaMatrix):
return exp(-0.5*((x-x0)**2+0.5*(y-y0)**2))
delta = 0.025
xgrid0=arange(-2, 6, delta)
ygrid0=arange(-2, 6, delta)
xgrid1=arange(3,11,delta)
ygrid1=arange(3,11,delta)
X0,Y0=meshgrid(xgrid0, ygrid0) #generate the grid
X1,Y1=meshgrid(xgrid1,ygrid1)
Z0=gaussian_2d(X0,Y0,2,3,cov)
Z1=gaussian_2d(X1,Y1,7,8,cov)
#plot the figure and add comments
plt.figure(1)
plt.clf()
plt.plot(xplot0[0],xplot0[1],'ko')
plt.plot(xplot1[0],xplot1[1],'gs')
plt.plot(u0[0],u0[1],'rx',markersize=20)
plt.plot(u1[0],u1[1],'y*',markersize=20)
plt.plot(x,y)
CS0=plt.contour(X0, Y0, Z0)
plt.clabel(CS0, inline=1, fontsize=10)
CS1=plt.contour(X1,Y1,Z1)
plt.clabel(CS1, inline=1, fontsize=10)
plt.title("Gaussian discriminat analysis")
plt.xlabel('Feature Dimension (0)')
plt.ylabel('Feature Dimension (1)')
plt.show(1)
这是最终的拟合结果:
欢迎交流