【周末AI课堂】基于贝叶斯推断的回归模型(代码篇)| 机器学习你会遇到的“坑”

AI课堂开讲,就差你了!

很多人说,看了再多的文章,可是没有人手把手地教授,还是很难真正地入门AI。为了将AI知识体系以最简单的方式呈现给你,从这个星期开始,芯君邀请AI专业人士开设“周末学习课堂”——每周就AI学习中的一个重点问题进行深度分析,课程会分为理论篇和代码篇,理论与实操,一个都不能少!

来,退出让你废寝忘食的游戏页面,取消只有胡吃海塞的周末聚会吧。未来你与同龄人的差异,也许就从每周末的这堂AI课开启了!

【周末AI课堂】基于贝叶斯推断的回归模型(代码篇)| 机器学习你会遇到的“坑”

在昨天的课程中,我们提到属性的取值一旦由离散变得连续,就不能用频率来估计概率。但是我们可以用一个概率密度函数来指定属性的类条件概率的估计,比如令条件概率为一个高斯分布:

【周末AI课堂】基于贝叶斯推断的回归模型(代码篇)| 机器学习你会遇到的“坑”

高斯分布由两个参数(均值和标准差)唯一确定,我们唯一需要做的只是对高斯分布的参数进行估计,参数一旦估计完成,我们的学习过程也就结束了,将新的样本添加进去,对参数进行更新即可。

为方便大家与前面的进行对比,我们采用与《核技巧(代码篇)》一样的数据:

from sklearn import datasets
import matplotlib.pyplot as plt
import seaborn as sns

X,y=datasets.make_moons(200,noise=.2,random_state=0)

sns.set(style='darkgrid')
for i,v,l in [[0,'r','class_0'],[1,'b','class_1']]:
  plt.scatter(X[y==i][:,0],X[y==i][:,1],c=v,label=l)
plt.legend()
plt.show()

【周末AI课堂】基于贝叶斯推断的回归模型(代码篇)| 机器学习你会遇到的“坑”
对于这种属性连续但目标离散的数据,我们可以很方便的用sklearn的naive_bayes构建分类器并使用它来适应数据:

from sklearn import datasets
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.naive_bayes import GaussianNB
import numpy as np

def make_meshgrid(x, y, h=.02):
    x_min, x_max = x.min() - 1, x.max() + 1
    y_min, y_max = y.min() - 1, y.max() + 1
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
                         np.arange(y_min, y_max, h))
    return(xx, yy)

X,y=datasets.make_moons(200,noise=.4,random_state=0)

xx,yy=make_meshgrid(X[:,0],X[:,1])
gnb=GaussianNB()
gnb.fit(X,y)
Z=gnb.predict_proba(np.c_[xx.ravel(),yy.ravel()])[:,1]
Z=Z.reshape(xx.shape)

sns.set(style='white')
plt.contourf(xx,yy,Z,cmap=plt.cm.RdBu,alpha=.8)
for i,v,l in [[0,'r','class_0'],[1,'b','class_1']]:
 plt.scatter(X[y==i][:,0],X[y==i][:,1],c=v,label=l,edgecolors='k')
plt.legend()
plt.show()

【周末AI课堂】基于贝叶斯推断的回归模型(代码篇)| 机器学习你会遇到的“坑”
如图,红蓝色逐渐变浅的分界线就是我们的决策边界,而且颜色越深,代表着离决策边界越远,说明了属于某一类的概率也就越大。

我们在上一节所提到,根据贝叶斯定理,我们的相对后验概率不仅取决于似然,还取决于先验,我们最终得到的概率会有着先验偏好的影响。在这里,我们调节高斯朴素贝叶斯类器的先验,就可以看到先验分布的影响:

......
piror=zip([0.01,0.2,0.8,0.99],[0.99,0.8,0.2,0.01])
sns.set(style='darkgrid')
for i,p in enumerate(piror):
    gnb=GaussianNB(p)# 先验概率
    gnb.fit(X,y)
    Z=gnb.predict_proba(np.c_[xx.ravel(),yy.ravel()])[:,1]
    Z=Z.reshape(xx.shape)

   plt.subplot(2,2,i+1)
   plt.contourf(xx,yy,Z,cmap=plt.cm.RdBu,alpha=.8)
   for i,v,l in [[0,'r','class_0'],[1,'b','class_1']]:
       plt.scatter(X[y==i][:,0],X[y==i][:,1],c=v,label=l,edgecolors='k')
   plt.title('piror of red point:%s' %p[0])

plt.legend()
plt.show()

【周末AI课堂】基于贝叶斯推断的回归模型(代码篇)| 机器学习你会遇到的“坑”
从图中可以看出,随着红色数据点的先验概率的增大,决策边界往蓝色数据点处移动,意味着我们的分类器对于红色点赋予更大的后验概率。

除了假设似然是高斯分布,我们还可以假设多项分布,伯努利分布,拉普拉斯分布等不同的分布形式,最终得到的决策边界也会不同。在面对具体的问题时,我们可以根据自己的经验或者领域知识来选取合适的先验和似然函数,从而更有针对性的处理问题。

接下来讨论一种更为复杂的情形,即特征值连续而且目标值也连续,即普遍的回归的问题。在上一篇《基于贝叶斯推断的回归模型》中提到了贝叶斯线性估计,它的基本思想是通过增量学习,将上一个数据点的后验概率作为下一次的先验概率,并使用全部的数据点通过极大后验估计来估计参数值。在《特征选择代码篇》中,我们曾经意外发现了一个比较完美的回归数据,是S1血清和S2血清的关系图,我们用线性回归的办法可以处理为:
【周末AI课堂】基于贝叶斯推断的回归模型(代码篇)| 机器学习你会遇到的“坑”
得到一条直线【周末AI课堂】基于贝叶斯推断的回归模型(代码篇)| 机器学习你会遇到的“坑”,如果我们利用贝叶斯估计的方法,很大程度上会得到一条类似的曲线(可能只是参数空间的微小变化),但正因为如此,我们需要对贝叶斯估计的过程做进一步的程序上的分析。将每个数据点依次添加,在参数空间上观察后验概率(后一次估计的先验概率)和似然函数,并且随着数据点的增加,对直线参数的约束也就越来越强,我们还可以在样本空间上直观的看到这种约束作用。

没有数据进入时,我们默认数据的先验为一个标准的高斯分布,而参数是从这个高斯分布上随机取到的点:

from matplotlib import pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import seaborn as sns
mean=0
sigma=1
x=np.linspace(-1,1,100)
y=np.linspace(-1,1,100)
X,Y=np.meshgrid(x,y)
z = np.exp(-((X-mean)**2 + (Y- mean)**2)/(2*(sigma**2)))
z = z/(np.sqrt(2*np.pi)*sigma)

plt.figure()
plt.contourf(Y,X,z,100,alpha=1,cmap=plt.cm.RdBu)
plt.xlabel('$\omega_0$')
plt.ylabel('$\omega_1$')
plt.title('Piror')
plt.show() 

【周末AI课堂】基于贝叶斯推断的回归模型(代码篇)| 机器学习你会遇到的“坑”
这是先验分布的contour

接着从高斯分布中随机采样得到一系列参数,然后将参数代入直线中,得到样本空间:

......
np.random.seed(42)

plt.figure()
a=np.linspace(-0.1,0.2,100)
for i,v in np.random.normal(loc=0.0,scale=1.0,size=(10,2)):
     omega1,omega2=i,v
     plt.plot(a,omega1+omega2*a)
plt.title('Data Space')
plt.xlabel('S1')
plt.ylabel('S2')
plt.show()

【周末AI课堂】基于贝叶斯推断的回归模型(代码篇)| 机器学习你会遇到的“坑”
参数是从先验分布上随机取得,然后根据参数和我们的线性模型【周末AI课堂】基于贝叶斯推断的回归模型(代码篇)| 机器学习你会遇到的“坑”,在样本空间上直接可以看到,没有添加任何数据的时候,模型并没有得到约束。

考虑到我们的样本有442个,为了更直观的表示数据对参数的约束作用,我们一次性添加50个点,来得到后验分布,写出这样的代码并不难,只需要利用我们在理论篇讲过的极大后验估计的方法:

import matplotlib.pyplot as plt
import numpy as np
from sklearn import datasets

Data=datasets.load_diabetes()
x=Data['data'][:,4][100:150]
y=Data['data'][:,5][100:150]

def fun(x,omega):
    return(omega[1]+omega[0]*x)

def posterior(omega,x,y):
   post=lnlike(omega,x,y)+5*(omega[0]*omega[0]+omega[1]*omega[1])#取了对数,后验就等于先验和似然的和
    return(post)

def lnlike(omega,x,y):
    hood=0
    for i in range(x.shape[0]):
    hood+=0.5*np.dot((y[i]-fun(x[i],omega)),(y[i]-fun(x[i],omega)))
    return(hood)

a=np.linspace(-1,1,100)
b=np.linspace(-1,1,100)

A,B=np.meshgrid(a,b)

plt.figure()
plt.contourf(A,B,posterior([A,B],x,y),100,alpha=1,cmap=plt.cm.RdBu)
plt.title('Posterior')
plt.xlabel('$\omega_0$')
plt.ylabel('$\omega_1$')
plt.show()

【周末AI课堂】基于贝叶斯推断的回归模型(代码篇)| 机器学习你会遇到的“坑”
可以看到,因为数据的约束,参数的contour向上方移动,【周末AI课堂】基于贝叶斯推断的回归模型(代码篇)| 机器学习你会遇到的“坑”更偏向于0,【周末AI课堂】基于贝叶斯推断的回归模型(代码篇)| 机器学习你会遇到的“坑”更偏向于1,我们可以简单的在附近对参数进行采样,观察样本空间的变化:

plt.figure()
plt.plot(x,y,'k.')
for i,v in zip(np.random.uniform(0.8,1.2,10),np.random.uniform(-0.025,0.025,10)):
omega2,omega1=i,v
plt.plot(a,omega1+omega2*a)
plt.title('Data Space')
plt.xlabel('S1')
plt.ylabel('S2')
plt.show()

【周末AI课堂】基于贝叶斯推断的回归模型(代码篇)| 机器学习你会遇到的“坑”
可以看到,添加数据对后验分布的影响直接体现在了样本空间上,原本随机的直线开始集中在样本周围。如果我们继续添加样本,直线也会变的越来越集中,而对应着的参数空间也会变得越来越小。

这个数据的回归趋势过于完美,可以预想到继续添加数据,参数空间变小的速度会越来越慢,一方面,这是数据量增加的必然结果,但更重要的是,我们要知道,对于太过完美的数据,添加的数据所影响的后验分布仍然与前面的数据保持一致,想象一个极端的例子,两点就可以确定一条直线,而后续的点会全部落在这条直线上,而参数并没有变化。

但绝对不缩小到一个点,因为贝叶斯估计的性质决定了我们得到的参数只能是一个分布,而不是一个点。虽然可以将参数优化到一个点,但这样做存在一定的风险,因为不同的数据得到的最佳参数值并不会一样,更加合理的的方式是为参数估计出一个置信区间(其实,置信区间就对应着参数空间的contour)。

如果模型携带参数,那么势必要对模型进行的参数进行估计。在整个机器学习中存不存在非参数的模型呢?我们下一节会介绍非参模型的表示,评估和优化。

【周末AI课堂】基于贝叶斯推断的回归模型(代码篇)| 机器学习你会遇到的“坑”

读芯君开扒

课堂TIPS

• 需要注意的是,对连续属性值所作的假设分布,仍然包含在朴素贝叶斯的框架之内,因为朴素贝叶斯假设了属性之间互相独立,而处理连续属性值的方式是对每一个属性都需要做出假设分布,最后的后验概率仍然是各属性分布的连乘。

• 除了一些特殊情况,比如二值化的数据,我们会用伯努利分布来尝试。大多数情况下,我们会使用高斯分布,一方面由于中心极限定理的存在,没有经验的情形下,高斯分布可能更为合理,另一方面则是因为高斯分布用的性质在数学上有着很多便利。

• 使用贝叶斯估计来处理回归问题时,需要处理一系列的超参数(初始先验分布的参数,批量的大小,以及最终写入优化目标的正则化项的系数),这些超参数的调节当然通过网格搜索或者随即搜索来尝试,但更重要的是,深刻理解贝叶斯估计的整个过程,就算你在调参的时候,也会比别人调的更快。比如,当你代入数据点估计后验的时候,如果后验分布变化并不明显,应该尝试更大的批量或者进行更多次的迭代,如果每次带入数据,后验分布就会发生巨变,你或许应该检查自己的数据是否存在异常。

【周末AI课堂】基于贝叶斯推断的回归模型(代码篇)| 机器学习你会遇到的“坑”

留言 点赞 发个朋友圈

我们一起探讨AI落地的最后一公里

作者:唐僧不用海飞丝

如需转载,请后台留言,遵守转载规范

推荐文章阅读

【周末AI课堂 | 第十三讲】基于贝叶斯推断的回归模型(理论篇)
【周末AI课堂 | 第十二讲】基于贝叶斯推断的分类模型(代码篇)
【周末AI课堂 | 第十一讲】基于贝叶斯推断的分类模型(理论篇)
【周末AI课堂 | 第十讲】核技巧(代码篇)
【周末AI课堂 | 第九讲】核技巧(理论篇)
【周末AI课堂 | 第八讲】非线性降维方法(代码篇)
【周末AI课堂 | 第七讲】非线性降维方法(理论篇)
【周末AI课堂 | 第六讲】线性降维方法(代码篇)
【周末AI课堂 | 第五讲】线性降维方法(理论篇)
【周末AI课堂 | 第四讲】如何进行特征选择(代码篇)
【周末AI课堂 | 第三讲】如何进行特征选择(理论篇)
【周末AI课堂 | 第二讲】过拟合问题(代码篇)
【周末AI课堂 | 第一讲】过拟合问题(理论篇)

长按识别二维码可添加关注

读芯君爱你

【周末AI课堂】基于贝叶斯推断的回归模型(代码篇)| 机器学习你会遇到的“坑”

上一篇:【视觉SLAM十四讲-个人笔记】初识SLAM


下一篇:【Latex】Algorithm排版