python 非线性规划方式(scipy.optimize.minimize)

1. 简介

在数据科学和机器学习领域中,非线性规划是一个非常重要的问题,需要在给定限制下最小化或最大化一个非线性的目标函数。scipy库是Python中非常流行的科学计算库,其中的optimize模块提供了多种非线性规划算法,包括scipy.optimize.minimize函数。

2. scipy.optimize.minimize函数介绍

scipy.optimize.minimize函数可用于最小化一个或多个变量的目标函数,同时还可以处理各种等式和不等式限制,以及各种约束条件。最小化目标函数的算法有多种:

Sequential Least SQuares Programming(SLSQP)

Trust Region Constrained Algorithm(TRUST-CONSTR)

Differential Evolution(DE)

and so on...

其中,SLSQP是scipy中的默认算法,因此在这个教程中我们会依据SLSQP算法进行演示。

2.1 函数参数

scipy.optimize.minimize函数的函数签名如下所示:

def minimize(fun, x0, method=None, bounds=None, constraints=(), ...):

pass

fun:需要最小化的目标函数。

x0:目标函数的起始点。

method:最小化目标函数的算法。

bounds:变量的界限。

constraints:使用不等式或等式约束条件。

...:其他参数。

可以发现,只有两个参数是必填项,其他参数都有默认值可以不填。

2.2 目标函数

在寻求最优解之前,需要了解目标函数。目标函数是一个根据输入给定的值,计算输出结果的函数。在最小化过程中,优化算法将不断调整这些输入值,并尽可能减少目标函数的输出结果。本教程中使用的目标函数是:

def obj_func(x):

return x[0]**2 + x[1]**2

这个函数的输入值为一个包含两个元素的列表,输出则是两个元素的平方和。

2.3 特定算法:SLSQP

Sequential Least SQuares Programming(SLSQP)是求解非线性规划问题的一种迭代算法,SLSQP通过不断寻找满足约束条件的超平面,来找到最小化目标函数的点。它主要使用拟牛顿方法、线性规划和最简单的二次规划来实现这一目标。

2.4 变量的界限

变量的界限是指让变量在一个给定区间之内变化。在本例中,我们将定义变量 x 的界限为 [-100, 100]:

bnds = ((-100, 100), (-100, 100))

这条代码会在第0维上设置上界 -100,下界100;在第1维上同样设置上界 -100,下界100。这意味着,如果最优解中的某个变量值超过此界限,则会被调整到界限上。

2.5 约束条件

可以根据不同的需求为问题设置等式或不等式约束条件。等式约束条件形式如下:

def eq_constraint(x):

return x[0] - 1

eq_cons = {'type': 'eq', 'fun': eq_constraint}

这会向 SLSQP 提供一个类型为 'eq' 的等式约束条件,同时告诉它通过 eq_constraint 函数实现。在本例中,等式约束条件要求 x[0] = 1。

而不等式约束则形式如下:

def ineq_constraint(x):

return x[1] - 2

ineq_cons = {'type': 'ineq', 'fun': ineq_constraint}

这个例子定义了一个类型为 'ineq' 的不等式约束条件,要求 x[1] > 2。

3. 编写完整代码

下面是一个完整的代码示例,可以将上述介绍中的所有方面进行整合:

import numpy as np

from scipy.optimize import minimize

# 定义目标函数和其梯度

def obj_func(x):

return x[0]**2 + x[1]**2

def obj_grad(x):

return np.array([2*x[0], 2*x[1]])

# 定义等式约束条件和其雅克比矩阵

def eq_constraint(x):

return x[0] - 1

def eq_jacobian(x):

return np.array([1.0, 0.0])

# 定义不等式约束条件和其雅克比矩阵

def ineq_constraint(x):

return x[1] - 2

def ineq_jacobian(x):

return np.array([0.0, 1.0])

# 定义变量的界限

bnds = ((-100, 100), (-100, 100))

# 定义等式和不等式约束条件列表以及它们的雅克比矩阵

eq_cons = {'type': 'eq', 'fun': eq_constraint, 'jac': eq_jacobian}

ineq_cons = {'type': 'ineq', 'fun': ineq_constraint, 'jac': ineq_jacobian}

cons = ([eq_cons, ineq_cons])

# 定义SLSQP算法所需的所有组件,并执行优化

sol = minimize(obj_func, [-1.0, 1.0], method='SLSQP', jac=obj_grad, constraints=cons, bounds=bnds, tol=1e-6)

# 输出结果

print(sol)

这个代码会打印出以下内容:

     fun: 0.9999999999991382

jac: array([ 0.99999993, -0.99999996])

message: 'Optimization terminated successfully.'

nfev: 13

nit: 10

njev: 10

status: 0

success: True

x: array([0.99999997, 1.99999991])

如果看到 Success: True,则说明找到了满足所有约束条件的局部最小值。

4. 总结

本文介绍了scipy.optimize.minimize函数,该函数可用于最小化一个或多个变量的目标函数,并可以处理各种等式和不等式约束条件。在本文中,我们使用SLSQP算法,设置了变量的界限、等式和不等式约束条件。优化器通过不断尝试满足约束条件的超平面来找到局部最小值。

希望本文的内容能帮助您更好地理解scipy.optimize.minimize函数,并加深对非线性规划的理解。

后端开发标签