【问题标题】:Why does "scipy.optimize.minimize" gives me such a bad fit?为什么“scipy.optimize.minimize”让我很不合适?
【发布时间】:2019-07-25 21:21:23
【问题描述】:

我有一个函数y(x,z) 有两个变量xz 和6 个系数abcdef。我有 xz 的数据,让我们说用于测试目的的系数数据。使用这些数据,我计算出我的y

然后我想用x,z和计算出的y的数据来拟合函数,得到系数并与测试目的一比较。

import numpy as np
from scipy.optimize import minimize

x = np.array([0,0.25,0.5,0.75,1]) # data of variable x
z = np.array([0,0.25,0.5,0.75,1]) # data of variable z

def func(pars,x,z): #my function
    a,b,c,d,e,f = pars
    return a*x**2+b*x+c+d*z+e*z*x+f*z*x**2

a = np.array([1,1,1,1,1])  #define coefficients to get the y data and compare them later with fit
b = np.array([0.5,0.5,0.5,0.5,0.5])
c = np.array([0.25,0.25,0.25,0.25,0.25])
d = np.array([1,1,1,1,1])
e = np.array([0.5,0.5,0.5,0.5,0.5])
f = np.array([0.25,0.25,0.25,0.25,0.25])

y = []
y.append(func((a,b,c,d,e,f),x,z)) #calculate the y data
print(y)

def resid(pars,x,z,y): #residual function
    return ((func(pars,x,z) - y) ** 2).sum()

pars0 = np.array([0,0,0,0,0,0])
res = minimize(resid, pars0,args=(x,z,y), method='cobyla',options={'maxiter': 5000000})
print("a = %f , b = %f, c = %f, d = %f, e = %f, f = %f" % (res.x[0], res.x[1], res.x[2], res.x[3], res.x[4], res.x[5]))

我从拟合中得到以下系数:

a = 1.181149 , b = 1.228558, c = 0.253053, d = 0.219143, e = 0.444941, f = 0.172369

与我计算y 数据的系数相比,拟合并不是我所说的足够。谁能解释一下为什么我的身材这么差?

P.S.:如果有人想知道,我使用cobyla,因为我稍后必须定义一些约束。这只是一个测试代码,用于找出我的问题所在(希望如此)。

【问题讨论】:

    标签: python scipy curve-fitting minimize


    【解决方案1】:

    看看res.fun,在你的情况下,1e-5 附近实际上非常合适。

    您很可能找到了目标函数的局部最小值。为了更好地理解这种行为,请尝试下面的代码。这将为不同的起点产生不同的结果。如您所见,您正在最小化,而不是全局最小值。要全局优化,您必须使用其他方法/方法。您还可以增加何时停止优化的标准。或者使用混合方法,从不同的初始点开始,解决局部最小化并取最佳值。

    for i in range(10):
        pars0 = np.random.rand(6) * 1
        res = minimize(resid, pars0, args=(x,z,y), method='cobyla',options={'maxiter': 5000000})
        print("a = %f , b = %f, c = %f, d = %f, e = %f, f = %f" % (res.x[0], res.x[1], res.x[2], res.x[3], res.x[4], res.x[5]))
        print(res.fun)
    

    尝试接近您正在寻找的解决方案的初始点。这很可能会产生全局结果。如果您不知道解决方案的模糊位置,您可能必须使用混合/全局方法来最小化。

    例如初始点:

    pars0 = np.array([1,0.5,0.25,1,0.5,0.25]) + np.random.rand(6)*0.01
    

    产生了一个非常合适的解决方案。

    【讨论】:

    • 啊,我明白了,写得很好。谢谢!一个小(愚蠢的)问题:res.fun 做什么?正如您所怀疑的那样,我不知道模糊的位置。所以我想,我必须使用全局方法。
    • 欢迎您!您可以在这里查看 res 对象的不同选项:docs.scipy.org/doc/scipy/reference/generated/…res.fun为您提供最小值的目标函数值。有关优化结果的更多信息,请参阅res.success 或其他人。您也可以尝试使用优化器的设置。但是如果你问我,1E-5 的均方根误差是相当不错的。等着看你的代码如何处理真实的测量数据。
    • 还有一件事:您还可以通过使用更详细的数据来增加曲线拟合。您只是在测试 5 个 x 和 z 值。尝试适合例如x = np.linspace(0,1,100)。这应该会增加寻找正确参数集的变化。
    猜你喜欢
    • 2014-01-03
    • 2011-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-16
    • 2011-01-03
    • 1970-01-01
    相关资源
    最近更新 更多