|
37 | 37 | self |
38 | 38 | {"fc1" (nn/Linear 1 n-hidden) |
39 | 39 | "fc2" (nn/Linear n-hidden n-hidden) |
40 | | - "fc3" (nn/Linear n-hidden 1)}) |
| 40 | + "fc3" (nn/Linear n-hidden n-hidden) |
| 41 | + "fc4" (nn/Linear n-hidden 1)}) |
41 | 42 | nil)) |
42 | 43 | "forward" |
43 | 44 | (py/make-instance-fn |
|
46 | 47 | x (F/sigmoid x) |
47 | 48 | x (py. self fc2 x) |
48 | 49 | x (F/sigmoid x) |
49 | | - x (py. self fc3 x)] |
| 50 | + x (py. self fc3 x) |
| 51 | + x (F/sigmoid x) |
| 52 | + x (py. self fc4 x)] |
50 | 53 | x)))})) |
51 | 54 |
|
52 | 55 | (defmacro without-gradient |
|
58 | 61 | (finally |
59 | 62 | (py. no-grad# ~'__exit__ nil nil nil))))) |
60 | 63 |
|
61 | | -(def model (ParabolaNet 20)) |
62 | | -(def n 1000) |
63 | | -(def features (torch/sub (torch/mul (torch/rand [n 1]) 6) 3)) |
64 | | -(def labels (torch/mul features features)) |
| 64 | +(def extent 6.0) |
| 65 | +(def n 32) |
| 66 | +(def noise 1.0) |
| 67 | +(def features (torch/sub (torch/mul (torch/rand [n 1]) (* 2 extent)) extent)) |
| 68 | +(def labels (torch/add (torch/mul features features) (torch/mul noise (torch/randn [n 1])))) |
65 | 69 |
|
66 | 70 | (def dataset (data/TensorDataset features labels)) |
67 | 71 |
|
|
74 | 78 | (def dev-ds (nth splits 1)) |
75 | 79 | (def test-ds (nth splits 2)) |
76 | 80 |
|
77 | | -(def data-loader (data/DataLoader train-ds :batch_size 16 :shuffle true)) |
78 | | - |
79 | | -(def criterion (nn/MSELoss)) |
80 | | -(def optimizer (optim/SGD (py. model "parameters") :lr 0.01 :weight_decay 0.0)) |
81 | | - |
82 | | -(py. model train) |
83 | | -(doseq [epoch (range 1000)] |
84 | | - (doseq [[features labels] data-loader] |
85 | | - (py. optimizer zero_grad) |
86 | | - (let [prediction (py. model __call__ features) |
87 | | - loss (py. criterion __call__ prediction labels)] |
88 | | - (py. loss backward) |
89 | | - (py. optimizer step))) |
90 | | - ; (when (= (mod (inc epoch) 100) 0) |
91 | | - ; (println (str "epoch: " (inc epoch) " loss: " (py. loss item)))) |
92 | | - ) |
93 | | - |
94 | | - |
95 | | -(without-gradient |
96 | | - (let [x (range -3.0 3.01 0.01) |
97 | | - y (map (fn [x] (py. (first (py. model __call__ (torch/tensor [x]))) item)) x) |
98 | | - ds (tc/dataset {:x x :y y})] |
99 | | - (-> ds |
100 | | - (plotly/base {:=title "Model" :=mode "lines"}) |
101 | | - (plotly/layer-point {:=x :x :=y :y})))) |
| 81 | +(def train-data-loader (data/DataLoader train-ds :batch_size 4 :shuffle true)) |
| 82 | +(def dev-data-loader (data/DataLoader dev-ds :batch_size 4 :shuffle true)) |
| 83 | + |
| 84 | +(defn average [numbers] |
| 85 | + (/ (reduce + numbers) (count numbers))) |
| 86 | + |
| 87 | +(defn train-epoch |
| 88 | + [train-data-loader criterion model optimizer] |
| 89 | + (py. model train) |
| 90 | + (for [[features labels] train-data-loader] |
| 91 | + (do |
| 92 | + (py. optimizer zero_grad) |
| 93 | + (let [prediction (py. model __call__ features) |
| 94 | + loss (py. criterion __call__ prediction labels)] |
| 95 | + (py. loss backward) |
| 96 | + (py. optimizer step) |
| 97 | + (py. loss item))))) |
| 98 | + |
| 99 | +(defn dev-epoch |
| 100 | + [dev-data-loader criterion model] |
| 101 | + (py. model eval) |
| 102 | + (without-gradient |
| 103 | + (for [[features labels] dev-data-loader] |
| 104 | + (let [prediction (py. model __call__ features) |
| 105 | + loss (py. criterion __call__ prediction labels)] |
| 106 | + (py. loss item))))) |
| 107 | + |
| 108 | +(defn training-run |
| 109 | + [train-data-loader dev-data-loader epochs n-hidden lr] |
| 110 | + (let [model (ParabolaNet n-hidden) |
| 111 | + optimizer (optim/SGD (py. model "parameters") :lr lr :weight_decay 0.0) |
| 112 | + criterion (nn/MSELoss)] |
| 113 | + (loop [epoch 1 train-losses [] dev-losses []] |
| 114 | + (let [train-loss (average (train-epoch train-data-loader criterion model optimizer)) |
| 115 | + dev-loss (average (dev-epoch dev-data-loader criterion model))] |
| 116 | + (if (< epoch epochs) |
| 117 | + (recur (inc epoch) (conj train-losses train-loss) (conj dev-losses dev-loss)) |
| 118 | + {:model model :train-losses (conj train-losses train-loss) :dev-losses (conj dev-losses dev-loss)}))))) |
| 119 | + |
| 120 | +(def result (training-run train-data-loader dev-data-loader 5000 200 0.01)) |
| 121 | + |
| 122 | +(defn plot-model |
| 123 | + [features labels {:keys [model]}] |
| 124 | + (without-gradient |
| 125 | + (let [x (range (- extent) (+ extent 0.01) 0.01) |
| 126 | + y (map (fn [x] (py. (first (py. model __call__ (torch/tensor [x]))) item)) x) |
| 127 | + ds (tc/dataset {:x x :y y}) |
| 128 | + pts (tc/dataset {:x (map first (py/->jvm (py. features tolist))) |
| 129 | + :y (map first (py/->jvm (py. labels tolist)))})] |
| 130 | + (-> ds |
| 131 | + (plotly/base {:=title "Model"}) |
| 132 | + (plotly/layer-point {:=dataset pts :=x :x :=y :y}) |
| 133 | + (plotly/layer-line {:=x :x :=y :y}))))) |
| 134 | + |
| 135 | + |
| 136 | + |
| 137 | +(defn smoothing |
| 138 | + [alpha] |
| 139 | + (fn [coll] |
| 140 | + (reductions (fn [prev-avg current] (+ (* alpha prev-avg) (* (- 1 alpha) current))) |
| 141 | + (first coll) |
| 142 | + (rest coll)))) |
| 143 | + |
| 144 | + |
| 145 | +(plot-model features labels result) |
| 146 | + |
| 147 | +(defn plot-losses |
| 148 | + [{:keys [train-losses dev-losses]} smoothing-fn] |
| 149 | + (-> (tc/dataset {:x (range 1 (count train-losses)) :y (smoothing-fn train-losses)}) |
| 150 | + (plotly/base {:=title "Losses"}) |
| 151 | + (plotly/layer-line {:=x :x :=y :y}) |
| 152 | + (plotly/layer-line {:=dataset (tc/dataset {:x (range 1 (count dev-losses)) :y (smoothing-fn dev-losses)}) :=x :x :=y :y}))) |
| 153 | + |
| 154 | +(plot-losses result (smoothing 0.99)) |
0 commit comments