4.4 SVM con el paquete kernlab

Hay varios paquetes que implementan este procedimiento (e.g. e1071, Meyer et al., 2020; svmpath, ver T. Hastie et al., 2004), aunque se considera que el más completo es kernlab (Karatzoglou et al., 2004).

La función principal es ksvm() y se suelen considerar los siguientes argumentos:

ksvm(formula, data, scaled = TRUE, type, kernel ="rbfdot", kpar = "automatic",
     C = 1, epsilon = 0.1, prob.model = FALSE, class.weights, cross = 0)
  • formula y data (opcional): permiten especificar la respuesta y las variables predictoras de la forma habitual (e.g. respuesta ~ .; también admite matrices).

  • scaled: vector lógico indicando que predictores serán reescalados; por defecto se reescalan todas las variables no binarias (y se almacenan los valores empleados para ser usados en posteriores predicciones).

  • type (opcional): cadena de texto que permite seleccionar los distintos métodos de clasificación, de regresión o de detección de atípicos implementados (ver ?ksvm); por defecto se establece a partir del tipo de la respuesta: "C-svc", clasificación con parámetro de coste, si es un factor y "eps-svr", regresión épsilon, si la respuesta es numérica.

  • kernel: función núcleo. Puede ser una función definida por el usuario o una cadena de texto que especifique una de las implementadas en el paquete (ver ?kernels); por defecto "rbfdot", kernel radial gausiano.

  • kpar: lista con los hiperparámetros del núcleo. En el caso de "rbfdot", además de una lista con un único componente "sigma" (inversa de la ventana), puede ser "automatic" (valor por defecto) e internamente emplea la función sigest() para seleccionar un valor “adecuado”.

  • C: (hiper)parámetro \(C\) que especifica el coste de la violación de las restricciones; por defecto 1.

  • epsilon: (hiper)parámetro \(\epsilon\) empleado en la función de pérdidas de los métodos de regresión; por defecto 0.1.

  • prob.model: si se establece a TRUE (por defecto es FALSE), se emplean los resultados de la clasificación para ajustar un modelo para estimar las probabilidades (y se podrán calcular con el método predict()).

  • class.weights: vector (con las clases como nombres) con los pesos de una mala clasificación en cada clase.

  • cross: número grupos para validación cruzada; por defecto 0 (no se hace validación cruzada). Si se asigna un valor mayor que 1 se realizará validación cruzada y se devolverá el error en la componente @cross (se puede acceder con la función cross(); y se puede emplear para seleccionar hiperparámetros).

Como ejemplo consideraremos el problema de clasificación con los datos de calidad de vino:

load("data/winetaste.RData")
# Partición de los datos
set.seed(1)
df <- winetaste
nobs <- nrow(df)
itrain <- sample(nobs, 0.8 * nobs)
train <- df[itrain, ]
test <- df[-itrain, ]


library(kernlab)
set.seed(1) 
# Selección de sigma = mean(sigest(taste ~ ., data = train)[-2]) 
# (depende de la semilla)
svm <- ksvm(taste ~ ., data = train,
            kernel = "rbfdot", prob.model = TRUE)
svm
## Support Vector Machine object of class "ksvm" 
## 
## SV type: C-svc  (classification) 
##  parameter : cost C = 1 
## 
## Gaussian Radial Basis kernel function. 
##  Hyperparameter : sigma =  0.0751133799772488 
## 
## Number of Support Vectors : 594 
## 
## Objective Function Value : -494.1409 
## Training error : 0.198 
## Probability model included.
# plot(svm, data = train) produce un error # packageVersion("kernlab") ‘0.9.29’

Podemos evaluar la precisión en la muestra de test empleando el procedimiento habitual:

pred <- predict(svm, newdata = test)
caret::confusionMatrix(pred, test$taste)
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction good bad
##       good  147  45
##       bad    19  39
##                                           
##                Accuracy : 0.744           
##                  95% CI : (0.6852, 0.7969)
##     No Information Rate : 0.664           
##     P-Value [Acc > NIR] : 0.003886        
##                                           
##                   Kappa : 0.3788          
##                                           
##  Mcnemar's Test P-Value : 0.001778        
##                                           
##             Sensitivity : 0.8855          
##             Specificity : 0.4643          
##          Pos Pred Value : 0.7656          
##          Neg Pred Value : 0.6724          
##              Prevalence : 0.6640          
##          Detection Rate : 0.5880          
##    Detection Prevalence : 0.7680          
##       Balanced Accuracy : 0.6749          
##                                           
##        'Positive' Class : good            
## 

Para obtener las estimaciones de las probabilidades, habría que establecer type = "probabilities" al predecir (devolverá una matriz con columnas correspondientes a los niveles)30:

p.est <- predict(svm, newdata = test, type = "probabilities")
head(p.est)
##           good       bad
## [1,] 0.4761934 0.5238066
## [2,] 0.7089338 0.2910662
## [3,] 0.8893454 0.1106546
## [4,] 0.8424003 0.1575997
## [5,] 0.6640875 0.3359125
## [6,] 0.3605543 0.6394457

Este procedimiento está implementado en el método "svmRadial" de caret y considera como hiperparámetros:

library(caret)
# names(getModelInfo("svm")) # 17 métodos
modelLookup("svmRadial")
##       model parameter label forReg forClass probModel
## 1 svmRadial     sigma Sigma   TRUE     TRUE      TRUE
## 2 svmRadial         C  Cost   TRUE     TRUE      TRUE

En este caso la función train() por defecto evaluará únicamente tres valores del hiperparámetro C = c(0.25, 0.5, 1) y fijará el valor de sigma. Alternativamente podríamos establecer la rejilla de búsqueda, por ejemplo:

tuneGrid <- data.frame(sigma = kernelf(svm)@kpar$sigma, # Emplea clases S4
                       C = c(0.5, 1, 5))
set.seed(1)
caret.svm <- train(taste ~ ., data = train, method = "svmRadial", 
                   preProcess = c("center", "scale"),
                   trControl = trainControl(method = "cv", number = 5),
                   tuneGrid = tuneGrid, prob.model = TRUE)
caret.svm
## Support Vector Machines with Radial Basis Function Kernel 
## 
## 1000 samples
##   11 predictor
##    2 classes: 'good', 'bad' 
## 
## Pre-processing: centered (11), scaled (11) 
## Resampling: Cross-Validated (5 fold) 
## Summary of sample sizes: 800, 801, 800, 800, 799 
## Resampling results across tuning parameters:
## 
##   C    Accuracy   Kappa    
##   0.5  0.7549524  0.4205204
##   1.0  0.7599324  0.4297468
##   5.0  0.7549374  0.4192217
## 
## Tuning parameter 'sigma' was held constant at a value of 0.07511338
## Accuracy was used to select the optimal model using the largest value.
## The final values used for the model were sigma = 0.07511338 and C = 1.
varImp(caret.svm)
## ROC curve variable importance
## 
##                      Importance
## alcohol                 100.000
## density                  73.616
## chlorides                60.766
## volatile.acidity         57.076
## total.sulfur.dioxide     45.500
## fixed.acidity            42.606
## pH                       34.972
## sulphates                25.546
## citric.acid               6.777
## residual.sugar            6.317
## free.sulfur.dioxide       0.000
confusionMatrix(predict(caret.svm, newdata = test), test$taste)
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction good bad
##       good  147  45
##       bad    19  39
##                                           
##                Accuracy : 0.744           
##                  95% CI : (0.6852, 0.7969)
##     No Information Rate : 0.664           
##     P-Value [Acc > NIR] : 0.003886        
##                                           
##                   Kappa : 0.3788          
##                                           
##  Mcnemar's Test P-Value : 0.001778        
##                                           
##             Sensitivity : 0.8855          
##             Specificity : 0.4643          
##          Pos Pred Value : 0.7656          
##          Neg Pred Value : 0.6724          
##              Prevalence : 0.6640          
##          Detection Rate : 0.5880          
##    Detection Prevalence : 0.7680          
##       Balanced Accuracy : 0.6749          
##                                           
##        'Positive' Class : good            
## 

References

Hastie, T., Rosset, S., Tibshirani, R., y Zhu, J. (2004). The entire regularization path for the support vector machine. Journal of Machine Learning Research, 5(Oct), 1391-1415.
Karatzoglou, A., Smola, A., Hornik, K., y Zeileis, A. (2004). kernlab - An S4 Package for Kernel Methods in R. Journal of Statistical Software, Articles, 11(9), 1-20. https://doi.org/10.18637/jss.v011.i09
Meyer, D., Dimitriadou, E., Hornik, K., Weingessel, A., y Leisch, F. (2020). e1071: Misc Functions of the Department of Statistics, Probability Theory Group (Formerly: E1071), TU Wien. https://CRAN.R-project.org/package=e1071

  1. Otras opciones son "votes" y "decision" para obtener matrices con el número de votos o los valores de \(m(\mathbf{x})\).↩︎