Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add epochs, dropout rate, learning rate options to MLP and example code #10

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 66 additions & 47 deletions src/scicloj/ml/smile/mlp.clj
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,39 @@
[tech.v3.datatype.errors :as errors]

[scicloj.ml.smile.classification :as classification])
(:import smile.classification.MLP
[smile.base.mlp HiddenLayerBuilder OutputLayerBuilder ActivationFunction OutputFunction Cost LayerBuilder]))
(:import
smile.classification.MLP
[smile.base.mlp HiddenLayerBuilder OutputLayerBuilder ActivationFunction OutputFunction Cost LayerBuilder]
smile.math.TimeFunction))


(defn train [feature-ds target-ds options]

"Training function of MLP model. "

(defn train
"Training function of MLP model."
[feature-ds target-ds {:keys [dropout-rate epochs learning-rate]
:or {epochs 1}
:as options}]
(let [mlp (MLP. (ds/column-count feature-ds)
(into-array LayerBuilder (:layer-builders options)))
;;

train-data (into-array
(map
double-array
(ds/value-reader feature-ds)))
y (int-array (seq (get target-ds (first (ds-mod/inference-target-column-names target-ds)))))])
(.update mlp train-data y)
mlp)
y (int-array (seq (get target-ds (first (ds-mod/inference-target-column-names target-ds)))))]
(when (number? dropout-rate)
(.setMomentum mlp (TimeFunction/constant (- 1.0 dropout-rate))))
(when (number? learning-rate)
(.setLearningRate mlp (TimeFunction/constant learning-rate)))
(doseq [x (range epochs)]
(println (format "Training...%d of %d " x epochs))
(.update mlp train-data y))
mlp))






(defn predict
"Predict function for MLP model"
[feature-ds thawed-model {:keys [target-columns
target-categorical-maps
options]}]
_options]}]
(errors/when-not-error target-categorical-maps "target-categorical-maps not found. Target column need to be categorical.")
(let [
target-colname (first target-columns)
Expand All @@ -46,7 +49,7 @@
count)
_ (errors/when-not-error (pos? n-labels) "n-labels equals 0. Something is wrong with the :lookup-table")

predictions (classification/double-array-predict-posterior (:model-data model) feature-ds {} n-labels)
predictions (classification/double-array-predict-posterior (:model-data thawed-model) feature-ds {} n-labels)
finalised-predictions
(-> predictions
(dtt/->tensor)
Expand All @@ -57,26 +60,33 @@
(-> (ds-mod/probability-distributions->label-column finalised-predictions target-colname)
(ds/update-column target-colname
#(vary-meta % assoc :column-type :prediction)))]

mapped-predictions))


(ml/define-model!
:smile.classification/mlp
train
predict
{
:options [{:name :layer-builders
:type :seq
:default []
:description "Sequence of type smile.base.mlp.LayerBuilder describing the layers of the neural network "}]


:documentation {:javadoc "https://haifengl.github.io/api/java/smile/classification/MLP.html"
{:options [{:name :layer-builders
:type :seq
:default []
:description "Sequence of type smile.base.mlp.LayerBuilder describing the layers of the neural network "}
{:name :dropout-rate
:type :float
:default 0.0
:description "Inverse of the Momentum, a simplified variant of Weight Decay."}
{:name :learning-rate
:type :float
:default 0.1
:description "The learning rate"}
{:name :epochs
:type :integer
:default 1
:description "The number of training cycles/weight adjustments to run when calling train."}]

:documentation {:javadoc "https://haifengl.github.io/api/java/smile/classification/MLP.html"
:user-guide "https://haifengl.github.io/classification.html#neural-network"}})




(comment
(do
Expand All @@ -85,23 +95,32 @@
(require '[scicloj.metamorph.ml.loss :as loss])

(def hidden-layer-builder
(HiddenLayerBuilder. 1 (ActivationFunction/linear)))

(def output-layer-builder
(OutputLayerBuilder. 3 (OutputFunction/LINEAR) (Cost/MEAN_SQUARED_ERROR)))

(def src-ds (ds/->dataset "test/data/iris.csv"))
(def ds (-> src-ds
(ds/categorical->number cf/categorical)
(ds-mod/set-inference-target "species")))
(def feature-ds (cf/feature ds))
(def split-data (ds-mod/train-test-split ds))
(def train-ds (:train-ds split-data))
(def test-ds (:test-ds split-data))
(def model (ml/train train-ds {:model-type :smile.classification/mlp
:layer-builders [hidden-layer-builder output-layer-builder]}))
(def prediction
(-> (ml/predict test-ds model)
(ds-cat/reverse-map-categorical-xforms))))

(HiddenLayerBuilder. 1 (ActivationFunction/linear)))

(def output-layer-builder
(OutputLayerBuilder. 3 (OutputFunction/LINEAR) (Cost/MEAN_SQUARED_ERROR)))
;; or, for softmax
(comment
(OutputLayerBuilder. 3 (OutputFunction/SOFTMAX) (Cost/LIKELIHOOD)))

(def dropout-rate 0.45) ;; 0.0 - 1.0, default 0.0 (no momentum)
(def learning-rate 0.1) ;; 0.0 - 1.0
(def epochs 200)

(def src-ds (ds/->dataset "test/data/iris.csv"))
(def ds (-> src-ds
(ds/categorical->number cf/categorical)
(ds-mod/set-inference-target "species")))
(def feature-ds (cf/feature ds))
(def split-data (ds-mod/train-test-split ds))
(def train-ds (:train-ds split-data))
(def test-ds (:test-ds split-data))
(def model (ml/train train-ds {:model-type :smile.classification/mlp
:dropout-rate dropout-rate
:learning-rate learning-rate
:epochs epochs
:layer-builders [hidden-layer-builder output-layer-builder]}))
(def prediction
(-> (ml/predict test-ds model)
(ds-cat/reverse-map-categorical-xforms))))
:ok)