9.13 Lab: Support Vector Classifier
library("tidymodels")
library("kernlab") # We'll use the plot method from this.set.seed(1)
sim_data <- matrix(
rnorm (20 * 2),
ncol = 2,
dimnames = list(NULL, c("x1", "x2"))
) %>%
as_tibble() %>%
mutate(
y = factor(c(rep(-1, 10), rep(1, 10)))
) %>%
mutate(
x1 = ifelse(y == 1, x1 + 1, x1),
x2 = ifelse(y == 1, x2 + 1, x2)
)
sim_data %>%
ggplot() +
aes(x1, x2, color = y) +
geom_point() +
labs(title = "Trying to make a hyperplane classifier",
subtitle = "simulated data",
caption = "R4DS book club") +
theme_minimal()
# generated this using their process then saved it to use here.
test_data <- readRDS("data/09-testdat.rds") %>%
rename(x1 = x.1, x2 = x.2)
test_data %>%
ggplot() +
aes(x1, x2, color = y) +
geom_point() +
labs(title = "Trying to make a hyperplane classifier",
subtitle = "simulated data",
caption = "R4DS book club") +
theme_minimal()
We create a spec for a model, which we’ll update throughout this lab with different costs.
svm_linear_spec <- svm_poly(degree = 1) %>%
set_mode("classification") %>%
set_engine("kernlab", scaled = FALSE)Then we do a couple fits with manual cost.
svm_linear_fit_10 <- svm_linear_spec %>%
set_args(cost = 10) %>%
fit(y ~ ., data = sim_data)
svm_linear_fit_10## parsnip model object
##
## Support Vector Machine object of class "ksvm"
##
## SV type: C-svc (classification)
## parameter : cost C = 10
##
## Polynomial kernel function.
## Hyperparameters : degree = 1 scale = 1 offset = 1
##
## Number of Support Vectors : 7
##
## Objective Function Value : -52.4483
## Training error : 0.15
## Probability model included.
svm_linear_fit_10 %>%
extract_fit_engine() %>%
plot()
svm_linear_fit_01 <- svm_linear_spec %>%
set_args(cost = 0.1) %>%
fit(y ~ ., data = sim_data)
svm_linear_fit_01## parsnip model object
##
## Support Vector Machine object of class "ksvm"
##
## SV type: C-svc (classification)
## parameter : cost C = 0.1
##
## Polynomial kernel function.
## Hyperparameters : degree = 1 scale = 1 offset = 1
##
## Number of Support Vectors : 16
##
## Objective Function Value : -1.189
## Training error : 0.05
## Probability model included.
svm_linear_fit_01 %>%
extract_fit_engine() %>%
plot()
svm_linear_fit_001 <- svm_linear_spec %>%
set_args(cost = 0.01) %>%
fit(y ~ ., data = sim_data)
svm_linear_fit_001## parsnip model object
##
## Support Vector Machine object of class "ksvm"
##
## SV type: C-svc (classification)
## parameter : cost C = 0.01
##
## Polynomial kernel function.
## Hyperparameters : degree = 1 scale = 1 offset = 1
##
## Number of Support Vectors : 20
##
## Objective Function Value : -0.1859
## Training error : 0.25
## Probability model included.
svm_linear_fit_001 %>%
extract_fit_engine() %>%
plot()
9.13.1 Tuning
Let’s find the best cost.
svm_linear_wf <- workflow() %>%
add_model(
svm_linear_spec %>% set_args(cost = tune())
) %>%
add_formula(y ~ .)
set.seed(1234)
sim_data_fold <- vfold_cv(sim_data, strata = y)
param_grid <- grid_regular(cost(), levels = 10)
# Our grid isn't identical to the book, but it's close enough.
param_grid## # A tibble: 10 × 1
## cost
## <dbl>
## 1 0.000977
## 2 0.00310
## 3 0.00984
## 4 0.0312
## 5 0.0992
## 6 0.315
## 7 1
## 8 3.17
## 9 10.1
## 10 32
tune_res <- tune_grid(
svm_linear_wf,
resamples = sim_data_fold,
grid = param_grid
)
# We ran this locally and then saved it so everyone doesn't need to wait for
# this to process each time they build the book.
# saveRDS(tune_res, "data/09-tune_res.rds")autoplot(tune_res)Tune can pull out the best result for us.
best_cost <- select_best(tune_res, metric = "accuracy")
svm_linear_final <- finalize_workflow(svm_linear_wf, best_cost)
svm_linear_fit <- svm_linear_final %>% fit(sim_data)
svm_linear_fit %>%
augment(new_data = test_data) %>%
conf_mat(truth = y, estimate = .pred_class)## Truth
## Prediction -1 1
## -1 9 1
## 1 2 8
\[\text{accuracy} = \frac{9 + 8}{9 + 1 + 2 + 8} = 0.85\]
svm_linear_fit_001 %>%
augment(new_data = test_data) %>%
conf_mat(truth = y, estimate = .pred_class)## Truth
## Prediction -1 1
## -1 11 6
## 1 0 3
\[\text{accuracy} = \frac{11 + 3}{11 + 6 + 0 + 3} = 0.70\]
9.13.2 Linearly separable data
sim_data_sep <- sim_data %>%
mutate(
x1 = ifelse(y == 1, x1 + 0.5, x1),
x2 = ifelse(y == 1, x2 + 0.5, x2)
)
sim_data_sep %>%
ggplot() +
aes(x1, x2, color = y) +
geom_point()
svm_fit_sep_1e5 <- svm_linear_spec %>%
set_args(cost = 1e5) %>%
fit(y ~ ., data = sim_data_sep)
svm_fit_sep_1e5## parsnip model object
##
## Support Vector Machine object of class "ksvm"
##
## SV type: C-svc (classification)
## parameter : cost C = 1e+05
##
## Polynomial kernel function.
## Hyperparameters : degree = 1 scale = 1 offset = 1
##
## Number of Support Vectors : 3
##
## Objective Function Value : -24.3753
## Training error : 0
## Probability model included.
svm_fit_sep_1e5 %>%
extract_fit_engine() %>%
plot()
svm_fit_sep_1 <- svm_linear_spec %>%
set_args(cost = 1) %>%
fit(y ~ ., data = sim_data_sep)
svm_fit_sep_1## parsnip model object
##
## Support Vector Machine object of class "ksvm"
##
## SV type: C-svc (classification)
## parameter : cost C = 1
##
## Polynomial kernel function.
## Hyperparameters : degree = 1 scale = 1 offset = 1
##
## Number of Support Vectors : 7
##
## Objective Function Value : -3.5451
## Training error : 0.05
## Probability model included.
svm_fit_sep_1 %>%
extract_fit_engine() %>%
plot()
test_data_sep <- test_data %>%
mutate(
x1 = ifelse(y == 1, x1 + 0.5, x1),
x2 = ifelse(y == 1, x2 + 0.5, x2)
)
svm_fit_sep_1e5 %>%
augment(new_data = test_data_sep) %>%
conf_mat(truth = y, estimate = .pred_class)## Truth
## Prediction -1 1
## -1 9 1
## 1 2 8
\[\text{accuracy} = \frac{9 + 8}{8 + 1 + 2 + 8} = 0.85\]
svm_fit_sep_1 %>%
augment(new_data = test_data_sep) %>%
conf_mat(truth = y, estimate = .pred_class)## Truth
## Prediction -1 1
## -1 9 0
## 1 2 9
\[\text{accuracy} = \frac{9 + 9}{9 + 0 + 2 + 9} = 0.90\]