SMO Support Vector Machines and different kernel functions: polynomic, radia-basis and string kernels
This commit is contained in:
parent
c1c7ba0ac5
commit
f91328f5e4
4 changed files with 146 additions and 1 deletions
|
@ -4,12 +4,13 @@
|
||||||
;;
|
;;
|
||||||
|
|
||||||
(ns clj-ml.classifiers
|
(ns clj-ml.classifiers
|
||||||
(:use [clj-ml utils data])
|
(:use [clj-ml utils data kernel-functions])
|
||||||
(:import (java.util Date Random)
|
(:import (java.util Date Random)
|
||||||
(weka.classifiers.trees J48)
|
(weka.classifiers.trees J48)
|
||||||
(weka.classifiers.bayes NaiveBayes)
|
(weka.classifiers.bayes NaiveBayes)
|
||||||
(weka.classifiers.bayes NaiveBayesUpdateable)
|
(weka.classifiers.bayes NaiveBayesUpdateable)
|
||||||
(weka.classifiers.functions MultilayerPerceptron)
|
(weka.classifiers.functions MultilayerPerceptron)
|
||||||
|
(weka.classifiers.functions SMO)
|
||||||
(weka.classifiers Evaluation)))
|
(weka.classifiers Evaluation)))
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,9 +66,24 @@
|
||||||
cols-val)]
|
cols-val)]
|
||||||
(into-array cols-val-a))))
|
(into-array cols-val-a))))
|
||||||
|
|
||||||
|
(defmethod make-classifier-options [:support-vector-machine :smo]
|
||||||
|
([kind algorithm map]
|
||||||
|
(let [cols-val (check-options {:fit-logistic-models "-M"}
|
||||||
|
map
|
||||||
|
[""])
|
||||||
|
cols-val-a (check-option-values {:complexity-constant "-C"
|
||||||
|
:tolerance "-L"
|
||||||
|
:epsilon-roundoff "-P"
|
||||||
|
:folds-for-cross-validation "-V"
|
||||||
|
:random-seed "-W"}
|
||||||
|
map
|
||||||
|
cols-val)]
|
||||||
|
(into-array cols-val-a))))
|
||||||
|
|
||||||
|
|
||||||
;; Building classifiers
|
;; Building classifiers
|
||||||
|
|
||||||
|
|
||||||
(defmacro make-classifier-m
|
(defmacro make-classifier-m
|
||||||
([kind algorithm classifier-class options]
|
([kind algorithm classifier-class options]
|
||||||
`(let [options-read# (if (empty? ~options) {} (first ~options))
|
`(let [options-read# (if (empty? ~options) {} (first ~options))
|
||||||
|
@ -95,6 +111,21 @@
|
||||||
([kind algorithm & options]
|
([kind algorithm & options]
|
||||||
(make-classifier-m kind algorithm MultilayerPerceptron options)))
|
(make-classifier-m kind algorithm MultilayerPerceptron options)))
|
||||||
|
|
||||||
|
(defmethod make-classifier [:support-vector-machine :smo]
|
||||||
|
([kind algorithm & options]
|
||||||
|
(let [options-read (if (empty? options) {} (first options))
|
||||||
|
classifier (new SMO)
|
||||||
|
opts (make-classifier-options :support-vector-machine :smo options-read)]
|
||||||
|
(.setOptions classifier opts)
|
||||||
|
(when (not (empty? (get options-read :kernel-function)))
|
||||||
|
;; We have to setup a different kernel function
|
||||||
|
(let [kernel (get options-read :kernel-function)
|
||||||
|
real-kernel (if (map? kernel)
|
||||||
|
(make-kernel-function (first (keys kernel))
|
||||||
|
(first (vals kernel)))
|
||||||
|
kernel)]
|
||||||
|
(.setKernel classifier real-kernel)))
|
||||||
|
classifier)))
|
||||||
|
|
||||||
;; Training classifiers
|
;; Training classifiers
|
||||||
|
|
||||||
|
|
81
src/clj_ml/kernel_functions.clj
Normal file
81
src/clj_ml/kernel_functions.clj
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
;;
|
||||||
|
;; Kernel functions for SVM classifiers
|
||||||
|
;; @author Antonio Garrote
|
||||||
|
;;
|
||||||
|
|
||||||
|
(ns clj-ml.kernel-functions
|
||||||
|
(:use [clj-ml utils data])
|
||||||
|
(:import (weka.classifiers.functions.supportVector PolyKernel RBFKernel StringKernel)))
|
||||||
|
|
||||||
|
(defmulti make-kernel-function-options
|
||||||
|
"Creates ther right parameters for a kernel-function"
|
||||||
|
(fn [kind map] kind))
|
||||||
|
|
||||||
|
(defmethod make-kernel-function-options :polynomic
|
||||||
|
([kind map]
|
||||||
|
(let [cols-val (check-option-values {:cache-size "-C"
|
||||||
|
:exponent "-E"
|
||||||
|
:use=lower-order-terms "-L"}
|
||||||
|
map
|
||||||
|
[""])]
|
||||||
|
(into-array cols-val))))
|
||||||
|
|
||||||
|
|
||||||
|
(defmethod make-kernel-function-options :radial-basis
|
||||||
|
([kind map]
|
||||||
|
(let [cols-val (check-option-values {:cache-size "-C"
|
||||||
|
:gamma "-G"}
|
||||||
|
map
|
||||||
|
[""])]
|
||||||
|
(into-array cols-val))))
|
||||||
|
|
||||||
|
(defmethod make-kernel-function-options :string
|
||||||
|
([kind map]
|
||||||
|
(let [pre-values-a (if (get map :use-normalization)
|
||||||
|
(if (get map :use-normalization)
|
||||||
|
["-N" "yes"]
|
||||||
|
["-N" "no"])
|
||||||
|
[""])
|
||||||
|
_foo (println (str "pre a" pre-values-a " map " map))
|
||||||
|
pre-values-b (if (get map :pruning)
|
||||||
|
(if (= (get map :pruning)
|
||||||
|
:lambda)
|
||||||
|
(conj (conj pre-values-a "-P") "1")
|
||||||
|
(conj (conj pre-values-a "-P" ) "0"))
|
||||||
|
pre-values-a)
|
||||||
|
_foo (println (str "pre b" pre-values-b))
|
||||||
|
cols-val (check-option-values {:cache-size "-C"
|
||||||
|
:internal-cache-size "-IC"
|
||||||
|
:lambda "-L"
|
||||||
|
:sequence-length "-ssl"
|
||||||
|
:maximum-sequence-length "-ssl-max"}
|
||||||
|
map
|
||||||
|
pre-values-b)]
|
||||||
|
(into-array cols-val))))
|
||||||
|
|
||||||
|
(defmulti make-kernel-function
|
||||||
|
"Creates a new kernel function"
|
||||||
|
(fn [kind & options] kind))
|
||||||
|
|
||||||
|
|
||||||
|
(defmethod make-kernel-function :polynomic
|
||||||
|
([kind & options]
|
||||||
|
(let [dist (new PolyKernel)
|
||||||
|
opts (make-kernel-function-options :polynomic (first-or-default options {}))]
|
||||||
|
(.setOptions dist opts)
|
||||||
|
dist)))
|
||||||
|
|
||||||
|
(defmethod make-kernel-function :radial-basis
|
||||||
|
([kind & options]
|
||||||
|
(let [dist (new RBFKernel)
|
||||||
|
opts (make-kernel-function-options :radial-basis (first-or-default options {}))]
|
||||||
|
(.setOptions dist opts)
|
||||||
|
dist)))
|
||||||
|
|
||||||
|
(defmethod make-kernel-function :string
|
||||||
|
([kind & options]
|
||||||
|
(let [dist (new StringKernel)
|
||||||
|
opts (make-kernel-function-options :string (first-or-default options {}))]
|
||||||
|
(.setOptions dist opts)
|
||||||
|
dist)))
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
(:use [clj-ml classifiers data] :reload-all)
|
(:use [clj-ml classifiers data] :reload-all)
|
||||||
(:use [clojure.test]))
|
(:use [clojure.test]))
|
||||||
|
|
||||||
|
|
||||||
(deftest make-classifiers-options-c45
|
(deftest make-classifiers-options-c45
|
||||||
(let [options (make-classifier-options :decission-tree :c45 {:unpruned true :reduced-error-pruning true :only-binary-splits true :no-raising true
|
(let [options (make-classifier-options :decission-tree :c45 {:unpruned true :reduced-error-pruning true :only-binary-splits true :no-raising true
|
||||||
:no-cleanup true :laplace-smoothing true :pruning-confidence 0.12 :minimum-instances 10
|
:no-cleanup true :laplace-smoothing true :pruning-confidence 0.12 :minimum-instances 10
|
||||||
|
@ -79,6 +80,11 @@
|
||||||
res (classifier-evaluate c :dataset ds tds)]
|
res (classifier-evaluate c :dataset ds tds)]
|
||||||
(is (= 26 (count (keys res))))))
|
(is (= 26 (count (keys res))))))
|
||||||
|
|
||||||
|
(deftest make-classifier-svm-smo-polykernel
|
||||||
|
(let [svm (make-classifier :support-vector-machine :smo {:kernel-function {:polynomic {:exponent 2.0}}})]
|
||||||
|
(is (= weka.classifiers.functions.supportVector.PolyKernel
|
||||||
|
(class (.getKernel svm))))))
|
||||||
|
|
||||||
|
|
||||||
(deftest classifier-evaluate-cross-validation
|
(deftest classifier-evaluate-cross-validation
|
||||||
(let [c (make-classifier :decission-tree :c45)
|
(let [c (make-classifier :decission-tree :c45)
|
||||||
|
|
27
test/clj_ml/kernel_functions_test.clj
Normal file
27
test/clj_ml/kernel_functions_test.clj
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
(ns clj-ml.kernel-functions-test
|
||||||
|
(:use [clj-ml kernel-functions] :reload-all)
|
||||||
|
(:use [clojure.test]))
|
||||||
|
|
||||||
|
(deftest make-kernel-function-polynomic
|
||||||
|
(let [kernel (clj-ml.kernel-functions/make-kernel-function :polynomic {:exponent 0.3})
|
||||||
|
options (.getOptions kernel)]
|
||||||
|
(is (= (aget options 2)
|
||||||
|
"-E"))
|
||||||
|
(is (= (aget options 3)
|
||||||
|
"0.3"))))
|
||||||
|
|
||||||
|
(deftest make-kernel-function-radial-basis
|
||||||
|
(let [kernel (clj-ml.kernel-functions/make-kernel-function :radial-basis {:gamma 0.3})
|
||||||
|
options (.getOptions kernel)]
|
||||||
|
(is (= (aget options 2)
|
||||||
|
"-G"))
|
||||||
|
(is (= (aget options 3)
|
||||||
|
"0.3"))))
|
||||||
|
|
||||||
|
(deftest make-kernel-function-string
|
||||||
|
(let [kernel (clj-ml.kernel-functions/make-kernel-function :string {:lambda 0})
|
||||||
|
options (.getOptions kernel)]
|
||||||
|
(is (= (aget options 6)
|
||||||
|
"-L"))
|
||||||
|
(is (= (aget options 7)
|
||||||
|
"0.0"))))
|
Loading…
Reference in a new issue