python实现的共轭梯度法

共轭梯度法是介于最速下降法与牛顿法之间的一个方法,它仅需利用一阶导数信息,但克服了最速下降法收敛慢的缺点,又避免了牛顿法需要存储和计算Hesse矩阵并求逆的缺点,共轭梯度法不仅是解决大型线性方程组最有用的方法之一,也是解大型非线性最优化最有效的算法之一。 在各种优化算法中,共轭梯度法是非常重要的一种。其优点是所需存储量小,具有步收敛性,稳定性高,而且不需要任何外来参数。

算法步骤:

import random
import numpy as np
import matplotlib.pyplot as plt

def goldsteinsearch(f,df,d,x,alpham,rho,t):
  '''
  线性搜索子函数
  数f,导数df,当前迭代点x和当前搜索方向d,t试探系数>1,
  '''
  flag = 0

  a = 0
  b = alpham
  fk = f(x)
  gk = df(x)

  phi0 = fk
  dphi0 = np.dot(gk, d)
  alpha=b*random.uniform(0,1)

  while(flag==0):
    newfk = f(x + alpha * d)
    phi = newfk
    # print(phi,phi0,rho,alpha ,dphi0)
    if (phi - phi0 )<= (rho * alpha * dphi0):
      if (phi - phi0) >= ((1 - rho) * alpha * dphi0):
        flag = 1
      else:
        a = alpha
        b = b
        if (b < alpham):
          alpha = (a + b) / 2
        else:
          alpha = t * alpha
    else:
      a = a
      b = alpha
      alpha = (a + b) / 2
  return alpha

def Wolfesearch(f,df,d,x,alpham,rho,t):
  '''
  线性搜索子函数
  数f,导数df,当前迭代点x和当前搜索方向d
  σ∈(ρ,1)=0.75
  '''
  sigma=0.75

  flag = 0

  a = 0
  b = alpham
  fk = f(x)
  gk = df(x)

  phi0 = fk
  dphi0 = np.dot(gk, d)
  alpha=b*random.uniform(0,1)

  while(flag==0):
    newfk = f(x + alpha * d)
    phi = newfk
    # print(phi,phi0,rho,alpha ,dphi0)
    if (phi - phi0 )<= (rho * alpha * dphi0):
      # if abs(np.dot(df(x + alpha * d),d))<=-sigma*dphi0:
      if (phi - phi0) >= ((1 - rho) * alpha * dphi0):
        flag = 1
      else:
        a = alpha
        b = b
        if (b < alpham):
          alpha = (a + b) / 2
        else:
          alpha = t * alpha
    else:
      a = a
      b = alpha
      alpha = (a + b) / 2
  return alpha

def frcg(fun,gfun,x0):

  # x0是初始点,fun和gfun分别是目标函数和梯度
  # x,val分别是近似最优点和最优值,k是迭代次数
  # dk是搜索方向,gk是梯度方向
  # epsilon是预设精度,np.linalg.norm(gk)求取向量的二范数
  maxk = 5000
  rho = 0.6
  sigma = 0.4
  k = 0
  epsilon = 1e-5
  n = np.shape(x0)[0]
  itern = 0
  W = np.zeros((2, 20000))

  f = open("共轭.txt", 'w')

  while k < maxk:
      W[:, k] = x0
      gk = gfun(x0)
      itern += 1
      itern %= n
      if itern == 1:
        dk = -gk
      else:
        beta = 1.0 * np.dot(gk, gk) / np.dot(g0, g0)
        dk = -gk + beta * d0
        gd = np.dot(gk, dk)
        if gd >= 0.0:
          dk = -gk
      if np.linalg.norm(gk) < epsilon:
        break

      alpha=goldsteinsearch(fun,gfun,dk,x0,1,0.1,2)
      # alpha=Wolfesearch(fun,gfun,dk,x0,1,0.1,2)
      x0+=alpha*dk

      f.write(str(k)+'  '+str(np.linalg.norm(gk))+"\n")
      print(k,alpha)
      g0 = gk
      d0 = dk
      k += 1

  W = W[:, 0:k+1] # 记录迭代点
  return [x0, fun(x0), k,W]

def fun(x):
  return 100 * (x[1] - x[0] ** 2) ** 2 + (1 - x[0]) ** 2
def gfun(x):
  return np.array([-400 * x[0] * (x[1] - x[0] ** 2) - 2 * (1 - x[0]), 200 * (x[1] - x[0] ** 2)])

if __name__=="__main__":
  X1 = np.arange(-1.5, 1.5 + 0.05, 0.05)
  X2 = np.arange(-3.5, 4 + 0.05, 0.05)
  [x1, x2] = np.meshgrid(X1, X2)
  f = 100 * (x2 - x1 ** 2) ** 2 + (1 - x1) ** 2 # 给定的函数
  plt.contour(x1, x2, f, 20) # 画出函数的20条轮廓线

  x0 = np.array([-1.2, 1])
  x=frcg(fun,gfun,x0)
  print(x[0],x[2])
  # [1.00318532 1.00639618]
  W=x[3]
  # print(W[:, :])
  plt.plot(W[0, :], W[1, :], 'g*-') # 画出迭代点收敛的轨迹
  plt.show()

代码中求最优步长用得是goldsteinsearch方法,另外的Wolfesearch是试验的部分,在本段程序中不起作用。

迭代轨迹:

三种最优化方法的迭代次数对比:


最优化方法


最速下降法


共轭梯度法


牛顿法


迭代次数


1702


240


5

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 梯度下降法介绍及利用Python实现的方法示例

    本文主要给大家介绍了梯度下降法及利用Python实现的相关内容,分享出来供大家参考学习,下面话不多说,来一起看看详细的介绍吧. 梯度下降法介绍 梯度下降法(gradient descent),又名最速下降法(steepest descent)是求解无约束最优化问题最常用的方法,它是一种迭代方法,每一步主要的操作是求解目标函数的梯度向量,将当前位置的负梯度方向作为搜索方向(因为在该方向上目标函数下降最快,这也是最速下降法名称的由来). 梯度下降法特点:越接近目标值,步长越小,下降速度越慢. 直观上

  • python实现随机梯度下降法

    看这篇文章前强烈建议你看看上一篇python实现梯度下降法: 一.为什么要提出随机梯度下降算法 注意看梯度下降法权值的更新方式(推导过程在上一篇文章中有) 也就是说每次更新权值都需要遍历整个数据集(注意那个求和符号),当数据量小的时候,我们还能够接受这种算法,一旦数据量过大,那么使用该方法会使得收敛过程极度缓慢,并且当存在多个局部极小值时,无法保证搜索到全局最优解.为了解决这样的问题,引入了梯度下降法的进阶形式:随机梯度下降法. 二.核心思想 对于权值的更新不再通过遍历全部的数据集,而是选择其中

  • python梯度下降法的简单示例

    梯度下降法的原理和公式这里不讲,就是一个直观的.易于理解的简单例子. 1.最简单的情况,样本只有一个变量,即简单的(x,y).多变量的则可为使用体重或身高判断男女(这是假设,并不严谨),则变量有两个,一个是体重,一个是身高,则可表示为(x1,x2,y),即一个目标值有两个属性. 2.单个变量的情况最简单的就是,函数hk(x)=k*x这条直线(注意:这里k也是变化的,我们的目的就是求一个最优的   k).而深度学习中,我们是不知道函数的,也就是不知道上述的k.   这里讨论单变量的情况: 在不知道

  • python+numpy+matplotalib实现梯度下降法

    这个阶段一直在做和梯度一类算法相关的东西,索性在这儿做个汇总, 一.算法论述 梯度下降法(gradient  descent)别名最速下降法(曾经我以为这是两个不同的算法-.-),是用来求解无约束最优化问题的一种常用算法.下面以求解线性回归为题来叙述: 设:一般的线性回归方程(拟合函数)为:(其中的值为1) 则这一组向量参数选择的好与坏就需要一个机制来评估,据此我们提出了其损失函数为(选择均方误差): 我们现在的目的就是使得损失函数取得最小值,即目标函数为: 如果的值取到了0,意味着我们构造出了

  • 基于随机梯度下降的矩阵分解推荐算法(python)

    SVD是矩阵分解常用的方法,其原理为:矩阵M可以写成矩阵A.B与C相乘得到,而B可以与A或者C合并,就变成了两个元素M1与M2的矩阵相乘可以得到M. 矩阵分解推荐的思想就是基于此,将每个user和item的内在feature构成的矩阵分别表示为M1与M2,则内在feature的乘积得到M:因此我们可以利用已有数据(user对item的打分)通过随机梯度下降的方法计算出现有user和item最可能的feature对应到的M1与M2(相当于得到每个user和每个item的内在属性),这样就可以得到通

  • Python编程实现线性回归和批量梯度下降法代码实例

    通过学习斯坦福公开课的线性规划和梯度下降,参考他人代码自己做了测试,写了个类以后有时间再去扩展,代码注释以后再加,作业好多: import numpy as np import matplotlib.pyplot as plt import random class dataMinning: datasets = [] labelsets = [] addressD = '' #Data folder addressL = '' #Label folder npDatasets = np.zer

  • python实现梯度下降算法

    梯度下降(Gradient Descent)算法是机器学习中使用非常广泛的优化算法.当前流行的机器学习库或者深度学习库都会包括梯度下降算法的不同变种实现. 本文主要以线性回归算法损失函数求极小值来说明如何使用梯度下降算法并给出python实现.若有不正确的地方,希望读者能指出. 梯度下降 梯度下降原理:将函数比作一座山,我们站在某个山坡上,往四周看,从哪个方向向下走一小步,能够下降的最快. 在线性回归算法中,损失函数为 在求极小值时,在数据量很小的时候,可以使用矩阵求逆的方式求最优的θ值.但当数

  • Python实现PS图像调整颜色梯度效果示例

    本文实例讲述了Python实现PS图像调整颜色梯度效果.分享给大家供大家参考,具体如下: 这里用 Python 实现 PS 中的色彩图,可以看到颜色的各种渐变,具体的效果可以参考附录说明 和之前的程序相比,这里利用矩阵的运算替代了 for 循环,提升了运行的效率. import numpy as np import matplotlib.pyplot as plt from skimage import io import numpy.matlib from skimage import img

  • Python语言描述随机梯度下降法

    1.梯度下降 1)什么是梯度下降? 因为梯度下降是一种思想,没有严格的定义,所以用一个比喻来解释什么是梯度下降. 简单来说,梯度下降就是从山顶找一条最短的路走到山脚最低的地方.但是因为选择方向的原因,我们找到的的最低点可能不是真正的最低点.如图所示,黑线标注的路线所指的方向并不是真正的地方. 既然是选择一个方向下山,那么这个方向怎么选?每次该怎么走? 先说选方向,在算法中是以随机方式给出的,这也是造成有时候走不到真正最低点的原因. 如果选定了方向,以后每走一步,都是选择最陡的方向,直到最低点.

  • python实现随机梯度下降(SGD)

    使用神经网络进行样本训练,要实现随机梯度下降算法.这里我根据麦子学院彭亮老师的讲解,总结如下,(神经网络的结构在另一篇博客中已经定义): def SGD(self, training_data, epochs, mini_batch_size, eta, test_data=None): if test_data: n_test = len(test_data)#有多少个测试集 n = len(training_data) for j in xrange(epochs): random.shuf

随机推荐