Composing Transforms
let dt = Nx.float32
let x0 () = Nx.create dt [| 2 |] [| 5.0; -3.0 |]
let run name tx steps =
let param = ref (x0 ()) in
let st = ref (Vega.init tx !param) in
for _ = 1 to steps do
let p, s = Vega.step !st ~grad:!param ~param:!param in
param := p;
st := s
done;
Printf.printf " %-40s x = %s\n" name (Nx.data_to_string !param)
let () =
let lr = Vega.Schedule.constant 0.01 in
Printf.printf "--- AdamW: alias vs primitives (50 steps) ---\n";
run "adamw (alias)" (Vega.adamw ~weight_decay:0.01 lr) 50;
run "chain [adam; decay; lr] (manual)"
(Vega.chain
[
Vega.scale_by_adam ();
Vega.add_decayed_weights ~rate:(Vega.Schedule.constant 0.01) ();
Vega.scale_by_learning_rate lr;
])
50;
Printf.printf "\n";
Printf.printf "--- Adding gradient clipping (50 steps) ---\n";
run "adam (no clipping)" (Vega.adam lr) 50;
run "clip_by_norm 1.0 + adam"
(Vega.chain [ Vega.clip_by_norm 1.0; Vega.adam lr ])
50;
run "clip 0.5 + adam" (Vega.chain [ Vega.clip 0.5; Vega.adam lr ]) 50;
Printf.printf "\n";
Printf.printf "--- chain is associative (50 steps) ---\n";
let a = Vega.scale_by_adam () in
let b = Vega.add_decayed_weights ~rate:(Vega.Schedule.constant 0.01) () in
let c = Vega.scale_by_learning_rate lr in
run "chain [a; b; c]" (Vega.chain [ a; b; c ]) 50;
run "chain [chain [a; b]; c]" (Vega.chain [ Vega.chain [ a; b ]; c ]) 50;
Printf.printf "\n";
Printf.printf "--- update + apply_updates (explicit) ---\n";
let tx = Vega.adam lr in
let param = ref (x0 ()) in
let st = ref (Vega.init tx !param) in
for i = 1 to 50 do
let updates, s = Vega.update !st ~grad:!param ~param:!param in
param := Vega.apply_updates ~param:!param ~updates;
st := s;
if i mod 10 = 0 then
Printf.printf " step %2d x = %s\n" i (Nx.data_to_string !param)
done