generateme / Feb 26 2020
Remix of Clojure by
Nextjournal
Bayesian Optimization
DRAFT!
TODO: description
Setup
{:deps {org.clojure/clojure {:mvn/version "1.10.1"} cljplot {:mvn/version "0.0.2-SNAPSHOT"} generateme/fastmath {:mvn/version "1.4.0-SNAPSHOT"} clojure2d {:mvn/version "1.2.0-SNAPSHOT"}}}deps.edn
Extensible Data Notation
(require [cljplot.build :as b] [cljplot.core :refer :all] [fastmath.core :as m] [fastmath.kernel :as k] [fastmath.random :as r] [fastmath.optimization :as o] [fastmath.classification :as cl] [clojure2d.color :as c] [clojure.java.io :as io] [clojure.string :as str])27.5s
Clojure
Usage
(defn black-box-function double [double x double y] (inc (- (- (m/sq x)) (m/sq (dec y)))))(def bounds [[2 4] [-3 3]])(black-box-function 1.0 0.0)0.1s
Clojure
-1
(o/maximize :bobyqa black-box-function {:bounds bounds})0.2s
Clojure
Vector(2) [List(2), -3]
(def bo (o/bayesian-optimization black-box-function {:bounds bounds}))(map (select-keys % [:x :y]) (take 5 bo))1.2s
Clojure
List(5) (Map, Map, Map, Map, Map)
(select-keys (nth bo 25) [:x :y])2.8s
Clojure
Map {:x: List(2), :y: -3.000000003303626}
(first bo)0.3s
Clojure
Map {:x: List(2), :y: -3.0010215642887346, :util-fn: Vector(4), :gp: Vector(4), :xs: List(4), :ys: List(4), :util-best: List(2)}
Function 1d
Function 2d
(def palette (reverse (:rdylbu-9 c/palette-presets)))(def gradient (c/gradient palette))(defn draw-2d [f bounds bayesian-optimizer iteration] (let [{:keys [util-fn gp xs]} (nth bayesian-optimizer iteration) cfg {:x (first bounds) :y (second bounds) :palette palette :contours 30 :gradient gradient}] (xy-chart {:width 700 :height 700} (b/series [:contour-2d f (assoc cfg :position [0 1])] [:scatter xs {:size 10 :color (c/darken (first palette)) :margins {:x [0 0] :y [0 0]} :position [0 1] :label "2d function with guessed points."}] [:function-2d util-fn (assoc cfg :position [0 0] :label "Utility function")] [:contour-2d (fn [x y] (gp [x y])) (assoc cfg :position [1 1] :label "Gaussian processes - mean (interpolation)")] [:contour-2d (fn [x y] (second (gp [x y] true))) (assoc cfg :position [1 0] :label "Gaussian processes - std dev")]) (b/add-axes :bottom) (b/add-axes :left))))0.2s
Clojure
user/draw-2d
(defn black-box-function2 double [double x double y] (+ 100.0 (* (m/sinc (+ 2.0 x y)) (m/sin (+ x x)) (m/cos (+ y y)) (m/sin (* 2.0 x y)))))(def bounds2 [[-1.0 0.5] [-2 -0.5]])(def draw-black-box2 (partial draw-2d black-box-function2 bounds2))(def bo (o/bayesian-optimization black-box-function2 {:bounds bounds2}))(save (draw-black-box2 bo 0) "/results/black-box2.jpg")5.1s
Clojure
(save (draw-black-box2 bo 10) "/results/black-box2-10.jpg")6.0s
Clojure
(save (draw-black-box2 bo 40) "/results/black-box2-40.jpg")11.0s
Clojure
Data normalization
(def bo (o/bayesian-optimization black-box-function2 {:bounds bounds2 :normalize? false}))(save (draw-black-box2 bo 10) "/results/black-box2-not-normalized.jpg")5.2s
Clojure
Utility functions and parameters
(def bo (o/bayesian-optimization black-box-function2 {:bounds bounds2 :noise 0.01 :utility-function-type :ucb :utility-param 0.1}))(save (draw-black-box2 bo 15) "/results/black-box2-ucb-low.jpg")5.4s
Clojure
(def bo (o/bayesian-optimization black-box-function2 {:bounds bounds2 :noise 0.01 :utility-function-type :ucb :utility-param 8}))(save (draw-black-box2 bo 15) "/results/black-box2-ucb-high.jpg")5.3s
Clojure
(def bo (o/bayesian-optimization black-box-function2 {:bounds bounds2 :noise 0.01 :utility-function-type :poi :utility-param 0.01}))(save (draw-black-box2 bo 15) "/results/black-box2-poi-low.jpg")5.5s
Clojure
(def bo (o/bayesian-optimization black-box-function2 {:bounds bounds2 :noise 0.01 :utility-function-type :poi :utility-param 0.9}))(save (draw-black-box2 bo 15) "/results/black-box2-poi-high.jpg")5.0s
Clojure
(def bo (o/bayesian-optimization black-box-function2 {:bounds bounds2 :noise 0.01 :utility-function-type :ei :utility-param 0.01}))(save (draw-black-box2 bo 15) "/results/black-box2-ei-low.jpg")5.4s
Clojure
(def bo (o/bayesian-optimization black-box-function2 {:bounds bounds2 :noise 0.01 :utility-function-type :ei :utility-param 0.9}))(save (draw-black-box2 bo 15) "/results/black-box2-ei-high.jpg")5.4s
Clojure
Kernel
(def bo (o/bayesian-optimization black-box-function2 {:bounds bounds2 :optimizer :cmaes :utility-function-type :ei :kernel (k/kernel :mattern-12 0.1) :noise 0.1}))(save (draw-black-box2 bo 15) "/results/black-box2-narrow.jpg")5.5s
Clojure
(def bo (o/bayesian-optimization black-box-function2 {:bounds bounds2 :utility-function-type :ei :kernel (k/kernel :mattern-12 2) :noise 0.1}))(save (draw-black-box2 bo 15) "/results/black-box2-wide.jpg")5.0s
Clojure
Hyperparameter search
(def dataset (with-open [data (io/reader sonar.csv)] (mapv (-> % (str/trim) (str/split ",") (->> (map read-string))) (line-seq data))))(count dataset)0.6s
Clojure
208
(def xs (map butlast dataset))(def ys (map (comp keyword last) dataset))(frequencies ys)0.3s
Clojure
Map {:R: 97, :M: 111}
Ada boost
(defn ada-boost-params double [double trees double nodes] (let [ada-boost (cl/ada-boost {:number-of-trees (int trees) :max-nodes (int nodes)} xs ys)] (:accuracy (cl/cv ada-boost))))(def ada-bounds [[1 (count dataset)] [2 (count dataset)]])(ada-boost-params 10 20)0.9s
Clojure
0.7548076923076923
(def ada-boost-bo (o/bayesian-optimization ada-boost-params {:init-points 5 :kernel (k/kernel :mattern-52 55.0) :noise 0.05 :utility-param 0.1 :bounds ada-bounds}))(select-keys (first ada-boost-bo) [:x :y])8.3s
Clojure
Map {:x: Vector(2), :y: 0.8461538461538461}
(select-keys (nth ada-boost-bo 20) [:x :y])26.1s
Clojure
Map {:x: List(2), :y: 0.8557692307692307}
(defn draw-2d-2 [bounds bayesian-optimizer iteration] (let [{:keys [gp xs]} (nth bayesian-optimizer iteration) cfg {:x (first bounds) :y (second bounds) :palette palette :contours 30}] (xy-chart {:width 700 :height 300} (b/series [:contour-2d (fn [x y] (gp [x y])) cfg] [:contour-2d (fn [x y] (second (gp [x y] true))) (assoc cfg :position [1 0] :label "Gaussian processes - std dev")] [:scatter xs {:size 10 :color (c/darken (first palette)) :margins {:x [0 0] :y [0 0]} :position [0 0] :label "Gaussian processes - mean (interpolation)"}]) (b/add-axes :bottom) (b/add-axes :left))))(save (draw-2d-2 ada-bounds ada-boost-bo 20) "/results/ada-boost.jpg")3.4s
Clojure
SVM
(defn svm-params double [double cp double cn] (let [cp (m/pow 10 cp) cn (m/pow 10 cn) svm (cl/svm {:c-or-cp cp :cn cn :kernel (k/kernel :gaussian)} xs ys)] (m/log (:accuracy (cl/cv svm)))))(def svm-bounds [[-6 6] [-6 6]])(m/exp (svm-params 1 1))1.8s
Clojure
0.8798076923076923
(def svm-bo (o/bayesian-optimization svm-params {:init-points 5 :kernel (k/kernel :mattern-52 1.5) :utility-param 0.3 :noise 0.05 :bounds svm-bounds}))(m/exp (:y (nth svm-bo 10)))21.6s
Clojure
0.8990384615384615
(save (draw-2d-2 svm-bounds svm-bo 10) "/results/svm.jpg")3.0s
Clojure