class: center, middle, inverse, title-slide #
Statistical Learning:
##
Support Vector Machines
(SVM) ### Prof. Carlos Trucíos
FACC/UFRJ
ctruciosm.github.io
carlos.trucios@facc.ufrj.br
### Grupo de Estudos CIA, – Causal Inference and Analytics – ### 2021-11-19 --- layout: true <a class="footer-link" href="http://ctruciosm.github.io">ctruciosm.github.io — Carlos Trucíos (FACC/UFRJ)</a> ---
## Introdução - Desenvolvido pelo pessoal da computação (1990s) -- - Funciona tanto se os grupos são linearmente separáveis ou não. -- --- class: inverse, right, middle # SVM --- ### SVM: Definições básicas **Hiperplano:** em um espaço de dimensão `\(p\)`, um hiperplano é um subespaço de dimensão `\(p-1\)`. Em termos matemáticos, um hiperplano é definido por `$$\beta_0 + \beta_1 X_1 + \beta_2 X_2 + \cdots + \beta_p X_p = 0$$` -- .panelset[ .panel[.panel-name[p = 2] `$$\underbrace{\beta_0}_{-0.7} + \underbrace{\beta_1}_{0.6} X_1 + \underbrace{\beta_2}_{-1} X_2= 0$$` <img src="ISL_12_files/figure-html/unnamed-chunk-2-1.png" width="50%" /> ] .panel[.panel-name[p = 3] `$$\underbrace{\beta_0}_{0} + \underbrace{\beta_1}_{1} X_1 + \underbrace{\beta_2}_{1} X_2 + \underbrace{\beta_3}_{-1} X_3= 0$$` <img src="imagens/hiperplano.png" width="25%" /> ] ] --- ### SVM: Intuição .center[ <img src="imagens/hiperplano.png" width="35%" /> ] -- E se utilizarmos o hiperplano para dividir as observações que caem acima/abaixo dele? -- Essa é a ideia do SVM (porém, bem mais complexa pois não precisa que a separação seja linear). --- ### SVM: Intuição .center[ <img src="ISL_12_files/figure-html/unnamed-chunk-6-1.png" width="60%" /> ] -- Como escolhemos o melhor hiperplano? (reta, no caso) -- Um critério é maximizar a distância mínima do ponto ao hiperplano! -- .blue[Ou seja, queremos encontrar os] `\(\beta\)`s .blue[que nos levam a esse hiperplano que maximiza a distância mínima do ponto ao hiperplano.] --- ### SVM: Intuição .center[ <img src="ISL_12_files/figure-html/unnamed-chunk-7-1.png" width="60%" /> ] -- Essas três pontos nas margens são chamados de _support vectors_ pois são vetores na dimensão `\(p\)` e porque suportam o hiperplano que maximiza a distância mínima do ponto ao hiperplano. -- Infelizmente, esse hiperplano não sempre existe (ou mesmo que existe não sempre é desejável). -- Mas podemos tentar achar outro tipo de hiperplanos. Por exemplo, podemos permitir que algumas observações estejam do lado errado do hiperplano / margens. --- ### SVM Muitas vezes, lidamos com casos em que um solução linearmente separável não é uma boa opção: .panelset[ .panel[.panel-name[Caso 1] .center[ <img src="imagens/nonlinearcase1.png" width="35%" /> ] ] .panel[.panel-name[Caso 2] .center[ <img src="imagens/nonlinearcase2.png" width="35%" /> ] ] .panel[.panel-name[Caso 3] .center[ <img src="imagens/nonlinearcase3.png" width="35%" /> ] ] ] --- ## SVM **Possíveis soluções:** - Incluir termos polinomiais como variáveis explicativas: `\(X^2, X^3,...\)` (a mesma idea quando trabalhamos com regressão linear). -- - Outra forma de lidar com essa não lineariedade é através de Kernels!!!! -- - **Kernels** são funções que quantificam a similaridade de dois observações. -- No caso linear, basicamente classificamos uma observação dependendo de ela cai acima/abaixo do hiperplano: `$$f(x) = \beta_0 + \underbrace{\beta_1 x_1 + \beta_2 x_2 + \cdots + \beta_k x_k}_{x' \beta}$$` --- class: inverse, right, middle # Implementação no R svm_poly e svm_rbf --- ## Implementação no R .panelset[ .panel[.panel-name[Splitting data] ```r library(tidymodels) library(mlbench) data(BreastCancer) BreastCancer <- BreastCancer %>% select(-Id) %>% drop_na() set.seed(123) data_split <- initial_split(BreastCancer, prop = 3/4, strata = Class) train_data <- training(data_split) test_data <- testing(data_split) ``` ] .panel[.panel-name[Reg. Logistica] ```r model_spec <- logistic_reg() %>% set_mode("classification") %>% set_engine("glm") model_fit <- model_spec %>% fit(Class ~ ., data = train_data) augment(model_fit, new_data = test_data) %>% accuracy(truth = Class, estimate = .pred_class) ``` ``` ## # A tibble: 1 × 3 ## .metric .estimator .estimate ## <chr> <chr> <dbl> ## 1 accuracy binary 0.930 ``` ] .panel[.panel-name[SVM Linear] ```r model_spec <- svm_poly(degree = 1) %>% set_mode("classification") %>% set_engine("kernlab", scaled = FALSE) model_fit <- model_spec %>% fit(Class ~ ., data = train_data) augment(model_fit, new_data = test_data) %>% accuracy(truth = Class, estimate = .pred_class) ``` ``` ## # A tibble: 1 × 3 ## .metric .estimator .estimate ## <chr> <chr> <dbl> ## 1 accuracy binary 0.971 ``` ] .panel[.panel-name[SVM Linear] ```r model_spec <- svm_poly(degree = 1) %>% set_mode("classification") %>% set_engine("kernlab", scaled = FALSE) model_fit <- model_spec %>% set_args(cost = 10) %>% fit(Class ~ ., data = train_data) augment(model_fit, new_data = test_data) %>% accuracy(truth = Class, estimate = .pred_class) ``` ``` ## # A tibble: 1 × 3 ## .metric .estimator .estimate ## <chr> <chr> <dbl> ## 1 accuracy binary 0.959 ``` ] .panel[.panel-name[SVM Poly 2] ```r model_spec <- svm_poly(degree = 2) %>% set_mode("classification") %>% set_engine("kernlab", scaled = FALSE) model_fit <- model_spec %>% fit(Class ~ ., data = train_data) augment(model_fit, new_data = test_data) %>% accuracy(truth = Class, estimate = .pred_class) ``` ``` ## # A tibble: 1 × 3 ## .metric .estimator .estimate ## <chr> <chr> <dbl> ## 1 accuracy binary 0.971 ``` ] .panel[.panel-name[SVM RBF] ```r model_spec <- svm_rbf() %>% set_mode("classification") %>% set_engine("kernlab", scaled = FALSE) model_fit <- model_spec %>% fit(Class ~ ., data = train_data) augment(model_fit, new_data = test_data) %>% accuracy(truth = Class, estimate = .pred_class) ``` ``` ## # A tibble: 1 × 3 ## .metric .estimator .estimate ## <chr> <chr> <dbl> ## 1 accuracy binary 0.965 ``` ] ] --- ## Data-Tips: .pull-left[ <img src="https://octodex.github.com/images/minertocat.png" width="70%" /> ] .pull-right[ - Temos utilizado apenas os valores padrão implementados no SVM. - Aprenda como _tunar_ parametros utilizando o pacote `tidymodels`. Dica: visite a [documentação](https://www.tidymodels.org/find/parsnip/#models) ou faça `args(rand_forest)`/ `args(boost_tree)` para saber quais hiperparâmetros podem ser tunados. **Happy Coding!** ### Referências - [James, G., Witten, D., Hastie, T., and Tibshirani, R. (2013). An Introduction to Statistical Learning with Applications in R. New York: Springer.](https://www.statlearning.com) Chapter 9 - [Chatzidimitriou, K., Diamantopoulos, T., Papamichail, M., and Symeonidis, A. (2018). Practical Machine Learning in R. Leanpub.](https://leanpub.com/practical-machine-learning-r) Chapter 6 ]