1

下面的代码,从我可以将类型作为参数传递给此函数吗?

大多复制

http://accord-framework.net/docs/html/T_Accord_MachineLearning_VectorMachines_Learning_SequentialMinimalOptimization.htm

工作正常。

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 

我想实现的train多态的版本,像

let train (kernel: string) (C: float) (tol: float) (inputs: float [] []) = 
    let learn = 
     if kernel = "Gaussian" then 
      SequentialMinimalOptimization<Gaussian>() 
     else 
      SequentialMinimalOptimization<Linear>() 
    // More code 

这不起作用,因为if表达式必须在其所有分支机构返回相同类型的对象。

我不知道是否有一种方式来传递LinearGaussian作为类型train(这些的确是种),这样我就不用写一个火车功能每种类型(trainGaussiantrainLinear)。 Akso,即使我不费吹灰之力编写这些单独的函数,我想根据用户的选择,在运行时很难调用它们,因为与陈述相同的问题会导致其丑陋的后遗症。

我已经使用接口在F#中实现了多态性,但是我自己构建了类。这些类在Accord.NET中,即使它们从基类继承,但我无法处理类型问题并实现多态。

感谢您的任何建议。

回答

4

用类似于't(并且可选地将其作为显式类型参数添加到train)的类型参数简单替换具体类型Gaussian应该很简单。我已经清理现有的代码非常轻微的,而这样做:

let train<'t> (C: float) (tol: float) (inputs: float [] []) = 
    let learn = SequentialMinimalOptimization<'t>(UseComplexityHeuristic = true, UseKernelEstimation = true) 
    if C >= 0. then learn.Complexity <- C 
    if tol > 0. then learn.Tolerance <- tol 

    learn.Learn(inputs, xor) 
在调用点

届时,将需要有某种方式让编译器知道使用什么类型的,无论是通过它在明确:

let svm = train<Gaussian> 0.5 1e-2 inputs 

或依靠类型推断,从你的程序的其他部分流动类型:

let svm:Gaussian = train 0.5 1e-2 inputs 
+1

谢谢。那看起来很有希望但是,当我将你的代码复制到我的.fsx文件中时,我在SequentialMinimalOptimization <'t>下得到了一条红色的波浪线,当't:> IKernel ''消息'A类型参数缺少约束'时。我还错过了什么吗? – Soldalma

+2

@Soldalma - 对不起,我想'SequentialMinimalOptimization <_>'的类型参数是一个约束,如果你添加一个明确的类型参数,你需要在你的定义中包含这个参数(即你需要将它定义为'train <'当't:> IKernel >')。另一方面,如果你从定义中省略了参数(所以它只是'let train(C:float)...'),那么我相信应该推断这个约束,而不需要你做任何额外的工作。 – kvb

+0

再次感谢。两种替代方法都可以工作,但我很惊讶你可以从函数签名中移除该类型,并将其留在函数体中。继续前进,我遇到了另一个障碍。如果类型是Linear,则语句'learn.UseKernelEstimation < - true'会导致运行时错误。有没有办法使用取决于类型的'if'或'match'语句跳过它? – Soldalma

相关问题