DeedleとAccord.NETを使ってサポートベクトルマシン(Support Vector Machine, SVM)を実行する

意外とサクっと出来るんじゃないかと思ったが、そうもいかなかった。とりあえずの元データはirisでこれは適当にcsv形式で保存しておいた。とりあえずCross Validation&可視化はなしで予測値をはじき出すまでで結構苦労したのでまとめる。使っているのはAccord.NETという.NETベースの機械学習ライブラリとDeedleというデータ操作ライブラリ。

また、SVMをF#でどうしたらよいのかは大体ここを見ている。

System.Environment.CurrentDirectory <- __SOURCE_DIRECTORY__
//ライブラリへの参照と名前空間をオープン
#r @"..\packages\Accord.2.14.0\lib\net40\Accord.dll"
#r @"..\packages\Accord.Math.2.14.0\lib\net40\Accord.Math.dll"
#r @"..\packages\Accord.Statistics.2.14.0\lib\net40\Accord.Statistics.dll"
#r @"..\packages\Accord.MachineLearning.2.14.0\lib\net40\Accord.MachineLearning.dll"
#r @"..\packages\Deedle.1.0.6\lib\net40\Deedle.dll"
#r @"..\packages\FSharp.Data.2.0.14\lib\net40\FSharp.Data.dll"
#r @"..\packages\FSharp.Charting.0.90.9\lib\net40\FSharp.Charting.dll"
open System
open System.IO
open Accord.MachineLearning
open Accord.MachineLearning.VectorMachines
open Accord.MachineLearning.VectorMachines.Learning
open Accord.Statistics.Kernels
open FSharp.Data
open FSharp.Charting
open Deedle
//同フォルダにあるirisファイルのロード
let iris = Frame.ReadCsv("iris.csv", hasHeaders=true)
//クラスラベル("setosa", "versicolor", "virginica")の数値化
let labels_string = iris.GetColumn<string>("Species").Values
let label_map = labels_string |> Seq.distinct |> Seq.mapi (fun i label -> (label, i)) |> Map.ofSeq
let labels = labels_string |> Seq.map(fun label -> label_map.[label]) |> Seq.toArray
//特徴量となるデータを2次元配列へ
let obs2D = 
    iris |> 
    Frame.sliceCols ["Sepal.Length"; "Sepal.Width"; "Petal.Length"; "Petal.Width"] |> 
    Frame.toArray2D
//特徴/クラス数のカウント
let features = obs2D |> Array2D.length2 
let classes = labels_string |> Seq.distinct |> Seq.length
//二次元配列を"配列の配列"let obs = Array.init (Array2D.length1 obs2D) (fun i -> obs2D.[i, *])
//SVM実行
let algorithm =
    fun (svm: KernelSupportVectorMachine)
        (classInputs: float[][])
        (classOutputs: int[]) (i: int) (j: int) ->
        let strategy = SequentialMinimalOptimization(svm, classInputs, classOutputs)
        strategy :> ISupportVectorMachineLearning
let kernel = Linear()
let svm = new MulticlassSupportVectorMachine(features, kernel, classes)
let learner = MulticlassSupportVectorLearning(svm, obs, labels)
let config = SupportVectorMachineLearningConfigurationFunction(algorithm)
learner.Algorithm <- config 
let error = learner.Run() |> printfn "Error: %f"
let predict = obs |> Array.map (fun o -> svm.Compute(o))

参考

Accord.NETのサイトをよくみるとScatterPlorなんてものが提供されているので、それを使ってみるか…