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
ydata
(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ónsigest()
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 aTRUE
(por defecto esFALSE
), se emplean los resultados de la clasificación para ajustar un modelo para estimar las probabilidades (y se podrán calcular con el métodopredict()
).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óncross()
; 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)
<- winetaste
df <- nrow(df)
nobs <- sample(nobs, 0.8 * nobs)
itrain <- df[itrain, ]
train <- df[-itrain, ]
test
library(kernlab)
set.seed(1)
# Selección de sigma = mean(sigest(taste ~ ., data = train)[-2])
# (depende de la semilla)
<- ksvm(taste ~ ., data = train,
svm 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:
<- predict(svm, newdata = test)
pred ::confusionMatrix(pred, test$taste) caret
## 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:
<- predict(svm, newdata = test, type = "probabilities")
p.est 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:
<- data.frame(sigma = kernelf(svm)@kpar$sigma, # Emplea clases S4
tuneGrid C = c(0.5, 1, 5))
set.seed(1)
<- train(taste ~ ., data = train, method = "svmRadial",
caret.svm 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
Otras opciones son
"votes"
y"decision"
para obtener matrices con el número de votos o los valores de \(m(\mathbf{x})\).↩︎