使用fmin_l_bfgs_b正确拟合模型参数的方法

8
我有一些实验数据(y,x,t_exp,m_exp),想使用约束多元BFGS方法找到适合这些数据的“最佳”模型参数(A,B,C,D,E)。参数E必须大于0,其他参数没有限制。
def func(x, A, B, C, D, E, *args):
    return A * (x ** E) * numpy.cos(t_exp) * (1 - numpy.exp((-2 * B * x) / numpy.cos(t_exp))) +  numpy.exp((-2 * B * x) / numpy.cos(t_exp)) * C + (D * m_exp)

initial_values = numpy.array([-10, 2, -20, 0.3, 0.25])
mybounds = [(None,None), (None,None), (None,None), (None,None), (0, None)]
x,f,d = scipy.optimize.fmin_l_bfgs_b(func, x0=initial_values, args=(m_exp, t_exp), bounds=mybounds)

一些问题:
  1. 我的模型公式中,应该包含自变量x,还是应该从实验数据x_exp中作为*args的一部分提供?
  2. 当我运行上面的代码时,我收到一个错误消息"func()至少需要6个参数(已提供3个)",我认为这些参数是x和我的两个*args... 我应该如何定义func?
编辑:感谢@zephyr的答案,我现在明白了目标是最小化残差平方和,而不是实际函数。我得到了以下可行的代码:
def func(params, *args):
    l_exp = args[0]
    s_exp = args[1]
    m_exp = args[2]
    t_exp = args[3]
    A, B, C, D, E = params
    s_model = A * (l_exp ** E) * numpy.cos(t_exp) * (1 - numpy.exp((-2 * B * l_exp) / numpy.cos(t_exp))) +  numpy.exp((-2 * B * l_exp) / numpy.cos(theta_exp)) * C + (D * m_exp)
    residual = s_exp - s_model
    return numpy.sum(residual ** 2)

initial_values = numpy.array([-10, 2, -20, 0.3, 0.25])
mybounds = [(None,None), (None,None), (None,None), (None,None), (0,None)]

x, f, d = scipy.optimize.fmin_l_bfgs_b(func, x0=initial_values, args=(l_exp, s_exp, m_exp, t_exp), bounds=mybounds, approx_grad=True)

我不确定边界是否正常工作。当我为E指定(0, None)时,我得到了运行标志2,异常终止。如果我将其设置为(1e-6, None),它可以正常运行,但选择了1e-6作为E。我是否正确指定了边界?

1个回答

14

我不想尝试弄清楚您正在使用的模型代表什么,因此这里有一个简单的示例,适合拟合一条直线:

x_true = arange(0,10,0.1)
m_true = 2.5
b_true = 1.0
y_true = m_true*x_true + b_true

def func(params, *args):
    x = args[0]
    y = args[1]
    m, b = params
    y_model = m*x+b
    error = y-y_model
    return sum(error**2)
initial_values = numpy.array([1.0, 0.0]) mybounds = [(None,2), (None,None)]
scipy.optimize.fmin_l_bfgs_b(func, x0=initial_values, args=(x_true,y_true), approx_grad=True) scipy.optimize.fmin_l_bfgs_b(func, x0=initial_values, args=(x_true, y_true), bounds=mybounds, approx_grad=True)

第一次优化是无界的,给出了正确答案,第二个则遵循边界,防止它达到正确的参数。

您错误的重要事情是几乎所有的优化函数中,“x”和“x0”指的是您正在优化的参数-其他所有参数都以参数形式传递。您的拟合函数返回正确的数据类型也很重要-在这里,我们需要一个单一值,某些程序需要一个误差向量。此外,除非您要计算解析梯度并提供它,否则您需要使用approx_grad=True标志。


谢谢,这帮助我理解了。我更新了问题,但仍然在E的边界上遇到问题。 - Benjamin
@Benjamin - 我看到一个问题是,在你的模型中,A和E是不确定的。由于它们只出现在项A*l_exp**E中,它们可以同时变化而不影响模型的值,因此不会有唯一的解决方案。 - so12311
似乎使用 (0, None) 可以将参数固定为 0,而使用 (0,10) 则允许在该范围内使用值。 - Benjamin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接