牛顿法
在实际的算法中,很少需要达到最大可能的精度。在现实世界的数据中,建模和测量误差通常比浮点数舍入导致的误差大了几个数量级,我们通常很愿意选择一种近似方法,以牺牲精度为代价换取速度。
接下来,我们将介绍这种近似的数值算法中最重要的组成部分之一:牛顿法。
Newton’s Method
牛顿方法是一种简单但非常强大的算法,用于寻找实值函数的近似根,即以下通用方程的解:
f(x)=0
对于函数f,我们只假设它至少有一个根,并且在搜索区间上f(x)是连续且可微的。虽然也有一些令人厌烦的异常情况,但在实际应用中几乎从未出现过这种情况,所以我们可以非正式地说这个函数是"好”的。
牛顿法的主要思想是以某个初始点x0开始,然后不断通过在函数图像上各点处切线与x轴交点的x坐标作为新的近似点来迭代优化。这个算法的直观理解是,如果f是“良好”的(光滑且单调),并且当前的近似点xi已经足够接近根了,那么下一个近似点xi+1会更接近这个根。

为了获取交点xn,我们需要另其切线函数等于零:
0=f(xi)+(xi+1−xi)f′(xi)
由此可以得到:
xi+1=xi−f′(xi)f(xi)
牛顿方法非常重要:它是科学领域和工程领域中各种优化求解器的基础。
平方根
作为一个简单的例子,让我们导出求平方根问题的算法:
x=n⟺x2=n⟺f(x)=x2−n=0
如果我们将f(x)=x2−n替换为上述通用公式,可以获得如下更新的规则:
xi+1=xi−2xixi2−n=2xi+n/xi
在实践中,我们还希望在它足够接近正确答案时立即停止它,我们可以在每次迭代后简单地检查:
const double EPS = 1e-9;
double sqrt(double n) { double x = 1; while (abs(x * x - n) > eps) x = (x + n / x) / 2; return x; }
|
该算法虽然在许多函数上都能收敛,但只有在某些特定的函数集合(比如凸函数)上,才能保证算法是可靠且可证明的。另外一个问题是如果算法能够收敛,那么它的收敛速度是多快。
收敛速度
让我们运行几次牛顿法来寻找2的平方根。初始值x0设定为1,然后在每次迭代之后,我们检查算法得到的结果有多少位数是准确的:
11.000000000000000000000000000000000000000000000000000000000000011.50000000000000000000000000000000000000000000000000000000000001.411.41666666666666666666666666666666666666666666666666666666666751.414211.41421568627450980392156862745098039215686274509803921568627451.414213562371.41421356237468991062629557889013491011655962211574404458490571.414213562373095048801681.41421356237309504880168962350253024361498192577619742849828901.414213562373095048801688724209698078569671875371.41421356237309504880168872420969807856967187537723400156101251.41421356237309504880168872420969807856967187537694807317667961.4142135623730950488016887242096980785696718753769480731766796
仔细观察,我们能够发现每次迭代准确的数字位数会大约翻倍。这种惊人的收敛速度并非巧合。
要定量分析这种收敛速度,我们需要考虑在第i次迭代时的相对误差δi,以及在下一次迭代时的误差δi+1。 我们需要确定δi+1相对于δi变小了多少,以此来衡量我们的算法收敛速度提升了多少:
∣δi∣=xxn−x
我们可以将xi表示为x⋅(1+δi)。将其带入对应的牛顿迭代公式并约掉两边的x可以得到:
1+δi+1=21(1+δi+1+δi1)=21(1+δi+1−δi+δi2+o(δi2))=1+2δi2+o(δi2)
这里我们对(1+δi)−1在0处进行泰勒展开,并假设了误差di很小(因为序列收敛,所以对于足够大的n,di≪1)。进一步我们可以得到:
δi+1=2δi2+o(δi2)
当我们接近解时,每次迭代大概会让误差平方,并且减半。由于对数(−log10δi)大致等于答案xi中准确小数位的数量,因此将相对误差平方,对应的就是将答案中的准确小数位的数量翻倍。
这个被称为二次收敛(quadratic convergence),事实上并不仅限于求平方根。可以证明的是(具体细节留给读者去推导):
∣δi+1∣=2⋅∣f′(xn)∣f′′(xi)⋅δi2
在一些额外的假设下,即f’(x)不等于0且f′′(x)连续的情况下,至少能得到二次收敛的结果。
拓展阅读