共轭梯度下降(logistic ) _机器学习

前言:

        前面讲过牛顿迭代法,当维度非常高的时候,求解Hessian 矩阵的逆矩阵计算量太复杂。

这里介绍一种更简单的求解方法,共轭梯度法

 

目录:

  1.     共轭简介
  2.      算法流程
  3.      参数推导过程
  4.      例子

一 : 共轭性质

          1.1 共轭说明

                A是n*n 的对称正定矩阵, 任意两个非零向量d_i,d_j,若

                d_i^TAd_j=0i \neq j , i,j=1,2...,k

                则这组方向关于A共轭

 

           1.2 几何意义,极小点:

                  设有二次函数

                  f(x)=(x-x^{-})A(x-x^{-})

               其中,x^{-} 是定点,函数的等值面为

                \frac{1}{2}(x-x^{-})A(x-x^{-}) = C

             是以x^{-} 为中心的椭圆面

          

           因为

           \triangledown f(x)=A(x-x^{-}) 

           \triangledown ^2 f(x) = A>0

          所以  x^{-} 是极小点

 

      1.3  几何解释

       

        x_0 是等值面一个点,沿着d_1 以最优步厂搜索得到点x_1

         d_1 是点x_1所在等值面的切向量,该点的法向量为

         \triangledown f(x_1)=A(x_1-x^{-})

        则d_1 与 \triangledown f(x_1) 正交,令d_2= x^{-}-x_1

       所以

       d_1^TAd_2=0

       即等值面的切向量和该点指向的极小点的向量关于A共轭

  

二 : 算法流程

        k = 0: 随机变量x_0

         g_0=\bigtriangledown f(x_0)

         if  0==g_0:

                停止

         else

               d_0 = -g_0

 

          for 

                      \lambda_k=-\frac{g_k^Td_k}{d_K^TAd_k}

                       x_{k+1}=x_k+\lambda_kd_k

                        g_{k+1}=\bigtriangledown f(x_{k+1})

                        if  0==g_{k+1}

                                   return

                        b_k=\frac{g_{k+1}^{T}Ad_k}{d_k^TAd_k}

                        d_{k+1}=-g_{k+1}+b_kd_k

                        k =k+1

                         x_{k}=x_{k+1}; g_{k}=g_{k+1};d_{k}=d_{k+1}

   

三    推导过程:

    1: 求出下一个搜索方向

      假设当前点x_{k+1}\triangledown f(x_{k+1}) \neq 0,

        令g_{k+1} =\triangledown f(x_{k+1}),  设下一个点搜索方向为 d_{k+1}= -g_{k+1}+b_kd_k

       因为 

        d_k^TAd_{k+1}=0 

       所以

       d_k^TAg_{k+1}=b_kd_k^TA d_k

     b_k=\frac{d_k^TAg_{k+1}}{d_k^TAd_k}

               

    2: 求出最佳搜索步伐

             x_{k+1}=x_k +\lambda_k d_k

            求解目标:

                     \lambda_k

             对\lambda_k 求导:

               f'(\lambda)=[A(x_k+\lambda_kd_k)+b]^Td_k=0

              因为

              g_k= \triangledown f(x_k)

                   =Ax_k+b

              所以

             f'(\lambda)=[g_k+A\lambda_kd_k]^Td_k=0

                 \lambda_k = -\frac{g_k^Td_k}{d_k^T A d_k}

   

四:  例子

  损失函数为:    f(x)=2x_1^2+x_2^2

 

           =\frac{1}{2} [x_1,x_2] \begin{bmatrix} 4 & 0 \\ 0 & 2 \end{bmatrix}[x_1, x_2]^T

         其中 A= \begin{bmatrix} 4 & 0\\ 0& 2 \end{bmatrix}

          

# -*- coding: utf-8 -*-
"""
Created on Tue Nov  5 10:11:12 2019

@author: chengxf2
"""
##共轭梯度下降
import numpy as np
from mpl_toolkits.mplot3d import Axes3D 
import matplotlib.pyplot as plt


class PRP() :
    
    
    def Draw(self):
        
        fig = plt.figure()
        ax = fig.add_subplot(111, projection='3d')
        
        
        
        x = np.arange(-5,5,0.5)
        y = np.arange(-5,5,0.5)
        
        X,Y = np.meshgrid(x,y)
        Z = 2*np.power(X,2)+np.power(Y,2)
        
      
        
        
        ax.plot_surface(X,Y,Z, rstride=1, cstride=1, cmap='cool')
        
        plt.show()
        
        
    
    def GetGradient(self, x):
        
        F = np.mat([[4,2]]).T
        
        grd = np.multiply(F, x)
        
        #print("\n grd :\n ",grd)
        return grd
        
        
    
    """
    加载数据集
    Args
       None
    return
       None
    """
    def LoadData(self):
        
        matA = np.mat([[4,0],
                       [0,2]])
    
        self.A = matA
        
        #print("\n self.A :\n",self.A)
    
    
    def __init__(self):
        
        
        self.LoadData()
        self.Draw()
        self.zero = 1e-6
        
    """
    获得lamb
    Args
        gk: 梯度
        dk: 方向
    """
    def  Getlamb(self, gk, dk):
        
         a= gk.T*dk
         b = dk.T*self.A*dk
         
         lamb = a/b
         
         return -lamb[0,0]
     
    
    """
    计算系数bk
    Args
       gk_1: 下一个点梯度
       dk_1:前一个点方向
    return
       b
    """
    def GetBk(self, gk_1, dk):
        
        a= gk_1.T*self.A*dk
        b = dk.T*self.A*dk
        
        c= a/b
        
        return c[0,0]
    
        
    
    
    def Train(self):
        k = 0
        
        xk = np.mat([[2,2]]).T
        
        gk= self.GetGradient(xk) ##初始梯度
        
        if np.linalg.norm(gk)<self.zero:
            return xk
        else:
            dk = -gk  ## 初始点方向
            
        
        while(1) :
           lamb = self.Getlamb(gk,dk)
           
           xk_1=xk+lamb*dk
           print("\n xk_1:  \t ",xk_1.T, "\t: lamb ",lamb)
           
           gk_1 =self.GetGradient(xk_1)
           
           
           if np.linalg.norm(gk_1)<self.zero:
               return xk_1
           
           bk = self.GetBk(gk_1,dk)
           dk_1 = -gk_1+bk*dk
           #print("\n bk: ",bk, "\t dk_1 ",dk_1)
           
           
           k=k+1
           print("\n    迭代次数 k:   \t ",k)
           xk = xk_1  
           gk = gk_1
           dk = dk_1
           print("\n xk:\t",xk,"\t gk :\t ",gk, "\t dk ",dk)
           
               
          
         


rp = PRP()
#rp.Train()
    
    
    

参考文档

   https://wenku.baidu.com/view/891db73ea88271fe910ef12d2af90242a895ab3f.html

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值