Scipy非线性曲线拟合中的过拟合问题

4
我有一个模型方程,我们称之为eq_m:

eq_m

我知道我的数据集符合这个方程,我试图将数据拟合到eq_m中,以便可以使用拟合参数预测新数据。
然而,由于eq_m是非线性的,因此我使用了scipy的curve_fit来获取lambda、mu和sigma参数值,使用以下代码段:
opt_parms, parm_cov = o.curve_fit(eq_m, x, y,maxfev=50000)
lamb , mu, sigm = opt_parms

我在各种数据组上运行这个模型,它们都应该遵循这个模型,其中55/60给我很好的结果,然而另外的5个组被高度过度拟合,并且预测参数具有很高的正值。是否有一种方法可以使用scipy/numpy或scikit-learn来压缩曲线拟合并惩罚高幅度参数值?
我的主管建议使用共轭先验分布,但我不知道如何在这里做到这一点。
请问有谁能帮助我解决这个问题吗?如果我要提供一个猜测来解决这个问题,有人能告诉我如何计算这些猜测吗?
1个回答

9
curve_fit不支持正则化,它始终使用最小二乘代价函数。若要对拟合进行正则化,则需要编写一个自定义的代价函数,并使用scipy.optimize.minimize来最小化该函数。
首先,让我们将曲线拟合转换为一个最小化问题:
def eq_m(x, lamb, mu, sigm):  # assumed signature of eq_m
    pass

def cost(params):  # simply use globally defined x and y
    lamb, mu, sigm = params
    model = eq_m(x, lamb, mu, sigm)
    return np.mean((model - y)**2)  # quadratic cost function

p0 = [1, 0, 1]  # initial guess for lambda, mu, and sigma
res = o.minimize(cost, p0)
print(res)  # see if minimization succeeded.
lamb, mu, sigm = res.x

我希望这个功能可以给你带来与curve_fit类似的结果。(如果不是这样的话,那么就是时候开始调试了。)

现在我们可以通过调整代价函数来实现正则化:

def cost(params):
    lamb, mu, sigm = params
    model = eq_m(x, lamb, mu, sigm)
    reg = lamb**2 + mu**2 + sigm**2  # very simple: higher parameters -> higher cost
    regweight = 1.0  # determines relative importance of regularization vs goodness of fit
    return np.mean((model - y)**2)  + reg * regweight

在惩罚参数方面,没有必要严格地采用二次惩罚。基本上你可以做任何事情,只要确保大的参数会增加成本。结果会有所不同 :-)

所有这些都是一种非常特殊的方法,缺乏严谨的理论基础。导师建议使用共轭先验听起来像是他们期望你使用Bayesian估计技术。虽然某些先验可以被认为是等同于正则化,但这种方法完全不同,并且在数学上可能相当复杂。你需要定义一个似然函数,对参数进行先验设定,并使用Bayes规则将它们组合起来得到后验似然,最终进行最大化,而不是成本函数。


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