简介
牛顿法又叫做牛顿-拉裴森(Newton-Raphson)方法,是一维求根方法中最著名的一种。其特点是在计算时需要同时计算函数值与其一阶导数值,从几何上解释,牛顿法是将当前点处的切线延长,使之与横轴相交,然后把交点处值作为下一估值点。
图1
从数学上解释,牛顿法可以从函数的泰勒展开得到。\(f(x)\)的泰勒展开可以表示为:
\(f(x+\delta)=f(x)+f’(x)\delta+\frac{f’’(x)}{2}\delta^2+O(\delta^3)\)
对于足够小的\(\delta\),可以将只保留上式右端关于的一阶项,得到:
\(\delta=-\frac{f(x)}{f’(x)}\)
于是得到由到的递推公式:
\(x_{i+1}=x_{i}+\delta=x_i-\frac{f(x_i)}{f’(x_i)}\)
可见牛顿法是让\(x\)沿着\(f(x)\)梯度的方向下降,类似于最优化方法中的梯度下降法。牛顿法也可以作为最优化算法,只不过那时需要求函数的二阶导数。
牛顿法相比二分法、截弦法的优点是收敛速度可以达到二阶,在根附近没迭代一次,结果的有效数字几乎可以翻倍。当然牛顿法也可能可能失败,比如收敛到一个局部极值,其切线方向与横轴水平,从而无法计算下一个迭代值。
另外,牛顿法的实现需要用户提供一个函数用于计算函数值\(f(x)\)与其一阶导数值\(f'(x)\),因此比较适合函数的导数可以解析求出的情况,如果需要求数值导数,则牛顿法的收敛速度和精度都会受影响。
我们可以将牛顿法和二分法综合起来形成一个混合算法,一旦牛顿法在运行过程中出现解跳出给定区间或者猜测值远离实际根导致收敛速度较慢时,就采取一步二分法。
实现一:利用预先求出的一阶导函数
import numpy as np import matplotlib.pyplot as plt def f(FV, PMT, r, n): return PMT * (1 + r) * (((1 + r)**n - 1)) / r + FV def df(FV, PMT, r, n): r_plus_1_power_n = (1 + r)**n p1 = N * PMT * r_plus_1_power_n / r p2 = -PMT * (r + 1) * (r_plus_1_power_n - 1) / r / r p3 = PMT * (r_plus_1_power_n - 1) / r return p1 + p2 + p3 def newtonRaphson2(FV, PMT, n, f, df, xmin, xmax, maxit, shift=0.0001, tol=1.0e-9): ''' 函数作用说明:计算组合收益率 FV:目标金额 PMT:每期投资金额 n:定投期数 f:函数值(根据要求的方程自定义) df:导数值ÿ