非线性优化之牛顿(梯度)下降法、高斯牛顿法、LM下降法

本质都是基于梯度下降法。
牛顿法: 依赖于Hessen矩阵非奇异,收敛较快
高斯 牛顿法:依赖二阶项的jacobian 解决了Hessen非奇异的问题,收敛相对慢
LM下降法:表现是使用一个因子拟合牛顿和高斯牛顿法

#coding=utf-8
from numpy import *
import sympy

def Hessen(f,x,x_value):
        #行 列表示Hesse矩阵
    num=len(x)
    lis2=mat([[1.0 for i in range(num)] for i in range(num)],dtype=float64)
        for i in range(num):
        for j in range(i,num):
            f1=sympy.diff(f,x[i],1)
            f2=sympy.diff(f1,x[j],1)
            value= f2.subs(x_value)
            lis2[i,j]=value
    return lis2


def Jacobian(f,x,x_value):
    num=len(x)
    lis1=mat([1.0 for i in range(num)])
    #print lis1
    for i in range(num):
        s2=sympy.diff(f,x[i],1)
        value= s2.subs(x_value)
        #print value
        lis1[0,i] =value
        #print lis1[0,i]
    return lis1.T

def handle(n): 
    x=[1 for i in range(n)]
    for i in range(n):
        str1='x['+str(i)+']'
        x[i] = sympy.Symbol(str1)
    return x

def Newton(f,x_value,maxIter):
    num=len(x_value.keys())
    x=handle(num)
    #求逆运算的问题
    error=f.subs(x_value)
    try:
        for i in range(maxIter):
            hessen=Hessen(f,x,x_value)
            I=mat(zeros((num,num)))
            #for q in range(num):
            #   I[q,q]=0.001
            jacobian=Jacobian(f,x,x_value)      
            delta=-1*dot((linalg.inv(hessen)+I),jacobian)
            #delta=dot(delta,error)
            #print jacobian,hessen,delta        
            for j in range(num):
                x_value[x[j]]=x_value[x[j]]+delta[j,0]
            error=f.subs(x_value)
            print i,error
    except:
        print "gradient is vanish"
    return x_value,error


def GaussNewton(f,x_value,maxIter):
    num=len(x_value.keys())
    x=handle(num)
    #求逆运算的问题
    error=f.subs(x_value)
    try:
        for i in range(maxIter):
            jacobian=Jacobian(f,x,x_value)  
            J1=dot(jacobian.T,jacobian)
            #print J1   
            J2=-1.0*dot(linalg.inv(J1),jacobian.T)
            delta=dot(J2,error).T   
            for j in range(num):
                x_value[x[j]]=x_value[x[j]]+delta[j,0]
            error=f.subs(x_value)
            print i,error
    except:
        pass
    return x_value,error



def LM(f,x_value,maxIter):
    num=len(x_value.keys())
    x=handle(num)
    #求逆运算的问题
    #last_value=f.subs(x_value)
    error=f.subs(x_value)
    lr=0.000001
    for i in range(maxIter):
        jacobian=Jacobian(f,x,x_value)  
        J1=dot(jacobian.T,jacobian)
        #print jacobian

        I=mat(zeros((len(J1),len(J1))))
        for q in range(len(J1)):
            I[q,q]=lr

        J1=J1+I
        J2=-1.0*dot(linalg.inv(J1),jacobian.T)
        delta=dot(J2,error).T

        for j in range(num):
            x_value[x[j]]=x_value[x[j]]+delta[j,0]
        if(f.subs(x_value)>=error):
            lr=lr*5
        else:
            lr=0.000001
        error=f.subs(x_value)
        print i,error
    return x_value,error




x=handle(2)
# sin cos need  like : sympy.sin()
f=(3-x[0])**2+(7-x[1])**2

x_value={x[0]:-1.5,x[1]:0.5};
maxIter=100

lis1=Jacobian(f,x,x_value)
#print lis1

lis2=Hessen(f,x,x_value)
#print lis2

#限制因素 非奇异矩阵
#Newton(f,x_value,100)

#GaussNewton(f,x_value,100)

#LM(f,x_value,100)



















  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值