The following code, mostly copied from
works fine.
module SVMModule
open Accord.MachineLearning
open Accord.MachineLearning.VectorMachines
open Accord.MachineLearning.VectorMachines.Learning
open Accord.Statistics.Kernels
open Accord.Math.Optimization.Losses
// open MathNet.Numerics.LinearAlgebra.Matrix
let inputs = [| [| 0.; 0. |]; [| 0.; 1. |]; [| 1.; 0. |]; [| 1.; 1. |] |]
let xor = [| 0; 1; 1; 0 |]
/// Creates and trains a Support Vector Machine given inputs and outputs.
/// The kernel can be Linear, Gaussian, or Polynomial.
/// The default tolerance is 1e-2.
let train (C: float) (tol: float) (inputs: float [] []) =
let learn = SequentialMinimalOptimization<Gaussian>()
learn.UseComplexityHeuristic <- true
learn.UseKernelEstimation <- true
if C >= 0. then learn.Complexity <- C
if tol > 0. then learn.Tolerance <- tol
let svm = learn.Learn(inputs, xor)
svm
let svm = train 0.5 1e-2 inputs
let prediction = svm.Decide inputs
printfn "SVM_0 Prediction: %A" prediction
I would like to implement a polymorphic version of train
, something like
let train (kernel: string) (C: float) (tol: float) (inputs: float [] []) =
let learn =
if kernel = "Gaussian" then
SequentialMinimalOptimization<Gaussian>()
else
SequentialMinimalOptimization<Linear>()
// More code
This does not work because an if
expression must return objects of the same type in all its branches.
I wonder if there is a way to pass Linear
or Gaussian
as a type to train
(these are indeed types) so that I do not have to write one train function for each type (trainGaussian
and trainLinear
). Akso, even if I took the trouble of writing these separate functions, I guess it would be difficult to call them at runtime depending on a user choice, as the same problem with an if
statement would rear its ugly head.
I have implemented polymorphism in F#
using interfaces, but with classes I built myself. These classes are in Accord.NET
and even though they inherit from a base class I was not able to handle the type issue and implement polymorphism.
Thanks for any suggestions.
It should be straightforward to simply replace the concrete type
Gaussian
with a type parameter like't
(and, optionally, add it as an explicit type parameter totrain
). I've cleaned up your existing code very slightly while doing so:Then at the call-site, there will need to be some way for the compiler to know what type to use, either by passing it in explicitly:
or by relying on type inference to flow the types from another part of your program: