2.7.4 特殊案例: 非线性最小二乘

2.7.4.1 最小化向量函数的基准

最小二乘法,向量函数基准值的最小化,有特定的结构可以用在scipy.optimize.leastsq()中实现的Levenberg–Marquardt 算法

让我们试一下最小化下面向量函数的基准:

In [5]:

  1. def f(x):
  2. return np.arctan(x) - np.arctan(np.linspace(0, 1, len(x)))
  3. x0 = np.zeros(10)
  4. optimize.leastsq(f, x0)

Out[5]:

  1. (array([ 0\. , 0.11111111, 0.22222222, 0.33333333, 0.44444444,
  2. 0.55555556, 0.66666667, 0.77777778, 0.88888889, 1\. ]), 2)

这用了67次函数评估(用'full_output=1'试一下)。如果我们自己计算基准并且使用一个更好的通用优化器(BFGS)会怎么样:

In [6]:

  1. def g(x):
  2. return np.sum(f(x)**2)
  3. optimize.fmin_bfgs(g, x0)
  1. Optimization terminated successfully.
  2. Current function value: 0.000000
  3. Iterations: 11
  4. Function evaluations: 144
  5. Gradient evaluations: 12

Out[6]:

  1. array([ -7.44987291e-09, 1.11112265e-01, 2.22219893e-01,
  2. 3.33331914e-01, 4.44449794e-01, 5.55560493e-01,
  3. 6.66672149e-01, 7.77779758e-01, 8.88882036e-01,
  4. 1.00001026e+00])

BFGS需要更多的函数调用,并且给出了一个并不精确的结果。

注意只有当输出向量的维度非常大,比需要优化的函数还要大,leastsq与BFGS相类比才是有趣的。

如果函数是线性的,这是一个线性代数问题,应该用scipy.linalg.lstsq()解决。

2.7.4.2 曲线拟合

2.7.4 特殊案例: 非线性最小二乘 - 图1

最小二乘问题通常出现在拟合数据的非线性拟合时。当我们自己构建优化问题时,scipy提供了这种目的的一个帮助函数: scipy.optimize.curve_fit():

In [7]:

  1. def f(t, omega, phi):
  2. return np.cos(omega * t + phi)
  3. x = np.linspace(0, 3, 50)
  4. y = f(x, 1.5, 1) + .1*np.random.normal(size=50)
  5. optimize.curve_fit(f, x, y)

Out[7]:

  1. (array([ 1.50600889, 0.98754323]), array([[ 0.00030286, -0.00045233],
  2. [-0.00045233, 0.00098838]]))

练习

用omega = 3来进行相同的练习。困难是什么?