4  Clojure with Scikit Learn Algorithm

(ns assignment.sklearn
  (:require
    [assignment.eda :refer [liver-disease]]
    [assignment.scicloj :refer [col-order]]
    [calc-metric.patch] ;eval from milliseconds to nanoseconds
    [fastmath.stats :as stats]
    [scicloj.ml.core :as ml]
    [scicloj.ml.dataset :as ds]
    [scicloj.ml.metamorph :as mm]
    [scicloj.sklearn-clj.ml]
    [utils.helpful-extracts
     :refer [best-models evaluate-pipe extract-params model->ds]]))

Define regressor and response

(def response :drinks)
(def regressors
  (remove #(= response %) (ds/column-names liver-disease)))

4.1 Build pipelines

(def pipeline-fn
  (ml/pipeline
    (mm/remove-column :selector)
    (mm/std-scale regressors {})
    (mm/set-inference-target response)))

In scikit.learn’s implementation of elastic net, it takes an alpha value, where \(alpha = 0\) is a ridge regression model, \(alpha = 1\) is a lasso regression model, and \(0 < alpha < 1\) is strictly an elastic net model that combines the loss functions of both ridge and lasso regression models at differing strengths. Closer to 0 means ridge regression loss function has a heavier consideration and alpha closer to 1 meaning the lasso loss function has a heavier consideration. (This is in general, there is an optional l1-ratio parameter that will change the above interpretation.)

(defn sklearn-pipe-fn [params]
  (ml/pipeline
    pipeline-fn
    {:metamorph/id :model}
    (mm/model (merge {:model-type     :sklearn.regression/elastic-net
                      :predict-proba? false}
                     params))))

4.2 Partition data

(def ds-split                                               ;:split-names [:train-val :test]
  (ds/split->seq liver-disease :kfold {:seed 123 :k 5 :ratio [0.8 0.2]}))
(def train-val-splits
  (ds/split->seq
    (:train (first ds-split))
    :kfold {:seed 123 :k 5}))

4.3 Evaluate pipelines

(def sklearn-pipelines
  (->>
    (ml/sobol-gridsearch {:alpha (ml/linear 0 1 250)})      ;doesnt like l1-ratio, why??
    (map sklearn-pipe-fn)))
(def evaluations-sklearn
  (ml/evaluate-pipelines
    sklearn-pipelines
    train-val-splits
    stats/omega-sq
    :accuracy
    {:other-metrices                   [{:name :mae :metric-fn ml/mae}
                                        {:name :rmse :metric-fn ml/rmse}]
     :return-best-pipeline-only        false
     :return-best-crossvalidation-only true}))

4.4 Extract models

(def models-sklearn-vals
  (->> (best-models evaluations-sklearn)
       reverse))
(-> models-sklearn-vals first :metric)
0.3641237206779405
(-> models-sklearn-vals first :params)
{:model-type :sklearn.regression/elastic-net,
 :predict-proba? false,
 :alpha 1.0}
(-> models-sklearn-vals first :fit-ctx :model :model-data :attributes :intercept_)
3.567873303167421
(-> models-sklearn-vals first :fit-ctx :model :model-data :attributes :coef_)
[0.23816559 0.         0.         0.16579044 0.25591104]
(-> (model->ds models-sklearn-vals 5)
    (ds/reorder-columns col-order))

_unnamed [5 7]:

:model-type :compute-time-ns :alpha :adj-r2 :mae :rmse :predict-proba?
:sklearn.regression/elastic-net 6331770 1.00000000 0.36412372 2.77538202 3.27570429 false
:sklearn.regression/elastic-net 4065197 0.99598394 0.36409472 2.77449564 3.27469312 false
:sklearn.regression/elastic-net 3652424 0.99196787 0.36406587 2.77360744 3.27368066 false
:sklearn.regression/elastic-net 3245103 0.98795181 0.36403717 2.77271740 3.27266689 false
:sklearn.regression/elastic-net 4218376 0.98393574 0.36400862 2.77182552 3.27165183 false
(-> (model->ds models-sklearn-vals 5)
    (ds/reorder-columns col-order)
    (ds/order-by :adj-r2 :desc))

_unnamed [5 7]:

:model-type :compute-time-ns :alpha :adj-r2 :mae :rmse :predict-proba?
:sklearn.regression/elastic-net 6331770 1.00000000 0.36412372 2.77538202 3.27570429 false
:sklearn.regression/elastic-net 4065197 0.99598394 0.36409472 2.77449564 3.27469312 false
:sklearn.regression/elastic-net 3652424 0.99196787 0.36406587 2.77360744 3.27368066 false
:sklearn.regression/elastic-net 3245103 0.98795181 0.36403717 2.77271740 3.27266689 false
:sklearn.regression/elastic-net 4218376 0.98393574 0.36400862 2.77182552 3.27165183 false

4.5 Build final models for evaluation

(def eval-sklearn
  (evaluate-pipe
    (->> (extract-params models-sklearn-vals 5)             ;use best 3 alphas
         (map sklearn-pipe-fn))
    ds-split))
(def models-sklearn
  (->> (best-models eval-sklearn)
       reverse))
(def top-sklearn
  (-> (model->ds models-sklearn 5)
      (ds/reorder-columns col-order)
      (ds/order-by :adj-r2 :desc)
      (ds/drop-columns :predict-proba?)))
top-sklearn

_unnamed [5 6]:

:model-type :compute-time-ns :alpha :adj-r2 :mae :rmse
:sklearn.regression/elastic-net 3434387 0.98393574 0.26161668 2.30607905 3.04582307
:sklearn.regression/elastic-net 3545495 0.98795181 0.26159480 2.30679512 3.04693277
:sklearn.regression/elastic-net 3777292 0.99196787 0.26157229 2.30750974 3.04804261
:sklearn.regression/elastic-net 5455140 0.99598394 0.26154913 2.30822291 3.04915259
:sklearn.regression/elastic-net 4709301 1.00000000 0.26152532 2.30893464 3.05026269
source: src/assignment/sklearn.clj