Running Plumber API Locally

Hi guys, I am trying to make a simple classification model I built into an api with plumber. However, when I run a prediction with the api's Swagger interface, I get the following error message printed in my console and on Swagger UI:

<simpleError in contrasts<-(tmp, value = contr.funs[1 + isOF[nn]]): contrasts can be applied only to factors with 2 or more levels>

Here is the code:

library(plumber)

#* @apiTitle Student Academic Performance API


#* Predict gender based on academic performance
#* @param  math.score The mathematics score
#* @param  reading.score The reading score
#* @param  writing.score The writing score
#* @post /predict

newdata <- function(math.score,reading.score,writing.score){
  
  modelsvm <- readRDS("student_performance.rds")
  
  newdf <- data.frame(
    math.score = c(math.score),
    reading.score = c(reading.score),
    writing.score = c(writing.score)
  )
  
  prediction <- predict(modelsvm,newdf)
  
  return(paste(prediction[[1]]))
  
}

As always, I will be very grateful for your suggestion. Thanks!

Hi @iFeanyi, thanks for posting your plumber question here.

What you are seeing I think is sending character values when the model expect numeric values? If this is the case, you might need to convert them to numeric with as.numeric.


Otherwise, if you expect character values and your models expect factors, keep in mind that when you do

  newdf <- data.frame(
    math.score = c(math.score),
    reading.score = c(reading.score),
    writing.score = c(writing.score)
  )

the levels will be computed from your input data and will not be the same as your training data. You might want to force the input to use your training data levels using

levels(x) <- ...check your model object if it contains the levels somewhere

Another thing, you could move model loading out of the endpoint function, if it does not need to be executed each time the API is called.

You can just put it after the endpoint function.

newdata <- function(math.score,reading.score,writing.score){
  
  newdf <- data.frame(
    math.score = c(math.score),
    reading.score = c(reading.score),
    writing.score = c(writing.score)
  )
  
  prediction <- predict(modelsvm,newdf)
  
  return(paste(prediction[[1]]))
  
}

modelsvm <- readRDS("student_performance.rds")

Hopefully this gets you on the right path.

Have a great day.

Thanks a lot @meztez for your helpful suggestion. Changing the input values to numeric ones indeed solved the problem. Thanks again!

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.