告诉scipy.optimize.minimize失败

3 投票
1 回答
2754 浏览
提问于 2025-04-18 06:33

我正在使用scipy.optimize.minimize来优化一个目标函数,这个函数需要几个参数,并根据这些参数运行一个复杂的数值模拟。不过,这个模拟并不总是能收敛,有时候我会让目标函数返回无穷大(inf),有时候返回不是数字(NaN)。

我以为这样做可以阻止优化算法在那些让模拟发散的参数附近找到解。然而,我遇到了一个情况,模拟在起始参数下根本就不收敛,但优化却“成功”结束了,迭代次数为0。看起来它并不在乎目标函数返回无穷大。

有没有办法让scipy.optimize.minimize在这种情况下失败,比如通过抛出某种异常?虽然在这个例子中很明显优化没有成功结束——因为迭代次数是0,而且我知道最优结果——但将来我可能会遇到一些我不知道答案的问题,这时我需要依赖minimize来告诉我情况是否糟糕。如果返回很多NaN和inf并不会“破坏”算法,我想我可能得用蛮力来解决。


以下是这个几乎没有迭代的例子。这个函数是两个变量的函数,总共调用了4次:
1) 在起始点 -> 模拟发散,f(x) = inf
2) 在右边1e-5的点(梯度近似) -> 模拟发散,f(x) = inf
3) 在上方1e-5的点(梯度近似) -> 模拟收敛,f(x) = 某个有限值
4) 再次在起始点 -> 模拟发散,f(x) = inf

1 个回答

1

我想到你有两个选择:

  • 选择约束优化
  • 修改你的目标函数,让它在数值模拟不收敛的时候返回一个很大的值。简单来说,就是返回一个比“正常”值大得多的数,这个“正常”值是根据你具体的问题来定的。这样一来,minimize 就会尝试往另一个方向去优化。

不过,我有点惊讶的是,minimize 似乎不把 inf 当作一个大值来处理,也没有尝试在其他方向寻找解决方案。可能只有当你的目标函数返回 nan 时,它才会以0次迭代结束?你可以试着在目标函数的 return 语句之前打印出这个值,看看问题出在哪里。

撰写回答