train-kit / src / ardegazu / train / model.cljs
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
;; ported-from: src/model.ts @ v1.0.0 (extracted-from: bot/src/rl/policy.ts @ fa686ee)
;;
;; Model shapes shared between a trainer (which writes them) and live bots
;; (which only ever run inference). Checkpoints are plain JSON — a trainer may
;; use tfjs to fit a net, but what lands on disk is framework-free and the
;; bots replay it with the tiny forward pass in forward.cljs.
;;
;; The MlpJson / MlpModel / TabularModel / AnyModel shapes are documented in
;; types/index.d.ts — the runtime here only guards structure.
(ns ardegazu.train.model)

(defn is-mlp-model
  "Structural guard for an MLP checkpoint; `game` (optional) also narrows."
  ([m] (is-mlp-model m js/undefined))
  ([m game]
   (let [x m]
     (if ^boolean (js* "(!!~{})" x)
       (and (identical? (.-v ^js x) 1)
            (string? (.-game ^js x))
            (or (undefined? game) (identical? (.-game ^js x) game))
            (let [net (.-net ^js x)]
              (and (js/Array.isArray (when (some? net) (.-sizes ^js net)))
                   (js/Array.isArray (when (some? net) (.-layers ^js net))))))
       false))))

(defn is-tabular-model
  "Structural guard for a tabular-Q checkpoint; `game` (optional) also narrows."
  ([m] (is-tabular-model m js/undefined))
  ([m game]
   (let [x m]
     (if ^boolean (js* "(!!~{})" x)
       (and (identical? (.-v ^js x) 1)
            (string? (.-game ^js x))
            (or (undefined? game) (identical? (.-game ^js x) game))
            ^boolean (js* "(typeof ~{} === 'object' && ~{} !== null)" (.-q ^js x) (.-q ^js x)))
       false))))

(defn is-model
  "Any structurally valid checkpoint (callers narrow with the guards above)."
  [m]
  (or (is-mlp-model m) (is-tabular-model m)))

(defn pick-action
  "Epsilon-greedy over action values (ties break to the first max)."
  ([qs epsilon] (pick-action qs epsilon js/Math.random))
  ([qs epsilon rand]
   (if (< (rand) epsilon)
     (js/Math.floor (* (rand) (.-length ^js qs)))
     (let [n (.-length ^js qs)]
       (loop [i 1 best 0]
         (if (< i n)
           (recur (inc i) (if (> (aget qs i) (aget qs best)) i best))
           best))))))

static mirror of HEAD · about · clone: git clone https://git.ardegazu.ro/train-kit.git