module MX = Owl_dense_real
module UT = Owl_utils
let kmeans x c = let open MX in
let cpts0 = fst (draw_rows x c) in
let cpts1 = zeros c (col_num x) in
let assignment = Array.make (row_num x) (0, max_float) in
let _ = try for counter = 1 to 100 do
Log.info "iteration %i ..." counter; flush stdout;
iteri_rows (fun i v ->
iteri_rows (fun j u ->
let e = sum((v -@ u) **@ 2.) in
if e < snd assignment.(i) then assignment.(i) <- (j, e)
) cpts0
) x;
iteri_rows (fun j u ->
let l = UT.filteri_array (fun i y -> fst y = j, i) assignment in
let z = average_rows (rows x l) in
let _ = copy_row_to z cpts1 j in ()
) cpts0;
if cpts0 =@ cpts1 then failwith "converged" else ignore (cpts0 << cpts1)
done with exn -> () in
cpts1, UT.map_array fst assignment
let numerical_gradient l p x y y' =
let open MX in
let h = 0.00001 in
let f = l y in
let g = mapi_by_row ~d:(col_num p)
(fun i v ->
let fa = f (x $@ (replace_row (v -$ h) p i)) in
let fb = f (x $@ (replace_row (v +$ h) p i)) in
(fb -@ fa) /$ (2. *. h)
) p in g
let l1 p = MX.(average_rows (abs p))
let l1_grad p =
MX.map (fun x ->
if x > 0. then 1. else if x < 0. then (-1.) else 0.
) p
let l2 p = MX.(0.5 $* (average_rows (p *@ p)))
let l2_grad p = p
let elastic a x = MX.(a $* (l1 x) +@ ((1. -. a) $* (l2 x)))
let elastic_grad a x =
let g1 = l1_grad x in
let g2 = l2_grad x in
MX.(a $* g1 +@ (a $* g2))
let noreg x = MX.(zeros 1 (col_num x))
let noreg_grad x = MX.(zeros (row_num x) (col_num x))
let square_loss y y' =
let open MX in
average_rows ((y' -@ y) **@ 2.)
let square_grad x y y' =
let open MX in
(transpose x) $@ (y' -@ y) /$ (float_of_int (row_num x))
let hinge_loss y y' =
let open MX in
let z = 1. $- ( y *@ y' ) in
let z = map (Pervasives.max 0.) z in
average_rows z
let hinge_grad x y y' =
let open MX in
let z = mapi (fun i j x ->
if x < 1. then (0. -. y.{i,j}) else 0.
) (y *@ y') in
(transpose x) $@ z /$ (float_of_int (row_num x))
let hinge2_loss y y' =
let z = hinge_loss y y' in
MX.(z *@ z)
let hinge2_grad x y y' = None
let softmax_loss y y' = None
let softmax_grad x y y' = None
let log_loss y y' =
let z = MX.map (fun x ->
if x > 18. then exp (-1. *. x)
else if x < (-18.) then (-1. *. x)
else log (1. +. exp(-1. *. x))
) MX.(y *@ y') in
MX.average_rows z
let log_grad x y y' =
let open MX in
let y' = sigmoid y' in
(transpose x) $@ (y' -@ y) /$ (float_of_int (row_num x))
let constant_rate a s c = 0.1
let optimal_rate a s c =
let c = float_of_int c in
s /. ((1. +. (a *. s *. c)) ** 0.75)
let decr_rate a s c = min 0.5 (1. /. (a *. float_of_int c))
let when_stable v c = v < 0.00001
let when_enough v c = (v < 0.00001 && c > 1000) || (c > 5000)
let _sgd_basic b s t l g r o a i p x y =
let p = if i = false then ref p
else ref MX.(p @= uniform 1 (col_num p)) in
let x = if i = false then x
else MX.(x @|| ones (row_num x) 1) in
let st = ref 0.1 in
let cost = ref (Array.make 5000 0.) in
let obj0 = ref max_float in
let obj1 = ref min_float in
let counter = ref 0 in
while not (t (abs_float (!obj1 -. !obj0)) !counter) do
let _ = obj0 := !obj1 in
let xt, idx = MX.draw_rows x b in
let yt = MX.rows y idx in
let yt' = MX.(xt $@ !p) in
let lt = l yt yt' in
let dt = g xt yt yt' in
let lt = if a = 0. then lt else MX.(lt +@ (a $* (r !p))) in
let dt = if a = 0. then dt else MX.(dt +@ (a $* (o !p))) in
let _ = st := s a !st !counter in
let _ = p := MX.(!p -@ (dt *$ !st)) in
let _ = obj1 := MX.sum lt in
let _ = if !counter < (Array.length !cost) then !cost.(!counter) <- !obj1 in
let _ = counter := !counter + 1 in
Log.info "iteration #%i: %.4f" !counter !obj1;
flush stdout
done; !p
let sgd ?(b=1) ?(s=optimal_rate) ?(t=when_stable) ?(l=square_loss) ?(g=square_grad) ?(r=noreg) ?(o=noreg_grad) ?(a=0.) ?(i=false) p x y = _sgd_basic b s t l g r o a i p x y
let gradient_descent = None
let svm_regression ?(i=false) p x y =
let b = min 50 (MX.(row_num x) / 2) in
let s = decr_rate in
let t = when_enough in
let l = hinge_loss in
let g = hinge_grad in
let r = l2 in
let o = l2_grad in
let a = 1. /. (float_of_int 100) in
_sgd_basic b s t l g r o a i p x y
let ols_regression ?(i=true) x y =
let b = 1 in
let s = optimal_rate in
let t = when_stable in
let l = square_loss in
let g = square_grad in
let r = noreg in
let o = noreg_grad in
let a = 0. in
let p = MX.(uniform (col_num x) (col_num y)) in
_sgd_basic b s t l g r o a i p x y
let ridge_regression ?(i=true) ?(a=0.001) x y =
let b = 1 in
let s = optimal_rate in
let t = when_stable in
let l = square_loss in
let g = square_grad in
let r = l2 in
let o = l2_grad in
let p = MX.(uniform (col_num x) (col_num y)) in
_sgd_basic b s t l g r o a i p x y
let lasso_regression ?(i=true) ?(a=0.001) x y =
let b = 1 in
let s = optimal_rate in
let t = when_stable in
let l = square_loss in
let g = square_grad in
let r = l1 in
let o = l1_grad in
let p = MX.(uniform (col_num x) (col_num y)) in
_sgd_basic b s t l g r o a i p x y
let logistic_regression ?(i=true) x y =
let b = 1 in
let s = optimal_rate in
let t = when_stable in
let l = log_loss in
let g = log_grad in
let r = noreg in
let o = noreg_grad in
let a = 0. in
let p = MX.(uniform (col_num x) (col_num y)) in
_sgd_basic b s t l g r o a i p x y