scipy.minimize 如何处理 NaN?
Posted
技术标签:
【中文标题】scipy.minimize 如何处理 NaN?【英文标题】:How does scipy.minimize handle NaN's? 【发布时间】:2018-09-02 19:37:13 【问题描述】:我在 scipy.minimize 中使用 SLSQP 求解器来求解约束优化问题。求解器经常会尝试违反约束的参数值。当违反这些约束时,目标函数返回nan
。这似乎会带来问题,因为我的近似雅可比几乎每次重新计算时都充满了nan
。通常情况下,优化会在exit mode 8: Positive directional derivative for linesearch
中终止。我怀疑近似雅可比行列式中的nan
是这个问题的根源。那么我的问题是 scipy.minimize 如何处理 nan
的?它们是良性的,还是应该将它们转换为一个大(甚至无限)的数字?据我所知,Scipy 文档中的任何地方都没有涵盖此信息。
【问题讨论】:
您应该假设每个 nan 都在杀死一切。所以:没有nans!唯一有效的 nan 是 API 级别的边界。在 SLSQP 方面,边界处理(恕我直言)也存在差异。在迭代期间将严格保持边界(没有关于边界的不可行解决方案是迭代),而约束则不是这样(它也可以描述边界)。 嗯,那么 nans 的处方是什么?他们应该转换为infs吗?还是其他一些较大的有限数? 这在很大程度上取决于特定的最小化器和/或问题。对于估计 Hessian 并使用返回高值的二阶导数的最小化器,可能会导致最小化器混淆。然而,对于不使用导数的方法(如 Nelder-Mead 单纯形算法),有时可以在参数超出范围时返回较大的值。 你最后做了什么? 【参考方案1】:根据您使用的搜索算法,scipy
中会检查 nans
。您必须检查每个搜索算法的来源。它通常不会影响最小化器(除非您使用非歧视性方法),但它确实会破坏最大化。一般来说,scipy
使用numpy
数组。了解发生了什么的最好方法是使用以下简单示例:
>>> x = [-np.nan, np.nan, 1, 2, 3, np.nan] # some random sequence of numbers and nans
>>> np.sort(x)
array([ 1., 2., 3., nan, nan, nan])
np.nan
总是被视为最大的数字,因此,您必须在搜索算法中明确说明这一点,以便这些解决方案在未来的迭代中被拒绝。至于解释+/- nans
,请参阅this,如果后端实现是在fortran 中 - 有时是这种情况。
【讨论】:
【参考方案2】:有一个非常先进的最小化例程,称为 Minuit,它用于粒子物理社区,类似于您提到的例程。他们都使用拟牛顿法来估计二阶导数,以尝试在最少的迭代次数内“跳”到最小值。
这些方法通常不处理边界值问题,并且有一类完全不同的算法致力于最小化具有约束的函数。
话虽如此,在 Minuit 中可以设置参数边界。在 Minuit 中实现这一点的方式非常聪明。基本上每个参数都“内部”映射到:
p_int = arcsin(2*(p_ext-a)/(b-a)-1)
和
p_ext = a + ((b-a)/2)*(sin(p_int)+1)
其中a
和b
分别是上限和下限。详情请参阅 Minuit 手册here。
假设你的每个参数都有线性界限,我怀疑你可以做类似的事情。
【讨论】:
以上是关于scipy.minimize 如何处理 NaN?的主要内容,如果未能解决你的问题,请参考以下文章