线性回归的意外输出

时间:2018-02-18 17:27:28

标签: ocaml linear-regression

根据我在博客上发现的内容,我使用渐变下降来实现线性回归。它似乎适用于较小的值,但对于较大的值,输出会上升! 以下是我的实施

let inps = [1.;2.;4.;3.;5.]
let targs = [1.;3.;3.;2.;5.]

let train inps targs = 
  let rec aux inps targs n slope intercept i = 
  match n with 
  | 0 -> [intercept;slope]
  | n ->
    let inp = List.nth inps i in 
    let output = inp*.slope +. intercept in 
    let error = (List.nth targs i) -. output in 
    let slope' = slope +. 0.01*.error*.inp in 
    let intercept' = intercept +. 0.01*.error in
    aux inps targs (n-1) slope' intercept' ((i+1) mod (List.length inps))
  in 
  aux inps targs 200 0. 0. 0

适用于上述inpstargs,输出为

utop # train inps targs;;
- : float list = [0.274637254235572281; 0.845725879951186532]

但是当我更改inps时,它会提供不正确且非常大的值

utop # let inps' = List.map (function x -> x*.10.) inps;;
val inps' : float list = [10.; 20.; 40.; 30.; 50.]
─( 22:53:28 )─< command 141 >────────────────────────────────────{ counter: 0 }─
utop # train inps' targs;;
- : float list = [9.50572250044365676e+69; 4.58043753555103929e+71]

这里有什么问题?

1 个答案:

答案 0 :(得分:3)

首先,你的实现并不是真正的梯度下降,而是一种多梯度下降的形式,你试图连续减少模型和给定点数据之间的距离而不是全局距离。

其次,使用List.nth通常表示您需要数组而不是列表。

第三,当步长太大时,过冲是梯度下降的经典问题。这个问题在这里强调,你为步长因子选择常数γ= 0.01,你的下一个点定义为:

x_{n+1} = x_n - γ ∇F_n(x_n)

在你的情况下,距离最小值越远,渐变越大,下一次跳跃越长。因此,这些跳跃在最小值附近振荡而不会收敛。例如,打印截距和斜率的中间值

0.010000,0.100000
0.019900,0.298000
-0.069499,-3.277960
0.934584,26.844530
-12.447027,-642.236005
51.911044,1.344703
51.152993,-13.816317
56.197990,187.983555
-0.739057,-1520.127837
759.382253,36485.937627
-2896.795332,-75.838225
-2852.629734,807.473742

解决方案是手动减小步长或实现更好的线搜索子算法。