> 文章列表 > 最优化方法Python计算:函数向量和函数矩阵

最优化方法Python计算:函数向量和函数矩阵

最优化方法Python计算:函数向量和函数矩阵

函数 f ( x ) , x ∈ R n f(\\boldsymbol{x}),\\boldsymbol{x}\\in\\text{ℝ}^n f(x),xRn梯度
∇ f ( x ) = ( ∂ f ∂ x 1 ∂ f ∂ x 2 ⋮ ∂ f ∂ x n ) \\nabla f(\\boldsymbol{x})=\\begin{pmatrix}\\frac{\\partial f}{\\partial x_1}\\\\\\frac{\\partial f}{\\partial x_2}\\\\\\vdots\\\\\\frac{\\partial f}{\\partial x_n}\\end{pmatrix} f(x)= x1fx2fxnf
和Hesse阵
∇ 2 f ( x ) = ( ∂ 2 f ∂ x 1 ∂ x 1 ∂ 2 f ∂ x 1 ∂ x 2 ⋯ ∂ 2 f ∂ x 1 ∂ x n ∂ 2 f ∂ x 2 ∂ x 1 ∂ 2 f ∂ x 2 ∂ x 2 ⋯ ∂ 2 f ∂ x 2 ∂ x n ⋮ ⋮ ⋱ ⋮ ∂ 2 f ∂ x n ∂ x 1 ∂ 2 f ∂ x n ∂ x 2 ⋯ ∂ 2 f ∂ x n ∂ x n ) \\nabla^2f(\\boldsymbol{x})=\\begin{pmatrix}\\frac{\\partial^2f}{\\partial x_1\\partial x_1}&\\frac{\\partial^2f}{\\partial x_1\\partial x_2}&\\cdots&\\frac{\\partial^2f}{\\partial x_1\\partial x_n}\\\\\\frac{\\partial^2f}{\\partial x_2\\partial x_1}&\\frac{\\partial^2f}{\\partial x_2\\partial x_2}&\\cdots&\\frac{\\partial^2f}{\\partial x_2\\partial x_n}\\\\\\vdots&\\vdots&\\ddots&\\vdots\\\\\\frac{\\partial^2f}{\\partial x_n\\partial x_1}&\\frac{\\partial^2f}{\\partial x_n\\partial x_2}&\\cdots&\\frac{\\partial^2f}{\\partial x_n\\partial x_n}\\end{pmatrix} 2f(x)= x1x12fx2x12fxnx12fx1x22fx2x22fxnx22fx1xn2fx2xn2fxnxn2f
中的元素都是 x \\boldsymbol{x} x的函数。以函数为元素的向量称为函数向量。相仿地,元素为函数的矩阵称为函数矩阵。以函数的意义,梯度和Hesse阵仍然是 x \\boldsymbol{x} x的函数,不过前者为 R n → R n \\text{ℝ}^n\\rightarrow\\text{ℝ}^n RnRn的函数,而后者为 R n → R n × n \\text{ℝ}^n\\rightarrow\\text{ℝ}^{n\\times n} RnRn×n的函数。
例如,Rosenbrock函数 f ( x 1 , x 2 ) = 100 ( x 2 − x 1 2 ) 2 + ( 1 − x 1 ) 2 f(x_1,x_2)=100(x_2-x_1^2)^2+(1-x_1)^2 f(x1,x2)=100(x2x12)2+(1x1)2的梯度
∇ f ( x 1 , x 2 ) = ( − 400 x 1 ( x 2 − x 1 2 ) − 2 ( 1 − x 1 ) 200 ( x 2 − x 1 2 ) ) \\nabla f(x_1,x_2)=\\begin{pmatrix}-400x_1(x_2-x_1^2)-2(1-x_1)\\\\200(x_2-x_1^2)\\end{pmatrix} f(x1,x2)=(400x1(x2x12)2(1x1)200(x2x12))
x = ( 0 0 ) \\boldsymbol{x}=\\begin{pmatrix}0\\\\0\\end{pmatrix} x=(00)处的值为 ∇ f ( 0 , 0 ) = ( − 2 0 ) \\nabla f(0,0)=\\begin{pmatrix}-2\\\\0\\end{pmatrix} f(0,0)=(20),在 x = ( 1 1 ) \\boldsymbol{x}=\\begin{pmatrix}1\\\\1\\end{pmatrix} x=(11)处的值为 ∇ f ( 1 , 1 ) = ( 0 0 ) \\nabla f(1,1)=\\begin{pmatrix}0\\\\0\\end{pmatrix} f(1,1)=(00)。Rosenbrock函数的Hesse阵
∇ 2 f ( x 1 , x 2 ) = ( − 400 ( x 2 − x 1 2 ) + 800 x 1 2 + 2 − 400 x 1 − 400 x 1 200 ) \\nabla^2f(x_1,x_2)=\\begin{pmatrix}-400(x_2-x_1^2)+800x_1^2+2&-400x_1\\\\-400x_1&200\\end{pmatrix} 2f(x1,x2)=(400(x2x12)+800x12+2400x1400x1200)
其在 x = ( 0 0 ) \\boldsymbol{x}=\\begin{pmatrix}0\\\\0\\end{pmatrix} x=(00)处的值为 ∇ 2 f ( 0 , 0 ) = ( 2 0 0 200 ) \\nabla^2f(0,0)=\\begin{pmatrix}2&0\\\\0&200\\end{pmatrix} 2f(0,0)=(200200),而在 x = ( 1 1 ) \\boldsymbol{x}=\\begin{pmatrix}1\\\\1\\end{pmatrix} x=(11)处的值为 ∇ 2 f ( 1 , 1 ) = ( 802 − 400 − 400 200 ) \\nabla^2f(1,1)=\\begin{pmatrix}802&-400\\\\-400&200\\end{pmatrix} 2f(1,1)=(802400400200)
Python用于科学计算的工具包sicpy的optimization模块提供了计算Rosenbrock函数值、梯度值及Hesse阵值的函数rosen、rosen_der和rosen_hess。
例1 调用rosen_der和rosen_hess验算上述计算结果。
:下列代码完成本例计算。

import numpy as np                                  #导入numpy
from scipy.optimize import rosen_der,rosen_hess     #导入rosen_der,rosen_hess
x=np.array([0,0])                                   #设置向量x
print(rosen_der(x))                                 #计算梯度
print(rosen_hess(x))                                #计算Hesse阵
x=np.array([1,1])                                   #重设向量x
print(rosen_der(x))                                 #重算梯度
print(rosen_hess(x))                                #重算Hesse阵

程序的第1~2行分别导入numpy包和scipy包中optimization模块的rosen_der函数和rosen_hess函数。第3行创建numpy提供的array类数组对象x,并将其初始化为[0,0],第4、5行调用rosen_der和rosen_hess函数,分别计算Rosenbrock函数在[0,0]处的梯度和Hesse阵并输出。第6行将x重置为[1,1],第7、8行将打印算得的梯度和Hesse阵。运行程序,输出

[-2  0]
[[  2   0]
[  0 200]]
[0 0]
[[ 802 -400]
[-400  200]]

其中第1行输出的是 ∇ f ( 0 , 0 ) = ( − 2 0 ) \\nabla f(0,0)=\\begin{pmatrix}-2\\\\0\\end{pmatrix} f(0,0)=(20),第2~3函数输出的是 ∇ 2 f ( 0 , 0 ) = ( 2 0 0 200 ) \\nabla^2f(0,0)=\\begin{pmatrix}2&0\\\\0&200\\end{pmatrix} 2f(0,0)=(200200)。第4行输出 ∇ f ( 1 , 1 ) = ( 0 0 ) \\nabla f(1,1)=\\begin{pmatrix}0\\\\0\\end{pmatrix} f(1,1)=(00),第5~6行输出 ∇ 2 f ( 1 , 1 ) = ( 802 − 400 − 400 200 ) \\nabla^2f(1,1)=\\begin{pmatrix}802&-400\\\\-400&200\\end{pmatrix} 2f(1,1)=(802400400200)
Rosenbrock函数是Python作为基准问题唯一提供梯度和Hesse阵计算函数的对象。一般情况下,我们需要自行为函数 f ( x ) , x ∈ R n f(\\boldsymbol{x}),\\boldsymbol{x}\\in\\text{ℝ}^n f(x),xRn设置计算梯度和Hesse阵的函数。
Python中有一个lambda运算符,可以用来定义简单函数,其语法格式为
lambda x: expression
其中,x表示函数的自变量,分号后的expression表示计算函数返回值的表达式,一般含有自变量x。
例2lambda运算符,设计Rosenbrock函数的梯度函数和Hesse阵函数。
:下列代码完成本例计算。

import numpy as np                                                      #导入numpy
f1=lambda x:np.array([-400*x[0]*(x[1]-x[0]**2)-2*(1-x[0]),              #设置梯度函数200*(x[1]-x[0]**2)])
f2=lambda x:np.array([[-400*(x[1]-x[0]**2)+800*x[0]**2+2,-400*x[0]],    #设置Hesse阵函数[-400*x[0],200]])
x=np.array([0,0])                                                       #设置向量x
print(f1(x))                                                            #计算梯度
print(f2(x))                                                            #计算Hesse阵
x=np.array([1,1])                                                       #重置向量x
print(f1(x))                                                            #重算梯度
print(f2(x))                                                            #重算Hesse阵

程序的第2~3行用lambda运算符定义Rosenbrock函数的梯度函数
∇ f ( x 1 , x 2 ) = ( − 400 x 1 ( x 2 − x 1 2 ) − 2 ( 1 − x 1 ) 200 ( x 2 − x 1 2 ) ) \\nabla f(x_1,x_2)=\\\\\\begin{pmatrix}-400x_1(x_2-x_1^2)-2(1-x_1)\\\\200(x_2-x_1^2)\\end{pmatrix} f(x1,x2)=(400x1(x2x12)2(1x1)200(x2x12))
为f1。注意,Python数组的下标是从0开始编码的。第4~5行定义Hesse阵函数
∇ 2 f ( x 1 , x 2 ) = ( − 400 ( x 2 − x 1 2 ) + 800 x 1 2 + 2 − 400 x 1 − 400 x 1 200 ) \\nabla^2f(x_1,x_2)=\\begin{pmatrix}-400(x_2-x_1^2)+800x_1^2+2&-400x_1\\\\-400x_1&200\\end{pmatrix} 2f(x1,x2)=(400(x2x12)+800x12+2400x1400x1200)
为f2。注意, Python使用二维数组(等长数组的数组)表示矩阵。第6~8行和9~11行分别计算 x = ( 0 0 ) \\boldsymbol{x}=\\begin{pmatrix}0\\\\0\\end{pmatrix} x=(00) x = ( 1 1 ) \\boldsymbol{x}=\\begin{pmatrix}1\\\\1\\end{pmatrix} x=(11)处Rosenbrock函数的梯度和Hesse阵并输出。程序运行结果为

[-2  0]
[[  2   0]
[  0 200]]
[0 0]
[[ 802 -400]
[-400  200]]

与例1的输出一致。