考虑最小二乘问题:
min x F ( x ) = 1 2 ∥ f ( x ) ∥ 2 2 \min _{x} F(x)=\frac{1}{2}\|f(x)\|_{2}^{2} xminF(x)=21∥f(x)∥22
对于简单的函数,我们可以令其导数 d F d x = 0 \frac{\rm{d}F}{\rm{d}\boldsymbol{x}}=0 dxdF=0,得到导数为零处的极值点。
而 SLAM 中的非线性函数形式复杂,常常难以用求导法得到最值,而采用梯度下降法,即,通过不断迭代 x k + 1 = x k + Δ x k \boldsymbol{x}_{k+1}=\boldsymbol{x}_k+\Delta\boldsymbol{x}_k xk+1=xk+Δxk,使得 ∣ ∣ f ( x k + Δ x k ) ∣ ∣ 2 ||f(\boldsymbol{x}_k+\Delta\boldsymbol{x}_k)||^2 ∣∣f(xk+Δxk)∣∣2 达到极小值,当 Δ x \Delta \boldsymbol{x} Δx 足够小时,即停止。关键在于增量 Δ x \Delta\boldsymbol{x} Δx 的选取。
过程如下:
——————————————————————————————————————————————————————
给定某个初值 x 0 \boldsymbol{x}_0 x0;
对于第 k k k 次迭代,寻找增量 Δ x k \Delta\boldsymbol{x}_k Δxk;
当 Δ x k \Delta \boldsymbol{x}_k Δxk 足够小时,即停止;否则,重复第二步,继续寻找。
——————————————————————————————————————————————————————
下面介绍几个常用的优化方法。
对于非线性函数 F ( x ) F(\boldsymbol{x}) F(x),考虑第 k k k 次迭代,将其在 x k \boldsymbol{x}_k xk 附近泰勒展开(将 Δ x k \Delta \boldsymbol{x}_k Δxk 看做未知数),
F ( x ) = F ( x k + Δ x k ) ≈ F ( x k ) + J ( x k ) T Δ x k + 1 2 Δ x k T H ( x k ) T Δ x k F(\boldsymbol{x})=F(\boldsymbol{x}_k+\Delta \boldsymbol{x}_k) \approx F(\boldsymbol{x}_k)+\boldsymbol{J}(\boldsymbol{x}_k)^T\Delta \boldsymbol{x}_k+\frac{1}{2}\Delta \boldsymbol{x}_k^T\boldsymbol{H}(\boldsymbol{x}_k)^T\Delta \boldsymbol{x}_k F(x)=F(xk+Δxk)≈F(xk)+J(xk)TΔxk+21ΔxkTH(xk)TΔxk
其中, J ( x k ) \boldsymbol{J}(\boldsymbol{x}_k) J(xk) 是 F ( x ) F(\boldsymbol{x}) F(x) 关于 x \boldsymbol{x} x 的一阶导数, H ( x k ) \boldsymbol{H}(\boldsymbol{x}_k) H(xk) 是二阶导数。
(1)最速下降法
仅保留一阶导数时,取增量为反向梯度即可,即
Δ x ∗ = − J ( x k ) \Delta \boldsymbol{x}^*=-\boldsymbol{J}(\boldsymbol{x}_k) Δx∗=−J(xk)
也被称为最速下降法。
(2)牛顿法
保留二阶梯度信息。此时增量方程为
Δ x ∗ = arg min ( F ( x ) + J ( x ) T Δ x + 1 2 Δ x T H Δ x ) \Delta \boldsymbol{x}^{*}=\arg \min \left(F(\boldsymbol{x})+\boldsymbol{J}(\boldsymbol{x})^{\mathrm{T}} \Delta \boldsymbol{x}+\frac{1}{2} \Delta \boldsymbol{x}^{\mathrm{T}} \boldsymbol{H} \Delta \boldsymbol{x}\right) Δx∗=argmin(F(x)+J(x)TΔx+21ΔxTHΔx)
右侧各项分别为 Δ x \Delta \boldsymbol{x} Δx 的零次、一次和二次项,将其对 Δ x \Delta \boldsymbol{x} Δx 求导,并令其为零
J + H Δ x = 0 ⇒ H Δ x = − J \boldsymbol{J}+\boldsymbol{H} \Delta \boldsymbol{x}=0 \Rightarrow \boldsymbol{H} \Delta \boldsymbol{x}=-\boldsymbol{J} J+HΔx=0⇒HΔx=−J
求解这个方程,即得到增量。此方法也被称为牛顿法。但在实际中, H \boldsymbol{H} H 矩阵计算较为困难。
将 f ( x ) f(\boldsymbol{x}) f(x) 一阶泰勒展开(注意不是 F ( x ) F(\boldsymbol{x}) F(x)):
f ( x + Δ x ) ≈ f ( x ) + J ( x ) T Δ x f(\boldsymbol{x}+\Delta \boldsymbol{x}) \approx f(\boldsymbol{x})+\boldsymbol{J}(\boldsymbol{x})^T\Delta \boldsymbol{x} f(x+Δx)≈f(x)+J(x)TΔx
其中, J ( x ) \boldsymbol{J}(\boldsymbol{x}) J(x) 是 f ( x ) f(\boldsymbol{x}) f(x) 关于 x \boldsymbol{x} x 的一阶导数,为 n × 1 n \times 1 n×1 列向量。
此时,我们的问题变为找到 Δ x \Delta \boldsymbol{x} Δx ,使得 1 2 ∥ f ( x ) + J ( x ) T Δ x ∥ 2 \frac{1}{2} \|f(\boldsymbol{x})+\boldsymbol{J}(\boldsymbol{x})^T\Delta \boldsymbol{x}\|^2 21∥f(x)+J(x)TΔx∥2 最小。将其展开
1 2 ∥ f ( x ) + J ( x ) T Δ x ∥ 2 = 1 2 ( f ( x ) + J ( x ) T Δ x ) T ( f ( x ) + J ( x ) T Δ x ) = 1 2 ( ∥ f ( x ∥ 2 + 2 f ( x ) J ( x ) T Δ x + Δ x T J ( x ) J ( x ) T Δ x ) \begin{aligned} \frac{1}{2} \|f(\boldsymbol{x})+\boldsymbol{J}(\boldsymbol{x})^T\Delta \boldsymbol{x}\|^2&=\frac{1}{2} (f(\boldsymbol{x})+\boldsymbol{J}(\boldsymbol{x})^T\Delta \boldsymbol{x})^T(f(\boldsymbol{x})+\boldsymbol{J}(\boldsymbol{x})^T\Delta \boldsymbol{x}) \\ &=\frac{1}{2} (\|f(\boldsymbol{x}\|^2+2f(\boldsymbol{x})\boldsymbol{J}(\boldsymbol{x})^T\Delta \boldsymbol{x}+\Delta \boldsymbol{x}^T\boldsymbol{J}(\boldsymbol{x})\boldsymbol{J}(\boldsymbol{x})^T\Delta \boldsymbol{x}) \end{aligned} 21∥f(x)+J(x)TΔx∥2=21(f(x)+J(x)TΔx)T(f(x)+J(x)TΔx)=21(∥f(x∥2+2f(x)J(x)TΔx+ΔxTJ(x)J(x)TΔx)
将 Δ x \Delta \boldsymbol{x} Δx 看做未知数,对其求导,并令其为零:
f ( x ) J ( x ) + J ( x ) J ( x ) T Δ x = 0 f(\boldsymbol{x})\boldsymbol{J}(\boldsymbol{x})+\boldsymbol{J}(\boldsymbol{x})\boldsymbol{J}(\boldsymbol{x})^T\Delta \boldsymbol{x}=\boldsymbol{0} f(x)J(x)+J(x)J(x)TΔx=0
得
J ( x ) J T ⏟ H ( x ) ( x ) Δ x = − J ( x ) f ( x ) ⏟ g ( x ) \underbrace{\boldsymbol{J}(\boldsymbol{x}) \boldsymbol{J}^{\mathrm{T}}}_{\boldsymbol{H}(\boldsymbol{x})}(\boldsymbol{x}) \Delta \boldsymbol{x}=\underbrace{-\boldsymbol{J}(\boldsymbol{x}) f(\boldsymbol{x})}_{\boldsymbol{g}(\boldsymbol{x})} H(x) J(x)JT(x)Δx=g(x) −J(x)f(x)
即
H ( x ) Δ x = g ( x ) \boldsymbol{H}(\boldsymbol{x})\Delta \boldsymbol{x}=\boldsymbol{g}(\boldsymbol{x}) H(x)Δx=g(x)
前面说到牛顿法中的二阶矩阵 H \boldsymbol{H} H 求解较为困难,所以这里用 J J ⊤ \boldsymbol{JJ}^\top JJ⊤ 作为 H \boldsymbol{H} H 的近似,从而省略了计算 H \boldsymbol{H} H 的过程。
(1)最速下降法
Δ x ∗ = − J ( x k ) \Delta \boldsymbol{x}^*=-\boldsymbol{J}(\boldsymbol{x}_k) Δx∗=−J(xk)
(2)牛顿法
H Δ x = − J \boldsymbol{H} \Delta \boldsymbol{x}=-\boldsymbol{J} HΔx=−J
(3)高斯牛顿法
J ( x ) J T ⏟ H ( x ) ( x ) Δ x = − J ( x ) f ( x ) ⏟ g ( x ) \underbrace{\boldsymbol{J}(\boldsymbol{x}) \boldsymbol{J}^{\mathrm{T}}}_{\boldsymbol{H}(\boldsymbol{x})}(\boldsymbol{x}) \Delta \boldsymbol{x}=\underbrace{-\boldsymbol{J}(\boldsymbol{x}) f(\boldsymbol{x})}_{\boldsymbol{g}(\boldsymbol{x})} H(x) J(x)JT(x)Δx=g(x) −J(x)f(x)
需要注意的是,最速下降法和牛顿法属于同一类型,他们的 J \boldsymbol{J} J 和 H \boldsymbol{H} H 都是针对 F ( x ) \boldsymbol{F(x)} F(x)(也就是整个目标函数);而高斯牛顿法的 J \boldsymbol{J} J 是针对 f ( x ) \boldsymbol{f(x)} f(x) (也就是误差项)。 此外,为减小数值,目标函数 F ( x ) \boldsymbol{F(x)} F(x) 可用均方差函数 。
考虑一条满足以下方程的曲线
y = exp ( a x 2 + b x + c ) + w y=\exp(ax^2+bx+c)+w y=exp(ax2+bx+c)+w
其中, a , b , c a, b, c a,b,c 为曲线参数, w w w 为高斯噪声,满足 w ∼ N ( 0 , σ 2 ) w \sim N(0, \sigma^2) w∼N(0,σ2)。假设有 N N N 个关于 x , y x, y x,y 的观测数据点,落在该直线附近,我们想用该方程进行拟合,也就是求出使残差最小的曲线参数 a , b , c a, b, c a,b,c。定义残差
( a , b , c ) ∗ = arg min a , b , c 1 2 ∑ i = 1 N ∥ y i − exp ( a x i 2 + b x i + c ) ∥ 2 2 (a, b, c)^*=\arg \min_{a, b, c} \frac{1}{2}\sum^N_{i=1}\|y_i-\exp(ax_i^2+bx_i+c)\|^2_2 (a,b,c)∗=arga,b,cmin21i=1∑N∥yi−exp(axi2+bxi+c)∥22
注意,这个问题的带估计变量是 a , b , c a, b, c a,b,c,而不是 x x x。
我们先根据模型生成 x , y x, y x,y 的真值,再加入高斯噪声,构成观测数据点。定义每一项的误差
e i = y i − exp ( a x i 2 + b i x + c ) e_i=y_i-\exp(ax_i^2+b_ix+c) ei=yi−exp(axi2+bix+c)
(1)最速下降法
Δ x ∗ = − J \Delta \boldsymbol{x}^*=-\boldsymbol{J} Δx∗=−J
其中, J = ∑ J i \boldsymbol{J}=\sum \boldsymbol{J}_i J=∑Ji, J i = [ ∂ F ∂ a , ∂ F ∂ b , ∂ F ∂ c ] ⊤ \boldsymbol{J}_i=[\frac{ \partial \boldsymbol{F}}{ \partial a}, \frac{ \partial \boldsymbol{F}}{ \partial b}, \frac{ \partial \boldsymbol{F}}{ \partial c}]^\top Ji=[∂a∂F,∂b∂F,∂c∂F]⊤。
∂ F ∂ a = e i ( − x i 2 exp ( a x i 2 + b x i + c ) ) ∂ F ∂ a = e i ( − x i exp ( a x i 2 + b x i + c ) ) ∂ F ∂ a = e i ( exp ( a x i 2 + b x i + c ) ) \frac{ \partial \boldsymbol{F}}{ \partial a}=e_i(-x_i^2\exp(ax_i^2+bx_i+c)) \\ \frac{ \partial \boldsymbol{F}}{ \partial a}=e_i(-x_i\exp(ax_i^2+bx_i+c))\\ \frac{ \partial \boldsymbol{F}}{ \partial a}=e_i(\exp(ax_i^2+bx_i+c)) ∂a∂F=ei(−xi2exp(axi2+bxi+c))∂a∂F=ei(−xiexp(axi2+bxi+c))∂a∂F=ei(exp(axi2+bxi+c))
/*********************************************************** *
* Time: 2023/8/10
* Author: xiaocong
* Function: 最速下降法
* 注意这里用的是 ae * xi * xi + be * xi + sin(ce)
* 原指数函数对误差和初值敏感,造成计算无穷大。
***********************************************************/
#include
#include
#include
#include
using namespace std;
using namespace Eigen;
const int N = 100; // 数据点个数
const int MAX_INTER = 1000; // 最大迭代次数
void steepestDescent(const VectorXd& x_data, const VectorXd& y_data, Vector3d& params)
{
double cost = 0;
for (int iter = 0; iter < MAX_INTER; iter++)
{
Vector3d J = Vector3d::Zero(); // 雅可比矩阵
cost = 0;
double ae = params(0);
double be = params(1);
double ce = params(2);
for (int i = 0;i < N;i++)
{
double xi = x_data(i), yi = y_data(i);
double ei = (yi - (ae * xi * xi + be * xi + sin(ce))); // 残差项
Vector3d Ji; // 雅可比矩阵
Ji(0) = ei * (-xi * xi);
Ji(1) = ei * (-xi);
Ji(2) = ei * (-cos(ce));
J += Ji;
cost += ei * ei;
}
Vector3d dx = -J / N; // 求解 dx
if (isnan(dx[0]))
{
cout << "result is nan!" << endl;
break;
}
if (dx.squaredNorm() < 1e-6) // dx 足够小
{
break;
}
// 迭代
params += dx;
cout << "iter= " << iter + 1 << endl;
cout << dx(0) << endl;
cout << dx(1) << endl;
cout << dx(2) << endl;
cout << "cost: " << cost << endl;
cout << "estimated abc= " << params(0) << ", " << params(1) << ", " << params(2) << endl;
}
}
int main(int argc, char** argv)
{
double ar = 1.0, br = 2.0, cr = 1; // 真实参数值
Vector3d params(2.0, 1.0, 0); // 初始参数值
// 生成数据
VectorXd x_data(N);
VectorXd y_data(N);
for (int i = 0; i < N; i++)
{
double xi = (i / 100.0); // [0~1.0]
double sigma = 0.02 * (rand() % 1000) / 1000.0 - 0.01; // 随机噪声,[-0.01, 0.01]
double yi = ar * xi * xi + br * xi + sin(cr) + sigma;
x_data(i) = xi;
y_data(i) = yi;
}
steepestDescent(x_data, y_data, params);
return 0;
}
iter= 454
-0.000666889
0.000694395
-0.000279458
cost: 0.0427055
estimated abc= 1.26563, 1.72471, 1.09882
(2)牛顿法
H Δ x = − J \boldsymbol{H} \Delta \boldsymbol{x}=-\boldsymbol{J} HΔx=−J
这里还需要求出海森矩阵即二阶导
H i = [ ∂ 2 F ∂ a 2 ∂ 2 F ∂ a ∂ b ∂ 2 F ∂ a ∂ c ∂ 2 F ∂ b ∂ a ∂ 2 F ∂ b 2 ∂ 2 F ∂ b ∂ c ∂ 2 F ∂ c ∂ a ∂ 2 F ∂ c ∂ b ∂ 2 F ∂ c 2 ] \boldsymbol{H}_i=\left[\begin{array}{c} \frac{ \partial^2 \boldsymbol{F}}{ \partial a^2} & \frac{ \partial^2 \boldsymbol{F} }{\partial a \partial b} &\frac{ \partial^2 \boldsymbol{F}}{ \partial a \partial c} \\ \frac{ \partial^2 \boldsymbol{F}}{\partial b \partial a} & \frac{ \partial^2 \boldsymbol{F}}{\partial b^2} &\frac{ \partial^2 \boldsymbol{F}}{ \partial b \partial c} \\ \frac{ \partial^2 \boldsymbol{F}}{ \partial c \partial a} & \frac{ \partial^2 \boldsymbol{F}}{\partial c \partial b} &\frac{ \partial^2 \boldsymbol{F}}{\partial c^2} \\ \end{array}\right] Hi= ∂a2∂2F∂b∂a∂2F∂c∂a∂2F∂a∂b∂2F∂b2∂2F∂c∂b∂2F∂a∂c∂2F∂b∂c∂2F∂c2∂2F
则 H = ∑ H i \boldsymbol{H}=\sum \boldsymbol{H}_i H=∑Hi
/*********************************************************** *
* Time: 2023/8/10
* Author: xiaocong
* Function: 牛顿法
* 注意这里用的是 ae * xi * xi + be * xi + sin(ce)
***********************************************************/
#include
#include
#include
#include
using namespace std;
using namespace Eigen;
const int N = 100; // 数据点个数
const int MAX_INTER = 1000; // 最大迭代次数
void steepestDescent(const VectorXd& x_data, const VectorXd& y_data, Vector3d& params)
{
double cost = 0;
for (int iter = 0; iter < MAX_INTER; iter++)
{
Vector3d J = Vector3d::Zero(); // 雅可比矩阵
Eigen::MatrixXd H(3, 3); // 海森矩阵
H.setZero();
cost = 0;
double ae = params(0);
double be = params(1);
double ce = params(2);
for (int i = 0;i < N;i++)
{
double xi = x_data(i), yi = y_data(i);
double ei = (yi - (ae * xi * xi + be * xi + sin(ce))) / N; // 残差项
J(0) += ei * (-xi * xi);
J(1) += ei * (-xi);
J(2) += ei * (-cos(ce));
H(0, 0) += xi * xi * xi * xi;
H(0, 1) += xi * xi * xi;
H(0, 2) += xi * xi * cos(ce);
H(1, 0) += xi * xi * xi;
H(1, 1) += xi * xi;
H(1, 2) += xi * cos(ce);
H(2, 0) += xi * xi * cos(ce);
H(2, 1) += xi * cos(ce);
H(2, 2) += cos(2 * ce);
cost += ei * ei;
}
Vector3d dx = H.ldlt().solve(-J); // 求解 dx
if (isnan(dx[0]))
{
cout << "result is nan!" << endl;
break;
}
if (dx.squaredNorm() < 1e-6) // dx 足够小
{
break;
}
// 迭代
params += dx;
cout << "iter= " << iter + 1 << endl;
cout << dx(0) << endl;
cout << dx(1) << endl;
cout << dx(2) << endl;
cout << "cost: " << cost << endl;
cout << "estimated abc= " << params(0) << ", " << params(1) << ", " << params(2) << endl;
}
}
int main(int argc, char** argv)
{
double ar = 1.0, br = 2.0, cr = 1.0; // 真实参数值
Vector3d params(2.0, 1.0, 0.0); // 初始参数值
// 生成数据
VectorXd x_data(N);
VectorXd y_data(N);
for (int i = 0; i < N; i++)
{
double xi = (i / 100.0); // [0~1.0]
double sigma = 0.02 * (rand() % 1000) / 1000.0 - 0.01; // 随机噪声,[-0.01, 0.01]
double yi = ar * xi * xi + br * xi + sin(cr) + sigma;
x_data(i) = xi;
y_data(i) = yi;
}
steepestDescent(x_data, y_data, params);
return 0;
}
iter= 470
-0.000656148
0.000766084
5.77874e-06
cost: 3.52463e-06
estimated abc= 1.09233, 1.89203, 1.01297
(3)高斯牛顿法
求出每个误差项关于状态变量的导数(注意 a , b , c a, b, c a,b,c 才是未知数):
∂ e i ∂ a = − x i 2 exp ( a x i 2 + b i x + c ) ∂ e i ∂ b = − x i exp ( a x i 2 + b i x + c ) ∂ e i ∂ c = − exp ( a x i 2 + b i x + c ) \frac{ \partial e_i }{ \partial a}=-x_i^2\exp(ax_i^2+b_ix+c) \\ \frac{ \partial e_i }{ \partial b}=-x_i\exp(ax_i^2+b_ix+c) \\ \frac{ \partial e_i }{ \partial c}=-\exp(ax_i^2+b_ix+c) ∂a∂ei=−xi2exp(axi2+bix+c)∂b∂ei=−xiexp(axi2+bix+c)∂c∂ei=−exp(axi2+bix+c)
记 J i = [ ∂ e i ∂ a , ∂ e i ∂ b , ∂ e i ∂ c ] ⊤ \boldsymbol{J}_i=[\frac{ \partial e_i }{ \partial a}, \frac{ \partial e_i }{ \partial b}, \frac{ \partial e_i }{ \partial c}]^\top Ji=[∂a∂ei,∂b∂ei,∂c∂ei]⊤。和前面不一样。
J ( x ) J T ⏟ H ( x ) ( x ) Δ x = − J ( x ) f ( x ) ⏟ g ( x ) \underbrace{\boldsymbol{J}(\boldsymbol{x}) \boldsymbol{J}^{\mathrm{T}}}_{\boldsymbol{H}(\boldsymbol{x})}(\boldsymbol{x}) \Delta \boldsymbol{x}=\underbrace{-\boldsymbol{J}(\boldsymbol{x}) f(\boldsymbol{x})}_{\boldsymbol{g}(\boldsymbol{x})} H(x) J(x)JT(x)Δx=g(x) −J(x)f(x)
此处即为
( ∑ i = 1 100 J i J i ⊤ ) Δ x = − ∑ i = 1 100 J i e i (\sum^{100}_{i=1}\boldsymbol{J}_i\boldsymbol{J}_i^\top)\Delta \boldsymbol{x}=-\sum^{100}_{i=1}\boldsymbol{J}_ie_i (i=1∑100JiJi⊤)Δx=−i=1∑100Jiei
/*********************************************************** *
* Time: 2023/8/10
* Author: xiaocong
* Function: 高斯牛顿法
***********************************************************/
#include
#include
#include
#include
using namespace std;
using namespace Eigen;
const int N = 100; // 数据点个数
const int MAX_INTER = 100; // 最大迭代次数
void gaussNewton(const VectorXd& x_data, const VectorXd& y_data, Vector3d& params)
{
double cost = 0;
for (int iter = 0; iter < MAX_INTER; iter++)
{
Matrix3d H = Matrix3d::Zero(); // H=JJ^T
Vector3d b = Vector3d::Zero(); // b=-Je
cost = 0;
double ae = params(0);
double be = params(1);
double ce = params(2);
for (int i = 0;i < N;i++)
{
double xi = x_data(i), yi = y_data(i);
double ei = yi - exp(ae * xi * xi + be * xi + ce); // 残差项
Vector3d Ji; // 雅可比矩阵
Ji(0) = -xi * xi * exp(ae * xi * xi + be * xi + ce);
Ji(1) = -xi * exp(ae * xi * xi + be * xi + ce);
Ji(2) = -exp(ae * xi * xi + be * xi + ce);
H += Ji * Ji.transpose();
b += -Ji * ei;
cost += ei * ei;
}
// 求解 dx
Vector3d dx = H.ldlt().solve(b);
if (isnan(dx[0]))
{
cout << "result is nan!" << endl;
break;
}
if (dx.squaredNorm() < 1e-6) // dx 足够小
{
break;
}
// 迭代
params += dx;
cout << "iter= " << iter + 1 << endl;
cout << dx(0) << endl;
cout << dx(1) << endl;
cout << dx(2) << endl;
cout << "cost= " << cost << endl;
cout << "estimated abc= " << params(0) << ", " << params(1) << ", " << params(2) << endl;
}
}
int main(int argc, char** argv)
{
double ar = 1.0, br = 2.0, cr = 1.0; // 真实参数值
Vector3d params(2.0, -1.0, 5.0); // 初始参数值
// 生成数据
VectorXd x_data(N);
VectorXd y_data(N);
for (int i = 0; i < N; i++)
{
double xi = i / 100.0; // [0~1]
double sigma = 0.02 * (rand() % 1000) / 1000.0 - 0.01; // 随机噪声,[-0.01, 0.01]
double yi = exp(ar * xi * xi + br * xi + cr) + sigma;
x_data(i) = xi;
y_data(i) = yi;
}
gaussNewton(x_data, y_data, params);
return 0;
}
iter= 7
-0.00134314
0.00213517
-0.000823118
cost= 0.00356444
estimated abc= 0.999314, 2.00098, 0.999659
最速下降法、牛顿法和高斯牛顿法都是常用的优化算法,用于解决最小化问题。它们各自有不同的优缺点,下面是对这三种算法的优缺点进行总结:
最速下降法:
优点:
缺点:
牛顿法:
优点:
缺点:
高斯牛顿法:
优点:
缺点:
综合来看,选择哪种算法取决于问题的性质和实际需求。最速下降法简单但收敛速度慢,适用于简单问题或作为其他优化算法的初始步骤。牛顿法收敛速度快,但在计算复杂和非凸问题中可能不稳定。高斯牛顿法适用于非线性问题,但对初始值敏感,需要权衡利弊。在实际应用中,可能需要结合多种算法来优化不同的问题。