Skip to main content
 首页 » 编程设计

python之为什么 scipy.optimize 如此依赖起始值

2025年05月04日29emanlee

我正在尝试使用 scipy.optimize 来做一些简单的优化问题,但我发现我只能找到起始值范围非常有限的解决方案。这是一个最小的可复制示例:

import numpy as np 
import scipy.stats as st 
from scipy.optimize import minimize 
 
p = np.linspace(0, 1, 100) 
neg_likelihood = lambda p: -1 * st.binom.pmf(6, n=9, p=p) 
minimize(neg_likelihood, 0.3) 

neg_likelihood 函数的形状如下图所示,所以正确答案应该在0.65 左右:

尝试不同的起始值,发现只有p的起始值在0.1和0.4之间才能找到正确的解>。最小化算法似乎非常不稳定。

我尝试了几种不同的最小化算法(BFGS、Powell 等),它们产生了相似的结果,所以我想问题一定是我的,而不是算法的。

请您参考如下方法:

标准数值优化例程使用函数值(您要优化的值)和梯度(函数的大致横向信息)。

您只提供了功能。因此优化程序必须近似梯度。每当您可以计算梯度时,请添加此信息源并且不要依赖近似值。

这里我手工计算,不使用统计中的函数。对数变换使计算梯度更容易。

import numpy as np 
from scipy.optimize import fmin_l_bfgs_b 
 
# do the math by hand, it's quite simple in this case 
def target_fun(p, k, n): 
    f = - k* np.log(p) - (n-k)*np.log(1-p) 
    g =  - k/p + (n-k) / (1-p) 
    return f, g 
 
f = lambda p: target_fun(p, k=6, n=9) 
epsilon = 1e-9 
fmin_l_bfgs_b(f, 0.999, bounds=[(epsilon,1-epsilon)]) 

当您添加梯度信息时,优化例程会成功找到任意起始值的最优值。