QBoard » Artificial Intelligence & ML » AI and ML - R » R caret model evaluation with alternate performance metric

R caret model evaluation with alternate performance metric

  • I'm using R's caret package to do some grid search and model evaluation. I have a custom evaluation metric that is a weighted average of absolute error. Weights are assigned at the observation level.
    X <- c(1,1,2,0,1) #feature 1
    w <- c(1,2,2,1,1) #weights
    Y <- 1:5 #target, continuous
    
    #assume I run a model using X as features and Y as target and get a vector of predictions
    
    mymetric <- function(predictions, target, weights){
    
    v <- sum(abs(target-predictions)*weights)/sum(weights) 
    return(v)
    }

    Here an example is given on how to use summaryFunction to define a custom evaluation metric for caret's train(). To quote:

    The trainControl function has a argument called summaryFunction that specifies a function for computing performance. The function should have these arguments:

    data is a reference for a data frame or matrix with columns called obs and pred for the observed and predicted outcome values (either numeric data for regression or character values for classification). Currently, class probabilities are not passed to the function. The values in data are the held-out predictions (and their associated reference values) for a single combination of tuning parameters. If the classProbs argument of the trainControl object is set to TRUE, additional columns in data will be present that contains the class probabilities. The names of these columns are the same as the class levels. lev is a character string that has the outcome factor levels taken from the training data. For regression, a value of NULL is passed into the function. model is a character string for the model being used (i.e. the value passed to the method argument of train).

    I cannot quite figure out how to pass the observation weights to summaryFunction.

     
    This post was edited by Nitara Bobal at July 31, 2020 2:30 PM IST
      July 31, 2020 2:29 PM IST
    0
  • You can't pass in weights directly to the summary function, which is an oversight since you can pass them to the modeling function. If the underlying model accommodates weights, they are used to produce the predicted values.

    I'll add that to the next release.

    Max

      July 31, 2020 2:31 PM IST
    0
  • There are two main conventions for specifying models in R: the formula
    interface and the non–formula (or “matrix”) interface.
    For the former, the predictors are explicitly listed in an R formula that
    looks like: outcome ⇠ var1 + var2 + ....
    For example, the formula
    modelFunction(price ~ numBedrooms + numBaths + acres,
    data = housingData)
    would predict the closing price of a house using three quantitative
    characteristics.

    The shortcut y  . can be used to indicate that all of the columns in the
    data set (except y) should be used as a predictor.
    The formula interface has many conveniences. For example,
    transformations, such as log(acres) can be specified in–line.
    It also autmatically converts factor predictors into dummy variables (using
    a less than full rank encoding). For some R functions (e.g.
    klaR:::NaiveBayes, rpart:::rpart, C50:::C5.0, . . . ), predictors are kept
    as factors.
    Unfortunately, R does not eciently store the information about the
    formula. Using this interface with data sets that contain a large number of
    predictors may unnecessarily slow the computations.
      August 2, 2021 3:00 PM IST
    0
  • The function postResample can be used to estimate the root mean squared error (RMSE), simple R2, and the mean absolute error (MAE) for numeric outcomes. For example:

    library(mlbench)
    data(BostonHousing)
    
    set.seed(280)
    bh_index <- createDataPartition(BostonHousing$medv, p = .75, list = FALSE)
    bh_tr <- BostonHousing[ bh_index, ]
    bh_te <- BostonHousing[-bh_index, ]
    
    set.seed(7279)
    lm_fit <- train(medv ~ . + rm:lstat,
                    data = bh_tr, 
                    method = "lm")
    bh_pred <- predict(lm_fit, bh_te)
    
    lm_fit
    ## Linear Regression 
    ## 
    ## 381 samples
    ##  13 predictor
    ## 
    
    
    ## No pre-processing
    ## Resampling: Bootstrapped (25 reps) 
    ## Summary of sample sizes: 381, 381, 381, 381, 381, 381, ... 
    ## Resampling results:
    ## 
    ##   RMSE      Rsquared   MAE     
    ##   4.374098  0.7724562  2.963927
    ## 
    
    
    ## Tuning parameter 'intercept' was held constant at a value of TRUE
    postResample(pred = bh_pred, obs = bh_te$medv)
    ##      RMSE  Rsquared       MAE 
    ## 4.0927043 0.8234427 2.8163731​


    A note about how R2 is calculated by caret: it takes the straightforward approach of computing the correlation between the observed and predicted values (i.e. R) and squaring the value. When the model is poor, this can lead to differences between this estimator and the more widely known estimate derived form linear regression models. Mostly notably, the correlation approach will not generate negative values of R2 (which are theoretically invalid). A comparison of these and other estimators can be found in Kvalseth 1985.

      August 9, 2021 1:51 PM IST
    0