四参数拟合算法之高斯牛顿法

介绍

 前面提到了牛顿法,那其实相当于求根的算法。跟一般最小二乘法的区别是,它并没有显示的最小二乘目标式子。
F ( A , B , C , D , x i ) = 0 F(A,B,C,D,x_i) = 0 F(A,B,C,D,xi)=0

 下面提到的高斯牛顿法,则要正式引入最小二乘法的目标式子。首先对牛顿法做一次更深入的展开。

牛顿法

 牛顿法在用于一元方程求根的时候,只需要做一阶泰勒展开,这个时候,用到的是迭代点的导数信息找到下一个迭代点。在多维的情况下面,则用到了梯度信息。在求解的问题的时候,假如初始点选得不好,可能会遇到梯度消失的问题,最后会导致收敛失败。但这好像是优化算法的一个通病,并非牛顿法的专利。言归正传,下面解释一下牛顿法在四参数数据拟合中应用。
对于给定的m组数据 ( x i , y i ) (x_i,y_i) (xi,yi),
w = [ A , B , C , D ] T f ( w ; x i ) = D + A − D 1 + ( x i / C ) B r i ( w ) = y i − f ( w ; x i ) \\ w = [A,B,C,D]^T \\ f(w;x_i) = D+\frac{A-D}{1+(x_i/C)^B} \\ r_i(w) = y_i-f(w;x_i) w=[A,B,C,D]Tf(w;xi)=D+1+(xi/C)BADri(w)=yif(w;xi)
r i ( w ) ∈ R r_i(w)\in \mathbb{R} ri(w)R称为剩余值,或者叫残差,偏差,是一个标量, r ( w ) ∈ R m × 1 r(w)\in \mathbb{R}^{m\times 1} r(w)Rm×1表示剩余函数,是一个向量。 f f f为待拟合的公式
求解的目标是使得残差平方最小,如下
m i n   F ( w ) = 1 2 r ( w ) T r ( w ) = 1 2 ∑ i = 1 m ∣ ∣ y i − f ( w ; x i ) ∣ ∣ 2 min \ F(w) =\frac{1}{2} r(w)^Tr(w) = \frac{1}{2} \sum_{i=1}^{m}||y_i-f(w;x_i) ||^2 min F(w)=21r(w)Tr(w)=21i=1myif(w;xi)2
牛顿法的第一步是求得 F ′ ( w ) F{'}(w) F(w),令 F ′ ( w ) = 0 F{'}(w) = 0 F(w)=0,再对其做泰勒展开
F ′ ( w + Δ w ) ≈ F ′ ( w ) + F ′ ′ ( w ) Δ w = 0 ⇒ Δ w = − ( F ′ ′ ( w ) ) − 1 F ′ ( w ) F{'}(w+\Delta w) \approx F{'}(w)+F{''}(w)\Delta w=0 \\\Rightarrow \Delta w = -(F{''}(w))^{-1}F{'}(w) F(w+Δw)F(w)+F(w)Δw=0Δw=(F(w))1F(w)
总共需要对F做二次求导,这里需要引入jacob矩阵
w 关于r的雅可比矩阵如下
J = [ ∂ r 1 ∂ A ⋯ ∂ r 1 ∂ D ⋮ ⋱ ⋮ ∂ r m ∂ A ⋯ ∂ r m ∂ D ] = [ r 1 ′ ( w ) ⋮ r m ′ ( w ) ] J=\begin{bmatrix} \frac{\partial r_1}{\partial A}&\cdots&\frac{\partial r_1}{\partial D}\\ \vdots&\ddots&\vdots\\ \frac{\partial r_m}{\partial A}&\cdots&\frac{\partial r_m}{\partial D} \end{bmatrix}=\begin{bmatrix} r^{'}_1(w)\\ \vdots \\ r^{'}_m(w) \end{bmatrix} J=Ar1ArmDr1Drm=r1(w)rm(w)

F的梯度信息g(w)
g ( w ) = F ′ ( w ) = ∑ i = 1 m r i ( w ) r i ′ ( w ) = J T r ( w ) g(w) = F^{'}(w) =\sum_{i=1}^{m}r_i(w)r_i^{'}(w)=J^Tr(w) g(w)=F(w)=i=1mri(w)ri(w)=JTr(w)
r i ( w ) ∈ R r_i(w)\in \mathbb{R} ri(w)R为标量, r i ( w ) ′ ∈ R m × 1 r_i(w)^{'}\in \mathbb{R}^{m \times 1} ri(w)Rm×1为偏导,或者说梯度,是一个向量,最后得到, g ( w ) ∈ R m × 1 g(w)\in \mathbb{R}^{m \times 1} g(w)Rm×1
F的海赛阵为
G ( w ) = ∑ i = 1 m ( r i ′ ( w ) r i ′ ( w ) T + r i ( w ) r i ′ ′ ( w ) ) = J T J + S ( w ) G(w) = \sum_{i=1}^{m}(r_i^{'}(w)r_i^{'}(w)^T+r_i(w)r_i^{''}(w))=J^TJ+S(w) G(w)=i=1m(ri(w)ri(w)T+ri(w)ri(w))=JTJ+S(w)
Δ w = − ( F ′ ′ ( w ) ) − 1 F ′ ( w ) = − ( J T J + S ( w ) ) − 1 J T r ( w ) \Delta w = -(F{''}(w))^{-1}F{'}(w)=-(J^TJ+S(w))^{-1}J^Tr(w) Δw=(F(w))1F(w)=(JTJ+S(w))1JTr(w)
S ( w ) ∈ R n × n S(w)\in \mathbb{R}^{n \times n} S(w)Rn×n通常运算量巨大,这部分常用两种处理,一种是忽略,即小剩余算法,另外一种是近似,大剩余算法。
高斯牛顿法忽略了其高阶项S(x),相当于目标式子的一阶泰勒展开
Δ w = − ( F ′ ′ ( w ) ) − 1 F ′ ( w ) = − ( J T J ) − 1 J T r ( w ) \Delta w = -(F{''}(w))^{-1}F{'}(w)=-(J^TJ)^{-1}J^Tr(w) Δw=(F(w))1F(w)=(JTJ)1JTr(w)
这个做法其实等同于之前的牛顿法。当残量 r ( w ∗ ) r(w^*) r(w)比较小时,这种方法比较有效,反之,算法就比较难收敛。另外,从上公式里面可以看到, Δ w \Delta w Δw的计算要求 J J J为列满秩,否则求得的结果可能不稳定,导致算法难以收敛。 为了克服这个问题,其中一个手段是改善矩阵 J T J J^TJ JTJ的变态程度。常用的处理就是在方程中加入扰动,也就是岭回归做的事情。从另外一个角度来说,也是加入 Δ w \Delta w Δw的2范式惩罚。为什么这么做呢,因为对于泰勒展开而言,无疑 Δ w \Delta w Δw越大,展开式越不准确。由此,便得到了Levenberg-Marquardt算法。

Matlab Code

>> [A,B,C,D] =-10 36.9 1974.7 431.0

下面的代码和之前代码基本一致,只不过去掉了matlab 的symbolic运算,速度快的飞起

clear;
load census;
x1 = cdate ;
y1 = pop ;
lamda = 0.3;
%init a,b,c,d
d = max(y1)+1;
a = min(y1)-0.1;
y2 = log((y1-d)./(a-y1));
x2 = log(x1);
[curve2,gof2] = fit(x2,y2, 'poly1');
b = -curve2.p1;
c = exp(curve2.p2/b);
%newton
for k = 1:1:1000
    fy = [];
    JacobiMatrix = ones(length(x1),4);
    w=[a,b,c,d];
    [res,R,fit] = evaluateFit(y1,x1,w);
    if R>0.997
        return;
    end
    for i = 1:1:length(x1)
        fy(i,:) =  d+(a-d)/(1+(x1(i)/c)^b);
        JacobiMatrix(i,1) = calc_pA(x1(i),a,b,c,d);
        JacobiMatrix(i,2) = calc_pB(x1(i),a,b,c,d);
        JacobiMatrix(i,3) = calc_pC(x1(i),a,b,c,d);
        JacobiMatrix(i,4) = calc_pD(x1(i),a,b,c,d);
    end
    delta_w = inv((JacobiMatrix)'*(JacobiMatrix))*JacobiMatrix'*(y1-fy);
    %update a b c d
    a = a +lamda*delta_w(1);
    b = b+lamda*delta_w(2);
    c = c +lamda*delta_w(3);
    d= d +lamda*delta_w(4);
end

function [res,R2,fit] = evaluateFit(y,x,w)
fit = getFittingValue(x,w);
res =  norm(y-fit)/sqrt(length(fit));
yu =  mean(y);
R2 = 1 - norm(y-fit)^2/norm(y - yu)^2;
end
function fit = getFittingValue(x,w)
len = length(x);
fit = ones(len,1);
for i = 1:1:len
    fit(i)  = hypothesis(x(i),w);
end
end
function val  = hypothesis(x,w)
a = w(1);b= w(2);c= w(3);d= w(4);
val = d+(a-d)/(1+(x/c)^b);
end
function val = calc_pA(x,A,B,C,D)
val = 1/((x/C)^B + 1);
end
function val = calc_pB(x,A,B,C,D)
val = -(log(x/C)*(A - D)*(x/C)^B)/((x/C)^B + 1)^2;
end
function val = calc_pC(x,A,B,C,D)
val = (B*x*(A - D)*(x/C)^(B - 1))/(C^2*((x/C)^B + 1)^2);
end
function val = calc_pD(x,A,B,C,D)
val = 1 - 1/((x/C)^B + 1);
end

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值