特此声明:本博文为我的另一片博文 PyMC3 概率编程入门 的从博文,之前属于其中的一部分内容,但是因为该篇主博文内容较多,整体比较繁杂,阅读体验感较差,并且今后对该主博文会做更新,将其作为学习笔记。因此出于学习目的,我决定将主博文定位为入门 PyMC3 概率编程的学习脉络与框架部分,而将其中的细节于诸多从博文中展示,这样既符合模块化思维,又提升主博文的阅读体验,以防自己和观看的同学们在繁杂的内容中找不到重点。因为该篇博文是从博文,所以会和主博文有一定的联系,不过我会尽量将知识点独立地剥离出来,如果大家有什么不清楚的地方,请在评论区提出,我会尽快修改,有兴趣的同学可以移步至主博文阅读一下。
find_MAP() 函数
通过本篇博文我们来了解一下 find_MAP()
函数,这个函数的参数比较多,接下来对这些参数一个一个来解释,帮助大家弄清楚它们分别代表什么意思:
find_MAP(start=None, vars=None, method="L-BFGS-B", return_raw=False, include_transformed=True,
progressbar=True, maxeval=5000, model=None, *args, **kwargs)
-
start:
dict
类型,表示开始进行数值优化的初始值的字典,默认是模型自带的测试点,一般以start={'theta':10}
的形式进行传参的话,这就表示数值优化时参数 theta 从 10 开始迭代优化; -
vars:
list
类型,表示需要优化的变量的列表,默认是认定模型内所有的连续型变量都要优化,比如说如果变量 theta 需要进行优化,那我们就通过vars=[theta]
的方式进行传参; -
method:
string
类型,表示进行数值优化时用到的优化算法,默认是 L-BFGS-B 算法,当然也可以使用其他算法像 BFGS、POWELL 等,比如说变量是离散类型的时候使用 POWELL 算法效果会更好,不过这里的这些算法实现时都是调用scipy.optimize
的函数,因此也可以通过fmin=scipy.optimize.fmin_l_bfgs_b
这样的形式来告诉模型要用的优化算法,但是这种形式不推荐用了,因为在以后的版本不会再用 fmin 这个参数了,所以推荐使用 method 参数; -
return_raw:
bool
类型,表示是否返回所有的输出值,默认为 False,刚刚也讲了算法实现时都是调用scipy.optimize
的函数,而这些函数的输出内容一般比较多,因此选择 False 可以帮助我们筛选掉一部分输出; -
include_transformed:
bool
类型,表示是否输出除原始变量外自动转换的变量,默认为 True,这个参数我之前也没搞太懂,当时我发现,当它设为 False 时,输出确实只有一开始定义的变量了,比如说当它为 True 时,输出为{'theta_log__':array(……),'theta':array(……)}
,而当它为 False 时输出为{'theta':array(……)}
,后来询问了老师之后知道,这个参数是指是否在输出中包含代数变换后的变量,如果我们的变量 theta 服从逆伽马分布,属于有界变量,则 PyMC3 会自动对其进行代数变换生成一个 FreeRV —— theta_log__,当 include_transformed 参数为 True 时,就意味着打印 theta_log__,输出为{'theta_log__':array(……),'theta':array(……)}
,如果看到这里对该参数还是有一些不理解,请阅读主博文第二部分 6 知识扩展,或许能解决你的疑问; -
progressbar:
bool
类型,表示是在命令行中显示程序运行时的进度条,默认为 True,进度条的样式通常如下所示,logp 表示分布在初始值时对应的对数似然,grad 表示数值优化时的梯度的一种输出形式,对于这种输出形式,我一开始简单地以为,grad 仅仅表示每轮迭代的梯度的平均值,但后来查看源码后发现并不是这样,不过至少确定一个事实,grad 是一个 numpy array 的二范数,以及 grad 确实和迭代的梯度紧密相关,因此在后文中统一以 grad 梯度称呼它,我们也可以把它当成梯度来理解它,但是对于它到底是什么的这个问题还有待研究:
这里的 logp 虽然是负数,但因为 log 函数是递增函数,因此还是 logp 越大表示对应的似然越大,表示初始值越接近极大似然点估计的值。而 grad 梯度是在优化过程中得出的,它则是越小表示初始值离极大似然点估计的值越近,它可以简单的理解为导数,导数可正可负,因此进度条上对于 grad 梯度显示的是一个二范数的形式,数学中的函数图像的极值点对应的导数为 0 ,因此当你看到你的进度条的 grad 梯度为 0 时,那么恭喜你,你的直觉非常准,初始值设置的非常好。
我们来看一下另一个初始值对应的进度条,这样对比一下可以帮助理解,可以看到,当初始值设置为 1 时,它对应的 logp 是非常小的,而优化时得出的 grad 梯度是非常大的,这说明初始值 1 与极大似然点估计的值还有很大距离,每一轮迭代需要使用较大的梯度才能最终得到理想的点估计值:
-
maxeval:
int
类型,表示数值优化过程中迭代的最大轮数,默认为 5000,不过有时候用不到这么多轮,比如说上面的两个进度条显示的分别时迭代了 6 轮和 10 轮; -
model:
Model
类型,表示当前的模型,如果find_MAP()
函数是在with pm.Model()
上下文管理器中,那这个参数就不用指定,如果不在则需要指定,否则会报错; -
*args, **kwargs:额外的参数将会传给
scipy.optimize
的优化算法函数,帮助配置优化项。
关于 find_MAP()
函数,下面也给出了它在源码中的说明和参数解释,大家可以参考一下:
def find_MAP(start=None, vars=None, method="L-BFGS-B", return_raw=False, include_transformed=True,
progressbar=True, maxeval=5000, model=None, *args, **kwargs)
"""
Finds the local maximum a posteriori point given a model.
find_MAP should not be used to initialize the NUTS sampler. Simply call pymc3.sample() and it will automatically initialize NUTS in a better way.
Parameters
----------
start : `dict` of parameter values (Defaults to `model.test_point`)
vars : list
List of variables to optimize and set to optimum (Defaults to all continuous).
method : string or callable
Optimization algorithm (Defaults to 'L-BFGS-B' unless
discrete variables are specified in `vars`, then
`Powell` which will perform better). For instructions on use of a callable,
refer to SciPy's documentation of `optimize.minimize`.
return_raw : bool
Whether to return the full output of scipy.optimize.minimize (Defaults to `False`)
include_transformed : bool
Flag for reporting automatically transformed variables in addition
to original variables (defaults to True).
progressbar : bool
Whether or not to display a progress bar in the command line.
maxeval : int
The maximum number of times the posterior distribution is evaluated.
model : Model (optional if in `with` context)
*args, **kwargs
Extra args passed to scipy.optimize.minimize
"""