Soldalma
Soldalma

Reputation: 4758

Why does R.predict.svm return a list of the wrong size?

I am trying to use the R type provider to fit and predict a Support Vector Machines model. I was able to fit the model but when I try to predict the returned vector has the same length as the training vector, which it should not have.

I tried the equivalent code directly in R and the returned list has the correct length.

Why is this happening?

Here is an example:

open System
open RDotNet
open RProvider
open RProvider.stats
open RProvider.e1071

// Random number generator
let rng = Random()
let rand () = rng.NextDouble()

// Generate fake X1 and X2 
let X1s = [ for i in 0 .. 9 -> 10. * rand () ] // length = 10
let X2s = [ for i in 0 .. 9 -> 5. * rand () ] // length = 10

let Z1s = [ for i in 0 .. 5 -> 10. * rand () ] // length = 6
let Z2s = [ for i in 0 .. 5 -> 5. * rand () ] // length = 6

// Build Ys
let Ys = [0;1;0;1;0;1;0;1;0;1]

let XMat =
    ["X1", box X1s; "X2", box X2s]
    |> namedParams
    |> R.cbind

let ZMat =
    ["Z1", box Z1s; "Z2", box Z2s]
    |> namedParams
    |> R.cbind

let svm_model =
    ["x", box XMat; "y", box Ys ; "type", box "C"; "gamma", box 1.0]
    |> namedParams
    |> R.svm

let svm_predict = R.predict(svm_model, ZMat)

let res =
    if svm_predict.Type = RDotNet.Internals.SymbolicExpressionType.IntegerVector then
        svm_predict.AsInteger()
        |> List.ofSeq
    else failwithf "Expecting a Numeric but got a %A" svm_predict.Type

printfn "The predicted values are: %A" res
// The predicted values are: [1; 2; 1; 2; 1; 2; 1; 1; 1; 2]

And here is the original R code:

library(stats)
library(e1071)

// Random number generator
x1 <- 10 * rnorm(10)
x2 <- 5 * rnorm(10)
x = cbind(x1, x2)

z1 <- 10 * rnorm(5)
z2 <- 5 * rnorm(5)
z = cbind(z1, z2)

zs <- c(0,1,0,1,0,1,0,1,0,1)

svm_fit = svm(x=x,y=zs,type="C",gamma=1.0)
svm_pred = predict(svm_fit, z)

print(svm_pred)
1 2 3 4 5 
1 0 1 1 1 
Levels: 0 1

Upvotes: 1

Views: 347

Answers (1)

Tomas Petricek
Tomas Petricek

Reputation: 243041

I suspect the issue might be when passing parameters to the R.predict function. I'm not an expert on SVMs, so I'm not sure what is the result this should give, but when I call it as follows, I get results similar to your R version:

let svm_predict = 
  namedParams ["object", box svm_model; "newdata", box ZMat ]
  |> R.predict 

I think what's going on is that the R type provider infers some information about parameter names of the predict function, but is not able to figure out exactly what the second parameter is - and so rather than providing it as newdata, it provides it as something else.

Upvotes: 2

Related Questions