函数 f ( x ) , x ∈ R n f(\boldsymbol{x}),\boldsymbol{x}\in\text{ℝ}^n f(x),x∈Rn的梯度
∇ 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)= ∂x1∂f∂x2∂f⋮∂xn∂f
和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)= ∂x1∂x1∂2f∂x2∂x1∂2f⋮∂xn∂x1∂2f∂x1∂x2∂2f∂x2∂x2∂2f⋮∂xn∂x2∂2f⋯⋯⋱⋯∂x1∂xn∂2f∂x2∂xn∂2f⋮∂xn∂xn∂2f
中的元素都是 x \boldsymbol{x} x的函数。以函数为元素的向量称为函数向量。相仿地,元素为函数的矩阵称为函数矩阵。以函数的意义,梯度和Hesse阵仍然是 x \boldsymbol{x} x的函数,不过前者为 R n → R n \text{ℝ}^n\rightarrow\text{ℝ}^n Rn→Rn的函数,而后者为 R n → R n × n \text{ℝ}^n\rightarrow\text{ℝ}^{n\times n} Rn→Rn×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(x2−x12)2+(1−x1)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(x2−x12)−2(1−x1)200(x2−x12))
在 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(x2−x12)+800x12+2−400x1−400x1200)
其在 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)=(802−400−400200)。
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)=(802−400−400200)。
Rosenbrock函数是Python作为基准问题唯一提供梯度和Hesse阵计算函数的对象。一般情况下,我们需要自行为函数 f ( x ) , x ∈ R n f(\boldsymbol{x}),\boldsymbol{x}\in\text{ℝ}^n f(x),x∈Rn设置计算梯度和Hesse阵的函数。
Python中有一个lambda运算符,可以用来定义简单函数,其语法格式为
lambda x: expression
其中,x表示函数的自变量,分号后的expression表示计算函数返回值的表达式,一般含有自变量x。
例2 用lambda运算符,设计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(x2−x12)−2(1−x1)200(x2−x12))
为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(x2−x12)+800x12+2−400x1−400x1200)
为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的输出一致。