为什么scipy.optimize严重依赖于起始值?

时间:2016-04-02 11:56:42

标签: python numpy optimization scipy

我正在尝试使用import csv from bs4 import BeautifulSoup import requests with requests.Session() as session: for ace in range(129867, 129869): url = "http://www.gbgb.org.uk/resultsMeeting.aspx" html = session.get(url, params={'id': ace}).text soup = BeautifulSoup(html, 'lxml') 来做一些简单的优化问题,但我发现我只能找到具有非常有限的起始值范围的解决方案。这是一个最小的可复制示例:

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

enter image description here

尝试不同的起始值,我发现只有当0.65的起始值介于p0.1之间时,才能找到正确的解决方案。最小化算法似乎非常不稳定。

我尝试了几种不同的最小化算法(BFGS,Powell等),它们产生了类似的结果,所以我猜问题必须是我的,而不是算法'。

2 个答案:

答案 0 :(得分:3)

标准数值优化程序使用函数值(您想要优化的值)和渐变(大致是函数的横向信息)。

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

这里我手工完成数学运算,不要使用统计数据中的函数。对数转换使计算梯度更容易。

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)])

添加渐变信息时,优化例程会成功找到任意起始值的最佳值。

答案 1 :(得分:2)

问题是你的函数在{0,1]之外的Format是未定义的(返回nan),优化器不喜欢它。

您可以尝试指定x选项以通知优化器 - 但是,nan返回会导致端点的梯度近似出现问题。

由于您只有一个变量,因此可以对1D问题使用特殊优化器,这些问题只能访问边界内的值:

bounds=[(0,1)]