Skip to content

Commit edc3886

Browse files
committed
Add overfitting parabola example
1 parent cb40cd8 commit edc3886

1 file changed

Lines changed: 84 additions & 31 deletions

File tree

src/mlp/main.clj

Lines changed: 84 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@
3737
self
3838
{"fc1" (nn/Linear 1 n-hidden)
3939
"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)})
4142
nil))
4243
"forward"
4344
(py/make-instance-fn
@@ -46,7 +47,9 @@
4647
x (F/sigmoid x)
4748
x (py. self fc2 x)
4849
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)]
5053
x)))}))
5154

5255
(defmacro without-gradient
@@ -58,10 +61,11 @@
5861
(finally
5962
(py. no-grad# ~'__exit__ nil nil nil)))))
6063

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]))))
6569

6670
(def dataset (data/TensorDataset features labels))
6771

@@ -74,28 +78,77 @@
7478
(def dev-ds (nth splits 1))
7579
(def test-ds (nth splits 2))
7680

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

Comments
 (0)