热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

python模块:Scipy.optimize.minimize规划问题求解

目录一、模块介绍二、模块源分析与参数解释三、实例求解四、参考

目录

一、模块介绍

二、模块源分析与参数解释

三、实例求解

四、参考


一、模块介绍

1.1模块功能

        Scipy.optimize是Scipy中一个用于解决数学模型中优化类模型的子包,该子包中又包含了多个子功能模块见下表,不同方法不同条件求解最优化模型。本节介绍minimize对一般规划问题的模型建立与求解。

问题类型模块
多元标量函数的有/无约束最小化minimize
最小二乘法最小化least_squares
单变量函数最小化器minimize_scalar
线性规划linprog

1.2模型介绍       

        多元标量函数的最小化,是数学规划模型中更为一般的模型,该模块包括有限制性约束和无限制性约束的最小化,而对于限制性约束又分为线性约束和非线性约束。这种更为一般的模型需要针对具体的问题假设选择特定的方法进行求解。

        在数学规划模型中,minimize提供的方法能够解决无/有(线性、非线性)约束的多个决策变量目标函数的最优化问题,但是由于该模块是依据函数导数与梯度进行求解,不能够求解整数规划、01规划等问题。

二、模块源分析与参数解释

2.1模块整体介绍

        对于整个多元标量的最小化问题,主要的api为optimize包下的minimize函数。该minimize函数的完整参数详情如下。同时,对于不同的method方法,函数的参数也会有相应的限制,这在具体的方法介绍中具体介绍。

minimize(fun, x0, args=(), method=None, jac=None, hess=None,
hessp=None, bounds=None, cOnstraints=(), tol=None,
callback=None, optiOns=None)

       该函数主要参数意义解释:

fun待求解的目标函数
x0初始猜测的数组
args目标函数带参数时需要指定
method选择的方法
jacjacobian矩阵或梯度函数(梯度求解的方法需要传入)
hesshessian矩阵
hessp黑塞向量积
bounds寻优范围
constraints限制约束
tol浮动,可以理解为单次寻找的步长上限,越小精度越高
callback回调函数
options选项字典,不同方法有不同选项

        完整的方法options可通过optimize的show_options方法访问

from scipy.optimize import show_options 

print(show_options(method='minimize')

        该模块提供求解方法字典如下,  通过optimize包导入minimize后,对minimize传入method参数指定方法。而对于不同方法的选用,便有不同的求解策略。我们选择部分主要方法介绍。

MINIMIZE_METHODS = ['nelder-mead', 'powell', 'cg', 'bfgs', 'newton-cg',
'l-bfgs-b', 'tnc', 'cobyla', 'slsqp', 'trust-constr',
'dogleg', 'trust-ncg', 'trust-exact', 'trust-krylov']

        无约束多元标量最小化选择以下4个方法:

  • nelder-mead 
  • powell
  • bfgs
  • newton-cg

        有约束多元标量最小化选择方法:

  • trust-constr

        对于更多的方法可以访问该文档查询:完整方法文档

2.2 各方法详细介绍

2.2.1 nelder-mead 

        方法完名称为Nelder-Mead Simplex algorithm Nelder-Mead单纯形法,该方法通过对可行域顶点不断迭代选出最优解。由于是迭代寻优策略,可以指定寻优范围。

该方法对应参数:

scipy.optimize.minimize(fun, x0, args=(), method='Nelder-Mead', bounds=None, tol=None, callback=None, optiOns={'func': None, 'maxiter': None, 'maxfev': None, 'disp': False, 'return_all': False, 'initial_simplex': None, 'xatol': 1e-5, 'fatol': 1e-5, 'adaptive': False})

特殊参数:

         bounds        该方法不要求函数连续,可指定寻优范围

特殊选项:

        xatol/fatol        解与函数值迭代之间绝对误差上限值,值越小求解越慢,精度越高

2.2.2 powell

        方法名称为鲍威尔算法,该方法通过共轭方向加速收敛,其它与单纯形法类似。

该方法对应参数:

scipy.optimize.minimize(fun, x0, args=(), method='Powell', bounds=None, tol=None, callback=None, optiOns={'func': None, 'xtol': 0.0001, 'ftol': 0.0001, 'maxiter': None, 'maxfev': None, 'disp': False, 'direc': None, 'return_all': False})

特殊参数:

         bounds        该方法不要求函数连续,可指定寻优范围

特殊选项:

        xatol/fatol        解与函数值迭代之间绝对误差上限值,值越小求解越慢,精度越高

2.2.3 bfgs

        方法名称为 BFGS(Broyden-Fletcher-Goldfarb-Shanno algorithm)拟牛顿法。算法利用梯度下降进行收敛,因此不可指定范围。该方法未传入梯度函数时通过第一次的差值估计。

该方法对应参数:

scipy.optimize.minimize(fun, x0, args=(), method='BFGS', jac=None, tol=None, callback=None, optiOns={'gtol': 1e-05, 'norm': inf, 'eps': 1.4901161193847656e-08, 'maxiter': None, 'disp': False, 'return_all': False, 'finite_diff_rel_step': None})

特殊参数:

         jac        梯度函数

特殊选项:

         gtol       梯度范数上限

        norm      范数浮动上限

        eps        求解浮动上限

2.2.4 newton-cg

        方法名称为NCG (Newton-Conjugate-Gradient algorithm)牛顿共轭梯度算法,该方法通过梯度函数,二阶导数的hessian矩阵形式将目标函数拟合为二次函数形式,通过该二次式梯度下降求解。

该方法对应参数:

scipy.optimize.minimize(fun, x0, args=(), method='Newton-CG', jac=None, hess=None, hessp=None, tol=None, callback=None, optiOns={'xtol': 1e-05, 'eps': 1. e-08, 'maxiter': None, 'disp': False, 'return_all': False})

特殊参数:

         jac        梯度函数

         hess         hessian矩阵

         hessp        hessian向量积(与hess只需要定义一个)

特殊选项:

         xtol        解的平均相对误差上限

        eps        求解浮动上限

2.2.5 trust-constr

        方法名称为Trust-Region Constrained Algorithm信赖域约束算法, 该方法需要用用约束模块定义线性和非线性约束。线性约束与linprog中约束定义类似,而非线性约束需要定义jacobian矩阵和hessian矩阵。

该方法对应参数:

scipy.optimize.minimize(fun, x0, args=(), method='trust-constr', hess=None, hessp=None, bounds=None, cOnstraints=(), tol=None, callback=None, optiOns={'grad': None, 'xtol': 1e-08, 'gtol': 1e-08, 'barrier_tol': 1e-08, 'sparse_jacobian': None, 'maxiter': 1000, 'verbose': 0, 'finite_diff_rel_step': None, 'initial_constr_penalty': 1.0, 'initial_tr_radius': 1.0, 'initial_barrier_parameter': 0.1, 'initial_barrier_tolerance': 0.1, 'factorization_method': None, 'disp': False})

特殊参数:

        bounds  变量定义域

         jac        梯度函数

         hess         hessian矩阵

         hessp        hessian向量积(与hess只需要定义一个)

        constraints        线性约束和非线性约束组成的约束列表

特殊选项:

        xatol/fatol   解与函数值迭代之间绝对误差上限值,值越小求解越慢,精度越高

三、实例求解

3.1 实例模型与知识补充

3.1.1Rosenbrock函数

        rosenbrock是一个常用于检测优化算法效果的函数Rosenbrock函数_百度百科 (baidu.com)。

该函数可以用以形式表示:

                                ​​​​​​​        f(X)=\sum_{i=1}^{N-1}100(x_{i+1}-x_{i}^{2} )^{2}+(1-x_{i})^{2}

         通过这两个矩阵可以将目标函数通过二次函数形式拟合。

对于数学部分了解以上部分即可,具体的数学解释可以参考:黑塞矩阵_百度百科 (baidu.com)

3.2 实例求解

3.2.1无约束多元标量最小化

        根据上面的介绍,我们以rosenbrock函数作为实例演示(下称rosen函数)。

        先定义rosen的目标函数,梯度函数和hessian矩阵以及一些假设变量如假定范围为bounds。设定x1,x2两组初始假设值用于比较初始值对求解的影响。

from scipy.optimize import minimize
import numpy as np
# 两组初始迭代值
x1=np.array([1,1.2,0.9,1.3,0.5])
x2=np.array([1,1.2,0.9,1.3,0.3])
# 以rosenbrock函数来评价优化方法
def rosen(x):
return sum(100*(x[1:]-x[:-1]**2.0)**2+(1-x[:-1])**2.0)
# 带参的rosen函数
def rosen_(x,a,b):
return sum(a*(x[1:]-x[:-1]**2.0)**2+(1-x[:-1])**2.0)+b
# rosen函数的梯度
def rosen_der(x):
xm = x[1:-1]
xm_m1 = x[:-2]
xm_p1 = x[2:]
der = np.zeros_like(x)
der[1:-1] = 200*(xm-xm_m1**2) - 400*(xm_p1 - xm**2)*xm - 2*(1-xm)
der[0] = -400*x[0]*(x[1]-x[0]**2) - 2*(1-x[0])
der[-1] = 200*(x[-1]-x[-2]**2)
return der
# rosen函数的hessian矩阵
def rosen_hess(x):
x = np.asarray(x)
H = np.diag(-400*x[:-1],1) - np.diag(400*x[:-1],-1)
diagOnal= np.zeros_like(x)
diagonal[0] = 1200*x[0]**2-400*x[1]+2
diagonal[-1] = 200
diagonal[1:-1] = 202 + 1200*x[1:-1]**2 - 400*x[2:]
H = H + np.diag(diagonal)
return H
# 限定寻优范围
bounds=np.array([[0,2],[0,2],[0,2],[0,2],[None,None]])

        各个方法的实现如下:

# nelder-mead单纯形方法 初始值依赖
res11=minimize(rosen_,x1,args=(100,1),method='nelder-mead',optiOns={'xatol': 1e-8, 'disp':True})
res12=minimize(rosen_,x1,args=(100,1),method='nelder-mead',optiOns={'xatol': 1e-8, 'disp':True})
print('========================')
print(res11)
print('========================')
print(res12)
# powell方法
res21=minimize(rosen_,x1,args=(100,1),method='powell',tol=1e-5,bounds=bounds,optiOns={'disp':True})
res22=minimize(rosen_,x2,args=(100,1),method='powell',bounds=bounds,optiOns={'disp':True})
# ftol和xtol分别为函数值与x解的相对误差上限
res21_=minimize(rosen_,x1,args=(100,1),method='powell',optiOns={'ftol':1e-8,'xtol':1e-8,'disp':True})
print('初始迭代值会对算法的收敛速度和精度产生影响========================')
print(res21.x)
print(res22.x)
print('对于精度过低,可以指定浮动上限值,通过增加代数提高算法精度========================')
print(res21_.x)
# bfgs拟牛顿方法 由于拟牛顿法采用梯度计算,不能够指定变量的寻优范围 gtol为梯度范数上限
res31=minimize(rosen,x1,method='bfgs',optiOns={'gtol':1e-8,'disp':True})
res32=minimize(rosen,x1,method='bfgs',jac=rosen_der,optiOns={'gtol':1e-8,'disp':True})
print('jac参数为函数梯度参数,若不指定,则通过差值估计,两者效果相差不大============')
print(res31)
print(res32)
# ncg 牛顿共轭梯度方法,先求解hessian矩阵得到二次函数拟合目标函数,再通过梯度下降求解最优
res41=minimize(rosen,x1,method='Newton-cg',jac=rosen_der,hess=rosen_hess,optiOns={'xtol':1e-8,'disp':True})
print(res41)

3.2.2 有约束的多元标量最小化

        我们选择二元标量的rosen函数,并添加约束,得到一个优化模型:

         ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        min 100(x_{1}-x_{0}^{2})^{2}+(1-x_{0})^{2}

                                                s.t.

        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​                \begin{cases} & \text{ } x_0+2x_1\leq 1 \\ & \text{ } x_0^2+x_1\leq 1 \\ & \text{ } x_0^2-x_1\leq 1 \\ & \text{ } 2x_0+x_1 = 1 \\ & \text{ } 0 \leq x_0 \leq 1 \\ & \text{ } -0.5 \leq x_1 \leq 2 \end{cases}

        按照下步骤建立模型并求解,其中线性约束部分与linprog模块类似,通过矩阵表示多个线性约束条件。而非线性约束需要定义对应的约束求解函数cons_f,jacobian矩阵函数和hessian矩阵的线性组合函数cons_J/cons_H.如下所示。两个约束需要通过LinearConstraint和NonlinearConstraint封装为对应的结构,并组合成列表形式作为constraints的参数。

# 有限制的最优化
# Trust-Region Constrained Algorithm信赖域约束算法
# 定义一个带有线性和非线性约束的优化函数
from scipy.optimize import Bounds,LinearConstraint,NonlinearConstraint
# bounds为定义域,参数分别为变量的下限和上限向量表示形式
bounds_t=Bounds([0, -0.5], [1.0, 2.0])
# 与linprog中定义线性约束相同,通过矩阵和向量表示参数
linear_cOnstraint=LinearConstraint([[1,2],[2,1]],[-np.inf,1],[1,1])
# 非线性约束需要jacobian矩阵和hessian矩阵辅助定义
# 返回非线性约束原函数
def cons_f(x):
return [x[0]**2 + x[1], x[0]**2 - x[1]]
# 对应返回jacboian矩阵
def cons_J(x):
return [[2*x[0], 1], [2*x[0], -1]]
# 返回hessian矩阵的线性组合形式
def cons_H(x,v):
return v[0]*np.array([[2, 0], [0, 0]]) + v[1]*np.array([[2, 0], [0, 0]])
from scipy.optimize import NonlinearConstraint
nonlinear_cOnstraint= NonlinearConstraint(cons_f, -np.inf, 1, jac=cons_J, hess=cons_H)
# 约束条件
x3=np.array([0.5,0])
res5=minimize(rosen, x3, method='trust-constr', jac=rosen_der,cOnstraints=[linear_constraint, nonlinear_constraint],hess=rosen_hess,optiOns={'verbose': 1}, bounds=bounds_t)
print(res5)

四、参考

[1] Scipy v1.9.0版用户指南 Optimization (scipy.optimize) — SciPy v1.9.0 Manual

[2] osego 指南 优化与寻根 (scipy.optimize ) — SciPy v1.8.0.dev0+1869.838cfbe Manual (osgeo.cn)


推荐阅读
  • Python脚本编写创建输出数据库并添加模型和场数据的方法
    本文介绍了使用Python脚本编写创建输出数据库并添加模型数据和场数据的方法。首先导入相应模块,然后创建输出数据库并添加材料属性、截面、部件实例、分析步和帧、节点和单元等对象。接着向输出数据库中添加场数据和历程数据,本例中只添加了节点位移。最后保存数据库文件并关闭文件。文章还提供了部分代码和Abaqus操作步骤。另外,作者还建立了关于Abaqus的学习交流群,欢迎加入并提问。 ... [详细]
  • 解决Cydia数据库错误:could not open file /var/lib/dpkg/status 的方法
    本文介绍了解决iOS系统中Cydia数据库错误的方法。通过使用苹果电脑上的Impactor工具和NewTerm软件,以及ifunbox工具和终端命令,可以解决该问题。具体步骤包括下载所需工具、连接手机到电脑、安装NewTerm、下载ifunbox并注册Dropbox账号、下载并解压lib.zip文件、将lib文件夹拖入Books文件夹中,并将lib文件夹拷贝到/var/目录下。以上方法适用于已经越狱且出现Cydia数据库错误的iPhone手机。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 开发笔记:图像识别基于主成分分析算法实现人脸二维码识别
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了图像识别基于主成分分析算法实现人脸二维码识别相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • “你永远都不知道明天和‘公司的意外’哪个先来。”疫情期间,这是我们最战战兢兢的心情。但是显然,有些人体会不了。这份行业数据,让笔者“柠檬” ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • Oracle分析函数first_value()和last_value()的用法及原理
    本文介绍了Oracle分析函数first_value()和last_value()的用法和原理,以及在查询销售记录日期和部门中的应用。通过示例和解释,详细说明了first_value()和last_value()的功能和不同之处。同时,对于last_value()的结果出现不一样的情况进行了解释,并提供了理解last_value()默认统计范围的方法。该文对于使用Oracle分析函数的开发人员和数据库管理员具有参考价值。 ... [详细]
  • 利用Visual Basic开发SAP接口程序初探的方法与原理
    本文介绍了利用Visual Basic开发SAP接口程序的方法与原理,以及SAP R/3系统的特点和二次开发平台ABAP的使用。通过程序接口自动读取SAP R/3的数据表或视图,在外部进行处理和利用水晶报表等工具生成符合中国人习惯的报表样式。具体介绍了RFC调用的原理和模型,并强调本文主要不讨论SAP R/3函数的开发,而是针对使用SAP的公司的非ABAP开发人员提供了初步的接口程序开发指导。 ... [详细]
  • SLAM中相机运动估计的基本问题及解决方案
    本文讨论了SLAM中相机运动估计的基本问题,指出了解决方案的存在。作者认为阅读相关SLAM书籍是掌握基础原理的有效途径,而不是仅仅依赖现成的解决方案。同时,作者也提到了激光雷达和特征点匹配等技术在SLAM中的应用,并建议读者深入理解相关原理,而不是盲目追求现成的代码。 ... [详细]
  • 预备知识可参考我整理的博客Windows编程之线程:https:www.cnblogs.comZhuSenlinp16662075.htmlWindows编程之线程同步:https ... [详细]
  • 树莓派语音控制的配置方法和步骤
    本文介绍了在树莓派上实现语音控制的配置方法和步骤。首先感谢博主Eoman的帮助,文章参考了他的内容。树莓派的配置需要通过sudo raspi-config进行,然后使用Eoman的控制方法,即安装wiringPi库并编写控制引脚的脚本。具体的安装步骤和脚本编写方法在文章中详细介绍。 ... [详细]
  • 本文由编程笔记#小编整理,主要介绍了关于数论相关的知识,包括数论的算法和百度百科的链接。文章还介绍了欧几里得算法、辗转相除法、gcd、lcm和扩展欧几里得算法的使用方法。此外,文章还提到了数论在求解不定方程、模线性方程和乘法逆元方面的应用。摘要长度:184字。 ... [详细]
author-avatar
曾经沧海难为水文杰59552066
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有