python实现共轭梯度法


Posted in Python onJuly 03, 2019

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

算法步骤:

python实现共轭梯度法

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是试验的部分,在本段程序中不起作用。

迭代轨迹:

python实现共轭梯度法

python实现共轭梯度法

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

最优化方法 最速下降法 共轭梯度法 牛顿法
迭代次数 1702 240 5

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

Python 相关文章推荐
python使用rabbitmq实现网络爬虫示例
Feb 20 Python
在Python3中初学者应会的一些基本的提升效率的小技巧
Mar 31 Python
python简单获取本机计算机名和IP地址的方法
Jun 03 Python
基于Python 的进程管理工具supervisor使用指南
Sep 18 Python
Python编程实现删除VC临时文件及Debug目录的方法
Mar 22 Python
Flask实现跨域请求的处理方法
Sep 27 Python
在Django中URL正则表达式匹配的方法
Dec 20 Python
linux查找当前python解释器的位置方法
Feb 20 Python
django多对多表的创建,级联删除及手动创建第三张表
Jul 25 Python
解决pycharm中opencv-python导入cv2后无法自动补全的问题(不用作任何文件上的修改)
Mar 05 Python
python爬虫中url管理器去重操作实例
Nov 30 Python
Pytest之测试命名规则的使用
Apr 16 Python
python实现微信自动回复及批量添加好友功能
Jul 03 #Python
Python 中Django安装和使用教程详解
Jul 03 #Python
利用python求积分的实例
Jul 03 #Python
python可视化爬虫界面之天气查询
Jul 03 #Python
python读写配置文件操作示例
Jul 03 #Python
Python正则表达式匹配数字和小数的方法
Jul 03 #Python
在python中利用numpy求解多项式以及多项式拟合的方法
Jul 03 #Python
You might like
针对PHP开发安全问题的相关总结
2019/03/22 PHP
php intval函数用法总结
2019/04/14 PHP
url参数中有+、空格、=、%、&amp;、#等特殊符号的问题解决
2013/05/15 Javascript
动态加载script文件的两种方法
2013/08/15 Javascript
javascript在子页面中函数无法调试问题解决方法
2014/01/17 Javascript
JavaScript声明变量名的语法规则
2015/07/10 Javascript
基于JavaScript实现仿京东图片轮播效果
2015/11/06 Javascript
纯javascript响应式树形菜单效果
2015/11/10 Javascript
总结JavaScript的正则与其他语言的不同之处
2016/08/25 Javascript
js document.getElementsByClassName的使用介绍与自定义函数
2016/11/25 Javascript
微信小程序 开发经验整理
2017/02/15 Javascript
webpack打包后直接访问页面图片路径错误的解决方法
2017/06/17 Javascript
Angular.js ng-file-upload结合springMVC的使用教程
2017/07/10 Javascript
使用react实现手机号的数据同步显示功能的示例代码
2018/04/03 Javascript
解决vue的 v-for 循环中图片加载路径问题
2018/09/03 Javascript
详解webpack模块加载器兼打包工具
2018/09/11 Javascript
JavaScript判断对象和数组的两种方法
2019/05/31 Javascript
Vue3 中的数据侦测的实现
2019/10/09 Javascript
js实现一款简单踩白块小游戏(曾经很火)
2019/12/02 Javascript
Vue替代marquee标签超出宽度文字横向滚动效果
2019/12/09 Javascript
Node.js中文件系统fs模块的使用及常用接口
2020/03/06 Javascript
python 查找文件夹下所有文件 实现代码
2009/07/01 Python
Python中字符串的处理技巧分享
2016/09/17 Python
python实现手机通讯录搜索功能
2018/02/22 Python
Python3导入CSV文件的实例(跟Python2有些许的不同)
2018/06/22 Python
浅谈Django的缓存机制
2018/08/23 Python
Python 支付整合开发包的实现
2019/01/23 Python
Django自定义列表 models字段显示方式
2020/04/03 Python
俄罗斯有趣和原创礼物网上商店:MagicMag
2019/08/01 全球购物
Java基础面试题
2014/07/19 面试题
成教自我鉴定
2013/10/27 职场文书
有创意的广告词
2014/03/18 职场文书
基层党员群众路线整改措施及努力方向
2014/10/28 职场文书
2014年体检中心工作总结
2014/12/23 职场文书
生活小常识广播稿
2015/08/19 职场文书
Android使用EventBus发送消息,Fragment中接收消息的方法会执行多次
2022/04/24 Java/Android