How can I perform novelty detection with ksvm in R?

2.7k views Asked by At

I am trying to implement a novelty detector using the kernlab library (ksvm function) in R. Here is a simple example of what I am trying to do:

# Training data
xxTrain <- matrix(rnorm(2000), nrow=1000, ncol=2, byrow=TRUE)
y <- rep(1,1000)
classifier <- ksvm(xxTrain, y, type="one-svc", kernel="rbfdot", kpar="automatic")
# Test data
x1 <- rnorm(1000)
scale <- c(rep(1,500), rep(10,100), rep(1,400))
x2 <- rnorm(1000)*scale
xxTest <- matrix(c(x1,x2), nrow=1000, ncol=2, byrow=TRUE)
# Prediction
p <- predict(classifier, xxTest, type="response")
# Visualization
plot(x2, type='l')
lines(x1, col="red")
points(5*as.integer(p), type='l', col="blue")

enter image description here

The figure above is the result I get. The blue trace is the prediction, and it clearly shows a period where its consitently 0. But it does not match in time or width with the outlier in the black trace. There are 100 points (black line) which are of larger amplitude, and the output I get in the blue does not match with the black line.

What am I doing wrong?

1

There are 1 answers

2
January On BEST ANSWER

Here is what you are doing wrong:

xxTest <- matrix(c(x1,x2), nrow=1000, ncol=2, byrow=TRUE)

this should be

xxTest <- matrix(c(x1,x2), nrow=1000, ncol=2, byrow=F )

or better

xxTest <- cbind( x1, x2 )

or simply

p <- predict( classifier, cbind( x1, x2 ), type= "response" )

Result (I have used grey for x2):

enter image description here

Explanation: by specyfying byrow=T, you were taking first the elements of x1 to fill up the first 500 rows (alternatively, column 1 and 2), and then x2 to fill up the remaining 500 rows of xxTest. Since the singularity was at around ~ 500 - 600 in x2, then it turned up in both columns of xxTest at around (500+500)/2 - (500+600)/2 which is 750-800 which is what you can see.