nx_pose_elm.nx source
↩ module page · 69 lines · 3194 B
1// nx_pose_elm.nx -- the NONLINEAR learner for pose-from-silhouette (roadmap R2 v1). The linear perceptron on raw
2// occupancy provably can't separate the hand regions (tried 9-region, delta, 3-band = all at chance). An EXTREME
3// LEARNING MACHINE fixes that WITHOUT fragile fixed-point backprop: a FIXED RANDOM projection h = relu(R*x + b)
4// lifts the occupancy into a high-dim nonlinear feature space where the classes ARE linearly separable, and only
5// the LINEAR OUTPUT is trained -- by the PROVEN perceptron rule (same one text2motion used). Random-features /
6// ELM is a real ML method (Rahimi-Recht random kitchen sinks; Huang ELM). Seeded LCG => deterministic. The
7// honest ceiling stays: coarse, our-render-silhouette domain; SOTA pose = a trained CNN. license_tier: ORIGINAL
8import "nx_syscalls.nx"
9const ELM_MAGIC_1103515245: i64 = 1103515245
10const ELM_MAGIC_12345: i64 = 12345
11
12const ELM_HSCALE: i64 = 256 // divides R*x before the bias, keeps h bounded
13
14func elm_lcg(st: *i64) -> i64 { st[0] = (st[0] * ELM_MAGIC_1103515245 + ELM_MAGIC_12345) & 0x7fffffff; return st[0] }
15// fill the FIXED random projection R[NH*NF] in [-4,4] and bias b[NH] in [-100,100] from a seed (deterministic).
16func elm_init(R: *i64, b: *i64, nh: i64, nf: i64, seed: i64) -> i64 {
17 let st: *i64 = sys_mmap(8) as *i64; st[0] = seed
18 var i: i64 = 0
19 while i < nh * nf { R[i] = (elm_lcg(st) % 9) - 4; i = i + 1 }
20 var j: i64 = 0
21 while j < nh { b[j] = (elm_lcg(st) % 201) - 100; j = j + 1 }
22 return 0
23}
24// project x[nf] -> h[nh] = relu( (R*x)/HSCALE + b ).
25func elm_project(R: *i64, b: *i64, x: *i64, nf: i64, nh: i64, h: *i64) -> i64 {
26 var j: i64 = 0
27 while j < nh {
28 var s: i64 = 0
29 var c: i64 = 0
30 while c < nf { s = s + R[j*nf+c] * x[c]; c = c + 1 }
31 s = s / ELM_HSCALE + b[j]
32 if s < 0 { s = 0 }
33 h[j] = s
34 j = j + 1
35 }
36 return 0
37}
38func elm_score(W: *i64, r: i64, h: *i64, nh: i64) -> i64 { var s: i64=0; var j: i64=0; while j<nh { s=s+W[r*nh+j]*h[j]; j=j+1 } return s }
39func elm_predict(W: *i64, h: *i64, nh: i64, nc: i64) -> i64 {
40 var best: i64 = 0; var bs: i64 = elm_score(W, 0, h, nh); var r: i64 = 1
41 while r < nc { let s: i64 = elm_score(W, r, h, nh); if s > bs { bs = s; best = r } r = r + 1 }
42 return best
43}
44// train the LINEAR OUTPUT W[nc*nh] on the projected features by the perceptron rule. hs = ns*nh. Returns last
45// epoch mistakes.
46func elm_train(W: *i64, hs: *i64, labels: *i64, ns: i64, nh: i64, nc: i64, epochs: i64) -> i64 {
47 var i: i64 = 0
48 while i < nc * nh { W[i] = 0; i = i + 1 }
49 var last: i64 = 0
50 var e: i64 = 0
51 while e < epochs {
52 var mist: i64 = 0
53 var n: i64 = 0
54 while n < ns {
55 let h: *i64 = (hs as i64 + n*nh*8) as *i64
56 let pred: i64 = elm_predict(W, h, nh, nc)
57 let lab: i64 = labels[n]
58 if pred != lab {
59 mist = mist + 1
60 var j: i64 = 0
61 while j < nh { W[lab*nh+j] = W[lab*nh+j] + h[j]; W[pred*nh+j] = W[pred*nh+j] - h[j]; j = j + 1 }
62 }
63 n = n + 1
64 }
65 last = mist
66 e = e + 1
67 }
68 return last
69}