最优化 - 牛顿优化算法

本人总结的常用优化算法PDF版本,主要讲解原理:http://download.csdn.net/detail/zk_j1994/9880349

主要包括梯度下降,共轭梯度法;牛顿法,拟牛顿法;信赖域方法,罚函数法。

# -*- coding: utf-8 -*-
"""
author: UniqueZ_
file:   牛顿法, 基于DFP的拟牛顿法
date:   2017-06-24
remark: 原方程为(x1)**2 + 2*(x2)**2
"""
import numpy as np
import matplotlib.pyplot as plt

class Newton_method:
    """ 使用的方向和牛顿方向有关的优化算法: 牛顿法 & 基于DFP的拟牛顿法 """
    def __init__(self, x0, gradient_threshold, method, H=None):
        """ 1. 初始化
        x0: 初始迭代点
        x: 当前迭代点
        gradient_threshold: 算法终止的梯度阈值
        H: 由梯度生成的矩阵, 取代牛顿法计算方向中的hessian矩阵; 
        method: "Newton" & "quasi_Newton_DFP" & "quasi_Newton_BFGS"
        """
        self.x = x0
        self.gradient_threshold = gradient_threshold
        self.method = method
        self.H = H
        
    def compute_original_fun(self, point):
        """ 2. 计算点point的函数值
        point: 一个点, 但不一定是当前的迭代点
        """
        value = point[0,0]**2 + 2*point[1,0]**2
        return value
        
    def compute_gradient(self):
        """ 3. 计算当前迭代点的梯度值 
        value:当前迭代点的梯度值,  一个矩阵
        """
        value = np.mat([[0],[0]], np.float)
        value[0,0] = 2*(self.x[0])
        value[1,0] = 2*(self.x[1])
        return value
    
    def compute_Hessian(self):
        """ 4. 计算当前迭代点的Hessian matrix """
        value = np.mat([[2, 0], [0, 4]], np.float)
        return value
    
    def is_termination(self):
        """ 5. 检验算法是否应该终止 """
        if np.linalg.norm(self.compute_gradient()) < self.gradient_threshold:
            return True
        else:
            return False
        
    def correct_algorithm(self, s, y):
        """ 6. 校正迭代矩阵: BFGS, DFP 
        s: 迭代点位移
        y: 梯度差
        H: 由梯度生成的矩阵, 取代牛顿法计算方向中的hessian矩阵
        """
        if self.method == "quasi_Newton_DFP":
            if s.T * y > 0:
                self.H = self.H - (self.H*y*y.T*self.H)/(y.T*self.H*y) + (s*s.T)/(s.T*y)
        elif self.method == "quasi_Newton_BFGS":
            if y.T*s > 0:
                self.H = self.H - (self.H*s*s.T*self.H)/(s.T*self.H*s) + (y*y.T)/(y.T*s)
        else:
            raise(Exception("No method founded."))
    
    def compute_direction(self):
        """ 7. 计算搜索方向 
        H: 由梯度生成的矩阵, 取代牛顿法计算方向中的hessian矩阵
        """
        if self.method == "Newton":
            value = -np.linalg.inv(self.compute_Hessian()) * self.compute_gradient()
        elif self.method in ["quasi_Newton_DFP", "quasi_Newton_BFGS"]:
            value = -self.H * self.compute_gradient()
        else:
            raise(Exception("No method founded."))
        return value
    
    def compute_step(self, alpha = 1, row = 1/4):
        """ 8. 计算步长 
        x: 当前迭代点, 一个行向量
        alpha: 初始步长, 返回步长, 步长迭代过程中每次缩短1/2, 最多迭代20次, alpha变为初始alpha的百万分之一
        row: 确定步长简单搜索法的一个参数
        """
        gradient = self.compute_gradient()
        direction = - gradient
        max_iter = 20
        for i in range(max_iter):
            if self.compute_original_fun(self.x + alpha*direction) <= self.compute_original_fun(self.x) + alpha*row*gradient.T*direction:
                break
            alpha = 1/3 * alpha
            if alpha < 0.1:
                alpha = 0.1
            if i == max_iter - 1:
                print("No valid step founded.")
        return alpha
    
    def compute_next_point(self, alpha, direction):
        """ 9. 计算下一个迭代点 """
        self.x = self.x + alpha * direction
        
    def draw_result(self, point):
        """ 10. 画出迭代点的变化过程 """
        plt.figure()
        plt.plot(range(len(point)), point, "y")
        plt.title("min value's change")
        return plt
        
    
    def main(self, iter_point, max_iter=1000):
        """ main
        method: 梯度优化算法方面的方法: gradient(梯度下降) & CG(共轭梯度法)
        max_iter: 最大迭代次数
        x_last: 上一个迭代点
        g_last: 上一个迭代点的梯度
        x: 最优解
        """
        iter_point.append(np.linalg.norm(self.x))
        for i in range(max_iter):
            # 算法是否终止
            if self.is_termination():
                break
                
            # 计算方向direction
            direction = self.compute_direction()

            # 计算步长alpha
            alpha = self.compute_step()
            
            # 计算下一个迭代点x
            x_last = self.x.copy()
            g_last = self.compute_gradient().copy()
            self.compute_next_point(alpha, direction)
            
            # 校正迭代矩阵
            if self.method in ["quasi_Newton_BFGS", "quasi_Newton_DFP"]:
                self.correct_algorithm(self.x - x_last, self.compute_gradient() - g_last)
            iter_point.append(np.linalg.norm(self.x))
        return iter_point
        
    
if __name__ == "__main__":
    # init
    params = {"x0": np.mat([[1],[1]]), "gradient_threshold": 1e-6, 
              "method": "quasi_Newton_DFP", "H": np.mat([[1,0],[0,1]], np.float)}
    Newton = Newton_method(**params)
    
    # computing
    iter_point = []
    iter_point = optimal_point = Newton.main(iter_point, max_iter=100)
    
    # draw
    Newton.draw_result(iter_point).show()


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
最优化是指在一定的约束条件下,寻找一个使目标函数取得最大值或最小值的过程。梯度下降法和牛顿法都是最优化问题中常用的方法。梯度下降法是一种迭代优化算法,通过计算目标函数的梯度来不断更新参数的值,直到达到某个停止条件。梯度下降法的思想是沿着目标函数梯度的反方向进行参数调整,以逐步接近最优解。它适用于凸函数和可微函数,并且可以用于求解无约束优化问题和约束优化问题的局部最优解。 牛顿法也是一种迭代优化算法,它利用函数的二阶导数信息(Hessian矩阵)来逼近函数的局部性质,从而更快地收敛到最优解。牛顿法在求解方程根或函数的最小值时非常有效。它经常被用于数学建模、机器学习、数据分析等领域中的参数优化问题,比如最小二乘法、逻辑回归、神经网络等模型的参数优化。 需要注意的是,梯度下降法和牛顿法在不同情况下的效果可能会有所不同。梯度下降法在参数空间中沿着梯度方向逐步搜索最优解,对于大规模数据集和高维参数空间比较适用。而牛顿法利用了更多的二阶导数信息,对于曲率较大的函数,在局部区域更容易找到最优解。但是牛顿法在计算复杂度和存储空间上可能会有一定的挑战。因此,在实际应用中,我们需要根据具体问题的特点选择合适的优化方法。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值