主要功能-最小化问题
-
目标函数分析:
- 定义函数 f ( x ) f(x) f(x) 及其一阶、二阶导数。
- 使用绘图工具可视化函数的形状。
-
实现数值优化:
- 使用牛顿法寻找函数的极值点,结合一阶和二阶导数加速收敛。
- 使用正则化牛顿法解决二阶导数矩阵可能不正定的问题。
-
可视化过程:
- 在优化过程中,动态标记初始点和更新点,直观展示牛顿法的优化轨迹。
环境设置和包导入
import Pkg; Pkg.activate(@__DIR__); Pkg.instantiate()
using LinearAlgebra
using ForwardDiff
using PyPlot
定义目标函数及其导数
function f(x)
return x.^4 + x.^3 - x.^2 - x
end
- 定义函数 f ( x ) = x 4 + x 3 − x 2 − x f(x) = x^4 + x^3 - x^2 - x f(x)=x4+x3−x2−x,这是目标函数。
function ∇f(x)
return 4.0*x.^3 + 3.0*x.^2 - 2.0*x - 1.0
end
- 定义
f
(
x
)
f(x)
f(x) 的一阶导数:
∇ f ( x ) = 4 x 3 + 3 x 2 − 2 x − 1 \nabla f(x) = 4x^3 + 3x^2 - 2x - 1 ∇f(x)=4x3+3x2−2x−1
function ∇2f(x)
return 12.0*x.^2 + 6.0*x - 2.0
end
- 定义
f
(
x
)
f(x)
f(x) 的二阶导数:
∇ 2 f ( x ) = 12 x 2 + 6 x − 2 \nabla^2 f(x) = 12x^2 + 6x - 2 ∇2f(x)=12x2+6x−2
绘制目标函数
x = LinRange(-1.75, 1.25, 1000)
- 生成区间 [ − 1.75 , 1.25 ] [-1.75, 1.25] [−1.75,1.25] 上的 1000 个均匀点,用于绘图。
p = plot(x, f(x))
- 绘制函数
f
(
x
)
f(x)
f(x) 在区间
[
−
1.75
,
1.25
]
[-1.75, 1.25]
[−1.75,1.25] 上的曲线。
定义牛顿法单步更新
function newton_step(x0)
xn = x0 - ∇2f(x0)\∇f(x0)
end
- 定义牛顿法的单步更新公式:
x new = x old − ( ∇ 2 f ( x old ) ) − 1 ∇ f ( x old ) x_{\text{new}} = x_{\text{old}} -{\left(\nabla^2 f(x_{\text{old}})\right)}^{-1} \nabla f(x_{\text{old}}) xnew=xold−(∇2f(xold))−1∇f(xold)
使用牛顿法寻找极值点
xguess = 0.0
- 初始猜测点 x guess = 0 x_{\text{guess}} = 0 xguess=0。
plot(x, f(x))
plot(xguess, f(xguess), "rx")
- 绘制目标函数,并在初始点
x
guess
x_{\text{guess}}
xguess 标记一个红叉。
xnew = newton_step(xguess[end])
xguess = [xguess xnew]
plot(x, f(x))
plot(xguess, f(xguess), "rx")
- 使用牛顿法计算新的 x new x_{\text{new}} xnew,并更新 x guess x_{\text{guess}} xguess。
- 再次绘制目标函数并标记新的点。
- 这个代码块可以反复运行,进行
x
g
u
e
s
s
x_{guess}
xguess迭代
- 这个代码块可以反复运行,进行
x
g
u
e
s
s
x_{guess}
xguess迭代
检查二阶导数在 x = 0 x = 0 x=0 的值
∇2f(0.0)
- 计算
∇
2
f
(
x
)
\nabla^2 f(x)
∇2f(x) 在
x
=
0
x = 0
x=0 的值,判断此处的二阶导数是否正定。结果为-2,不是正定的
定义正则化牛顿法
function regularized_newton_step(x0)
β = 1.0
H = ∇2f(x0)
while !isposdef(H)
H = H + β*I
end
xn = x0 - H\∇f(x0)
end
- 实现正则化牛顿法,解决二阶导数矩阵
∇
2
f
(
x
)
\nabla^2 f(x)
∇2f(x) 可能不是正定的问题。
- 步骤:
- 初始化 β = 1.0 \beta = 1.0 β=1.0 和 Hessian 矩阵 H = ∇ 2 f ( x ) H = \nabla^2 f(x) H=∇2f(x)。
- 如果
H
H
H 不是正定(
isposdef(H)
返回false
),则将 β I \beta I βI 加入 H H H,直到 H H H 正定。 - 使用修正后的
H
H
H 计算牛顿更新公式:
x new = x old − H − 1 ∇ f ( x old ) x_{\text{new}} = x_{\text{old}} - H^{-1} \nabla f(x_{\text{old}}) xnew=xold−H−1∇f(xold)
- 步骤:
使用正则化牛顿法寻找极值点
xguess = 0.0
plot(x, f(x))
plot(xguess, f(xguess), "rx")
- 再次初始化
x
guess
x_{\text{guess}}
xguess 并绘制初始点。
xnew = regularized_newton_step(xguess[end])
xguess = [xguess xnew]
plot(x, f(x))
plot(xguess, f(xguess), "rx")
- 使用正则化牛顿法计算新的点 x new x_{\text{new}} xnew 并更新 x guess x_{\text{guess}} xguess。
- 再次绘制目标函数并标记新的点。
- 这个代码块可以反复运行,进行 x g u e s s x_{guess} xguess迭代