首页 > 代码库 > 牛顿法

牛顿法

看最优化的文章时总能看到牛顿法和梯度下降法等基础算法,这里对牛顿法做个总结。

牛顿法一般的用途有:1、求方程的根;2、求极值

求方程的根

并不是所有的方程都有求根公式,或者求根公式很复杂,导致求解困难。利用牛顿法,可以迭代求解。

原理是利用泰勒公式,在x0处展开,且展开到一阶,即f(x) = f(x0)+(x-x0)f‘(x0)

求解方程f(x)=0,即f(x0)+(x-x0)*f‘(x0)=0,求解x = x1=x0-f(x0)/f‘(x0),因为这是利用泰勒公式的一阶展开,f(x) = f(x0)+(x-x0)f‘(x0)处并不是完全相等,而是近似相等,这里求得的x1并不能让f(x)=0,只能说f(x1)的值比f(x0)更接近f(x)=0,于是乎,迭代求解的想法就很自然了,可以进而推出x(n+1)=x(n)-f(x(n))/f‘(x(n)),通过迭代,这个式子必然在f(x*)=0的时候收敛。整个过程如下图:

技术分享

 

求极值

根据函数极值的必要条件可知,要求一个函数f(x)的极值,可以令f‘(x)=0求方程得到极小值点,于是可以采用类似于上面的牛顿法求方程,迭代式子为:

技术分享

 

下面编写程序对上面的各举一个例子说明:

#!/usr/bin/python
# -*- coding:utf8 -*-
import random

#f(x) = x^2 - 4*x + 3

lastval = random.uniform(-10,10)
def solution(func1, func2) :
    global lastval
    val = 0
    for index in xrange(0, 100) :
        val = lastval - func1(lastval) * 1.0 / func2(lastval)
        if abs(val - lastval) < 0.000001 : break
        lastval = val
    print "times of iterate : %s" % index
    return val

if __name__ == "__main__" :
    print "solution of equation x^2 - 4*x + 3 =0 : %s" % solution(lambda x: x**2 - 4*x + 3, lambda x: 2*x - 4)
    print "minimum of f(x) = x^2 - 4*x + 3 : %s" % solution(lambda x: 2*x - 4, lambda x: 2)


执行结果:

技术分享

可以看到牛顿法解方程需要迭代的次数一直在变,这是跟初始值有关;求极值例子比较简单,只一次迭代就完成了,其实相同条件下牛顿法求极值比梯度下降法要更快!牛顿法的一大优点就是它比梯度下降法更具有全局判断能力,在二阶导数的作用下,从函数的凹凸性出发,直接搜索怎样到达极值点;而梯度法是从初始点的领域开始判断,在局部进行最速下降方向,然后步步逼近极值;所以往往会导致梯度下降法比牛顿法迭代的次数更多。

 

文章参考于http://blog.csdn.net/luoleicn/article/details/6527049

                  http://www.zhihu.com/question/19723347

 

牛顿法