
上QQ阅读APP看书,第一时间看更新
3.2.4 计算全域最小值
前面介绍的几种最小值优化算法都只能计算局域的最小值,optimize库还提供了几种能进行全局优化的算法,下面以前面的正弦波拟合为例,演示全局优化函数的用法。在使用leastsq( )对正弦波进行拟合时,误差函数residuals( )返回一个数组,表示各个取样点的误差。而函数最小值算法则只能对一个标量值进行最小化,因此最小化的目标函数func_error( )返回所有取样点的误差的平方和。
def func(x, p): A, k, theta = p return A* np.sin(2* np.pi* k* x+theta) def func_error(p, y, x): return np.sum((y - func(x, p))** 2) x = np.linspace(0, 2* np.pi, 100) A, k, theta = 10, 0.34, np.pi/6 y0 = func(x, [A, k, theta]) np.random.seed(0) y1 = y0 + 2 * np.random.randn(len(x))
我们使用optimize.basinhopping( )全域优化函数找出正弦波的三个参数。它的前两个参数和其他求最小值的函数一样:目标函数和初始值。由于它是全局优化函数,因此初始值的选择并不是太重要。niter参数是全域优化算法的迭代次数,迭代的次数越多,就越有可能找到全域最优解。
在basinhopping( )内部需要调用局域最小值函数,其minimizer_kwargs参数决定了所采用的局域最小值算法以及传递给此函数的参数。下面的程序指定使用L-BFGS-B算法搜索局域最小值,并且将两个对象y1和x传递给该局域最小值求解函数的args参数,而该函数会将这两个参数传递给func_error( )。
result = optimize.basinhopping(func_error, (1, 1, 1), niter = 10, minimizer_kwargs={"method":"L-BFGS-B", "args":(y1, x)}) print result.x [ 10.25218694 -0.34239909 2.63341582]
虽然频率和相位与原系数不同,但是由于正弦函数的周期性,其拟合曲线是和原始数据重合的,如图3-5所示。

图3-5 用basinhopping( )拟合正弦波