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

相關問題