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)

其中ab 分别是上限和下限。详情请参阅 Minuit 手册here。

假设你的每个参数都有线性界限,我怀疑你可以做类似的事情。

【讨论】:

以上是关于scipy.minimize 如何处理 NaN?的主要内容,如果未能解决你的问题,请参考以下文章

如何处理插补没有意义的 NaN 值? (对于 PCA)

使用python绘制箱线图时如何处理NaN值

python:如何处理if语句中的NaN数据[重复]

如何处理来自文本框的输入以不打印 NaN

如何处理 Python 中应该缺失的缺失值(不应插入 NaN)?

Fs 错误地读取或保存导致 NaN 的文件。如何处理?