您的位置:首页 > 其它

优化算法——牛顿法(Newton Method)

2016-06-07 16:33 183 查看
转载:http://blog.csdn.net/google19890102/article/details/41087931

一、牛顿法概述

    除了前面说的梯度下降法,牛顿法也是机器学习中用的比较多的一种优化算法。牛顿法的基本思想是利用迭代点

处的一阶导数(梯度)和二阶导数(Hessen矩阵)对目标函数进行二次函数近似,然后把二次模型的极小点作为新的迭代点,并不断重复这一过程,直至求得满足精度的近似极小值。牛顿法的速度相当快,而且能高度逼近最优值。牛顿法分为基本的牛顿法和全局牛顿法。

二、基本牛顿法

1、基本牛顿法的原理

    基本牛顿法是一种是用导数的算法,它每一步的迭代方向都是沿着当前点函数值下降的方向。
    我们主要集中讨论在一维的情形,对于一个需要求解的优化函数

,求函数的极值的问题可以转化为求导函数

。对函数

进行泰勒展开到二阶,得到



对上式求导并令其为0,则为



即得到



这就是牛顿法的更新公式。

2、基本牛顿法的流程

给定终止误差值

,初始点

,令


计算

,若

,则停止,输出


计算

,并求解线性方程组得解








,并转2。

三、全局牛顿法

    牛顿法最突出的优点是收敛速度快,具有局部二阶收敛性,但是,基本牛顿法初始点需要足够“靠近”极小点,否则,有可能导致算法不收敛。这样就引入了全局牛顿法。

1、全局牛顿法的流程

给定终止误差值





,初始点

,令


计算

,若

,则停止,输出


计算

,并求解线性方程组得解






是不满足下列不等式的最小非负整数










,并转2。

2、Armijo搜索

    全局牛顿法是基于Armijo的搜索,满足Armijo准则:
给定



,令步长因子

,其中

是满足下列不等式的最小非负整数:



四、算法实现

    实验部分使用Java实现,需要优化的函数

,最小值为



1、基本牛顿法Java实现

package org.algorithm.newtonmethod;

/**
* Newton法
*
* @author dell
*
*/
public class NewtonMethod {
private double originalX;// 初始点
private double e;// 误差阈值
private double maxCycle;// 最大循环次数

/**
* 构造方法
*
* @param originalX初始值
* @param e误差阈值
* @param maxCycle最大循环次数
*/
public NewtonMethod(double originalX, double e, double maxCycle) {
this.setOriginalX(originalX);
this.setE(e);
this.setMaxCycle(maxCycle);
}

// 一系列get和set方法
public double getOriginalX() {
return originalX;
}

public void setOriginalX(double originalX) {
this.originalX = originalX;
}

public double getE() {
return e;
}

public void setE(double e) {
this.e = e;
}

public double getMaxCycle() {
return maxCycle;
}

public void setMaxCycle(double maxCycle) {
this.maxCycle = maxCycle;
}

/**
* 原始函数
*
* @param x变量
* @return 原始函数的值
*/
public double getOriginal(double x) {
return x * x - 3 * x + 2;
}

/**
* 一次导函数
*
* @param x变量
* @return 一次导函数的值
*/
public double getOneDerivative(double x) {
return 2 * x - 3;
}

/**
* 二次导函数
*
* @param x变量
* @return 二次导函数的值
*/
public double getTwoDerivative(double x) {
return 2;
}

/**
* 利用牛顿法求解
*
* @return
*/
public double getNewtonMin() {
double x = this.getOriginalX();
double y = 0;
double k = 1;
// 更新公式
while (k <= this.getMaxCycle()) {
y = this.getOriginal(x);
double one = this.getOneDerivative(x);
if (Math.abs(one) <= e) {
break;
}
double two = this.getTwoDerivative(x);
x = x - one / two;
k++;
}
return y;
}

}


2、全局牛顿法Java实现

package org.algorithm.newtonmethod;

/**
* 全局牛顿法
*
* @author dell
*
*/
public class GlobalNewtonMethod {
private double originalX;
private double delta;
private double sigma;
private double e;
private double maxCycle;

public GlobalNewtonMethod(double originalX, double delta, double sigma,
double e, double maxCycle) {
this.setOriginalX(originalX);
this.setDelta(delta);
this.setSigma(sigma);
this.setE(e);
this.setMaxCycle(maxCycle);
}

public double getOriginalX() {
return originalX;
}

public void setOriginalX(double originalX) {
this.originalX = originalX;
}

public double getDelta() {
return delta;
}

public void setDelta(double delta) {
this.delta = delta;
}

public double getSigma() {
return sigma;
}

public void setSigma(double sigma) {
this.sigma = sigma;
}

public double getE() {
return e;
}

public void setE(double e) {
this.e = e;
}

public double getMaxCycle() {
return maxCycle;
}

public void setMaxCycle(double maxCycle) {
this.maxCycle = maxCycle;
}

/**
* 原始函数
*
* @param x变量
* @return 原始函数的值
*/
public double getOriginal(double x) {
return x * x - 3 * x + 2;
}

/**
* 一次导函数
*
* @param x变量
* @return 一次导函数的值
*/
public double getOneDerivative(double x) {
return 2 * x - 3;
}

/**
* 二次导函数
*
* @param x变量
* @return 二次导函数的值
*/
public double getTwoDerivative(double x) {
return 2;
}

/**
* 利用牛顿法求解
*
* @return
*/
public double getGlobalNewtonMin() {
double x = this.getOriginalX();
double y = 0;
double k = 1;
// 更新公式
while (k <= this.getMaxCycle()) {
y = this.getOriginal(x);
double one = this.getOneDerivative(x);
if (Math.abs(one) <= e) {
break;
}
double two = this.getTwoDerivative(x);
double dk = -one / two;// 搜索的方向
double m = 0;
double mk = 0;
while (m < 20) {
double left = this.getOriginal(x + Math.pow(this.getDelta(), m)
* dk);
double right = this.getOriginal(x) + this.getSigma()
* Math.pow(this.getDelta(), m)
* this.getOneDerivative(x) * dk;
if (left <= right) {
mk = m;
break;
}
m++;
}
x = x + Math.pow(this.getDelta(), mk)*dk;
k++;
}
return y;
}
}


3、主函数

package org.algorithm.newtonmethod;

/**
* 测试函数
* @author dell
*
*/
public class TestNewton {
public static void main(String args[]) {
NewtonMethod newton = new NewtonMethod(0, 0.00001, 100);
System.out.println("基本牛顿法求解:" + newton.getNewtonMin());

GlobalNewtonMethod gNewton = new GlobalNewtonMethod(0, 0.55, 0.4,
0.00001, 100);
System.out.println("全局牛顿法求解:" + gNewton.getGlobalNewtonMin());
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: