Python中的曲线拟合最小化均匀范数或L1范数(非最小二乘)
我有一组数据点(x_I,y_I),希望拟合曲线。我有一个函数的参数化,所以f(x;a)是由参数a定义的 我感兴趣的是使一致范数最小化的参数,即目标是min_a max_I | f(x_I;a)-y_I |。 如果不可能,我也对L1范数感兴趣,即目标\min_a\sum_I | f(x_I;a)-y_I | 我知道scipy.optimize中的曲线拟合,但该库仅适用于最小二乘目标,即L2范数 我想解决的问题规模较小,大约有100-200个数据点和4-5个参数,因此如果算法超慢,也没什么大不了的。 任何图书馆的建议都将不胜感激 谢谢 实现这一点的一种方法(我这里只讨论L1规范): 转换:Python中的曲线拟合最小化均匀范数或L1范数(非最小二乘),python,mathematical-optimization,curve-fitting,Python,Mathematical Optimization,Curve Fitting,我有一组数据点(x_I,y_I),希望拟合曲线。我有一个函数的参数化,所以f(x;a)是由参数a定义的 我感兴趣的是使一致范数最小化的参数,即目标是min_a max_I | f(x_I;a)-y_I |。 如果不可能,我也对L1范数感兴趣,即目标\min_a\sum_I | f(x_I;a)-y_I | 我知道scipy.optimize中的曲线拟合,但该库仅适用于最小二乘目标,即L2范数 我想解决的问题规模较小,大约有100-200个数据点和4-5个参数,因此如果算法超慢,也没什么大不了的。
- 不可微(由于L1范数)无约束优化问题
- 到:可微约束优化问题李>
- 而不是Min(和(L1(x)):
- 引入形状为x的变量y(辅助变量)
- 介绍约束条件:-y可能会给出L1的可微替代方案。您可能想查看迭代加权最小二乘法,例如()谢谢您的全面回答。然而,仅仅使用f5r5e5d在库[scipy cookbook.readthedocs.io/items/robust\u regression.html]中提到的软L1看起来确实更简单。我暂时不回答这个问题,因为我对统一规范非常感兴趣。
import numpy as np import matplotlib.pyplot as plt from scipy import optimize np.random.seed(0) """ Example function and curve_fit """ def f(t, omega, phi): return np.cos(omega * t + phi) x_ = np.linspace(0, 3, 50) y = f(x_, 1.5, 1) + .5*np.random.normal(size=50) y[5] += 5 # synthetic outlier y[10] += 5 # """ params, params_cov = optimize.curve_fit(f, x_, y) t = np.linspace(0, 3, 1000) """ Prototype l1 solver """ N = 2 # n-vars M = x_.shape[0] # number of samples def g(x): return sum(x[N+M:]) cons = ({'type': 'eq', 'fun': lambda x: x[N:N+M] - (f(x_, *x[:N]) - y), } , {'type': 'ineq', 'fun': lambda x: x[N+M:] + x[N:M+2], # -u_i <= x_i }, {'type': 'ineq', 'fun': lambda x: -x[N:M+2] + x[N+M:]} # x_i <= u_i ) res = optimize.minimize(g, np.random.uniform(high=0.05, size=N+M+M), constraints=cons, options={'disp': True}) params_ = res.x[:N] print(res.x[N:N+M]) # losses print(res.x[N+M:]) # l1(losses) """ Plot results """ plt.plot(x_, y, color='red', label='orig') plt.plot(t, f(t, *params), color='blue', label='curve_fit') plt.plot(t, f(t, *params_), color='black', label='l1') plt.legend() plt.show()