Tutorial de SVM

Posted by Cayan Portela, Fernanda Amorim, Gustavo Monteiro, Jader Martins e Mariana Montenegro on July 13, 2017

Tutorial de SVM

Neste tutorial será trabalhado uma introdução geral a Support Vector Machines (SVM) e uma aplicação básica utilizando o pacote e1071.

O que é o Support Vector Machine?

O Support Vector Machine, também conhecido como Máquina de Suporte Vetorial, foi elaborado com o estudo proposto por Boser, Guyon e Vapnik em 1992. Ele é um algoritmo de aprendizado supervisionado, cujo objetivo é classificar determinado conjunto de pontos de dados que são mapeados para um espaço de características multidimensional usando uma função kernel, abordagem utilizada para classificar problemas. Nela, o limite de decisão no espaço de entrada é representado por um hiperplano em dimensão superior no espaço (VAPNIK et al., 1997 e SARADHI et al., 2005).

De forma mais simples…

O SVM realiza a separação de um conjunto de objetos com diferentes classes, ou seja, utiliza o conceito de planos de decisão. Podemos analisar o uso do SVM com o seguinte exemplo. Na Figura 1 é possível observar duas classes de objetos: azul ou laranja. Essa linha que os separa define o limite em que se encontram os pontos azuis e os pontos laranjas. Ao entrarem novos objetos na análise, estes serão classificados como laranjas se estiverem à direita e como azuis caso situem-se à esquerda. Neste caso, conseguimos separar, por meio de uma linha, o conjunto de objetos em seu respectivo grupo, o que caracteriza um classificador linear.

No entanto, problemas de classificação costumam ser mais elaborados, sendo necessário realizar a separação ótima por meio de estruturas mais complexas. O SVM propõe a classificação de novos objetos (teste) com base em dados disponíveis (treinamento). Como pode-se observar na Figura 2. A separação ótima nesse caso ocorreria com a utilização de uma curva.

Na esquerda da Figura 3 observamos a complexidade em separar os objetos originais. Para mapeá-los, utilizamos um conjunto de funções matemáticas, conhecido como Kernels. Esse mapeamento é conhecido como o processo de reorganização dos objetos.

Observa-se que à direita da Figura 3 há uma separação linear dos objetos. Assim, ao invés de construir uma curva complexa, como no esquema à esquerda; o SVM propõe, nesse caso, essa linha ótima capaz de separar os pontos azuis dos laranjas.

#sensacional #inesquecível

E agora, como posso aplicar esse modelo?

Primeiramente, é necessário carregar os dados que serão estudados. Felizmente esse dataset já está disponível nativamente no R. Para carregá-lo, basta executar o seguinte comando:

data(iris)

Após carregar a base algumas explorações serão feitas:

summary(iris)
head(iris)
tail(iris)
str(iris)

O comando summary apresenta algumas estatísticas das variáveis do dataframe, como média, mediana, máximo, mínimo e quantis.

>summary(iris)
  Sepal.Length    Sepal.Width     Petal.Length    Petal.Width          Species  
 Min.   :4.300   Min.   :2.000   Min.   :1.000   Min.   :0.100   setosa    :50  
 1st Qu.:5.100   1st Qu.:2.800   1st Qu.:1.600   1st Qu.:0.300   versicolor:50  
 Median :5.800   Median :3.000   Median :4.350   Median :1.300   virginica :50  
 Mean   :5.843   Mean   :3.057   Mean   :3.758   Mean   :1.199                  
 3rd Qu.:6.400   3rd Qu.:3.300   3rd Qu.:5.100   3rd Qu.:1.800                  
 Max.   :7.900   Max.   :4.400   Max.   :6.900   Max.   :2.500                  

Os comandos head e tail mostram as primeiras seis linhas e as últimas seis linhas nesta ordem. Já o comando str apresenta a estrutura das variáveis. Por exemplo, se são quantitativas ou categóricas.

> head()
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa

A partir disso, é possível ter uma noção de como são os dados e quais os tipos de variáveis trabalhadas. É muito importante conhecer bem os dados que serão usados.

Como vamos utilizar as variáveis quantitativas ‘Sepal Length’, ‘Sepal Width’, ‘Petal Length’ e ‘Petal Width’ como preditoras para a variável categórica ‘Species’, é interessante observar a correlação entre as covariáveis do modelo.

> names(iris)
[1] "Sepal.Length" "Sepal.Width"  "Petal.Length" "Petal.Width"  "Species"    

> cor(iris[,1:4])
             Sepal.Length Sepal.Width Petal.Length Petal.Width
Sepal.Length    1.0000000  -0.1175698    0.8717538   0.8179411
Sepal.Width    -0.1175698   1.0000000   -0.4284401  -0.3661259
Petal.Length    0.8717538  -0.4284401    1.0000000   0.9628654
Petal.Width     0.8179411  -0.3661259    0.9628654   1.0000000 

Gráficos contam histórias!

Gráficos são uma excelente ferramenta de abstração e apresentação de suas explorações, estudos que atingem maior público são aqueles que usam de todos os recursos póssiveis para tornar a informação o mais inteligivel possivel, vamos visualizar como cada variável se relaciona por um mapa de gradiente, definindo o vermelho (cor quente) para maior correlação entre as variáveis e o azul (cor fria) para menor correlação:

library(lattice)
cor <- cor(iris[,1:4])
rgb.palette <- colorRampPalette(c("blue", "red"), space = "rgb")
levelplot(cor, main="Correlation Iris Dataset", xlab="", ylab="", col.regions=rgb.palette(120))

#voilà

Um belo gráfico de correlação. :sunglasses: Primeiro importamos a biblioteca lattice responsável pela geração de nosso gráfico, armazenamos a matriz de correlação em uma variável e então criamos uma paleta de cores (um array com a definição computacional dessas cores) com a função colorRampPaletter, indo do azul ao vermelho, por fim passamos essas definições a função levelplot que cuidará do resto.

Agora o gráfico definitivo para entendermos os nossos dados, o gráfico de dispersão tridimensional. Temos quatro variáveis mas apenas 3 nos possibilitarão enxergar além!

install.packages("scatterplot3d")
library(scatterplot3d)
colors <- c("#e41a1c", "#377eb8", "#4daf4a")
colors <- colors[as.numeric(iris$Species)]
scatterplot3d(iris[,1:3], pch = 15, color=colors)

Com o pacote scatterplot3d instalado e carregado, definimos 3 cores hexadecimais e salvamos no array colors, então sobrescrevemos esse array com um array referente a espécie substituindo pela cor, especie 1, cor 1, especie 2, cor 2… Por fim passamos todos esses parametros para nossa função que gera nosso gráfico. Como pode ver é clara uma ‘separação’ para os nossos dados, assim não será um trabalho difícil para nossa máquina.

Agora a parte mais esperada… #vamoslá

Para utilizar o SVM, é necessário instalar o pacote e1071 por meio do comando install.packages("e1071"). Aguarde o processo de instalação finalizar e vamos à separação dos dados.

Primeiramente, iremos separar 70% das observações do dataset para ‘calibrarmos’ o modelo e utilizaremos as demais observações para verificar o poder de predição do modelo ajustado.

> dim(iris)
[1] 150   5

> treino <- sample(1:150, 0.7*150)  
> teste <- setdiff(1:150,treino)

> iris_treino <- iris[treino,]
> iris_teste <- iris[teste,]

No pacote e1071, usamos a função svm() para ajustar o modelo de máquina de suporte vetorial. Nota-se que a sintaxe é bastante parecida com as funções lm() e glm() para modelos, lineares e lineares generalizados. Uma vez que declaramos a variável dependente (a variável em que queremos fazer predições), a função automaticamente detecta o seu tipo (categórica ou quantitativa) e utiliza o procedimento adequado para o ajuste do modelo.

> require(e1071)
> modelo1 <- svm(Species ~ . , data = iris_treino)

> summary(modelo1)
Call:
svm(formula = Species ~ ., data = iris_treino)


Parameters:
   SVM-Type:  C-classification 
 SVM-Kernel:  radial 
       cost:  1 
      gamma:  0.25 

Number of Support Vectors:  49

Vimos que foi utilizado o kernel “radial” no modelo proposto, pois é o default (o que a função admite se nada é informado no argumento). A função svm() aceita os seguintes kernels: radial, linear, polynomial e sigmoide.

Diferentes kernels ajustam diferentes modelos e, consequentemente, diferentes valores preditos. Ajustaremos então, um modelo para cada kernel, visando obter uma menor taxa de erro de classificação.

modelo2 <- svm(Species ~ . , kernel = "linear" , data = iris_treino)
modelo3 <- svm(Species ~ . , kernel = "polynomial" , data = iris_treino)
modelo4 <- svm(Species ~ . , kernel = "sigmoid" , data = iris_treino)

Agora aplicamos os modelos ajustados nas observações da base ‘teste’ e, por meio de uma tabela de contingência, comparamos a classificação proposta pelos modelos com a classificação real das observações.

preditos1 <- predict(modelo1,iris_teste)

> table(preditos1,iris_teste$Species)

preditos     setosa versicolor virginica
  setosa         11          0         0
  versicolor      0         20         0
  virginica       0          1        13

Ao realizar o mesmo procedimento para os demais modelos, podemos utilizar a soma dos elementos não pertencentes à diagonal principal como uma medida de erro, já que estes correspodem aos elementos classificados erroneamente.

preditos2 <- predict(modelo2,iris_teste)
preditos3 <- predict(modelo3,iris_teste)
preditos4 <- predict(modelo4,iris_teste)

t1 <- table(preditos1,iris_teste$Species)
t2 <- table(preditos2,iris_teste$Species)
t3 <- table(preditos3,iris_teste$Species)
t4 <- table(preditos4,iris_teste$Species)
> sum(c(t1[lower.tri(t1)],t1[upper.tri(t1)]))
[1] 1
> sum(c(t2[lower.tri(t2)],t2[upper.tri(t2)]))
[1] 1
> sum(c(t3[lower.tri(t3)],t3[upper.tri(t3)]))
[1] 3
> sum(c(t4[lower.tri(t4)],t4[upper.tri(t4)]))
[1] 7

Assim, vimos que o modelo1 (kernel = radial) e o modelo2 (kernel = linear) apresentaram resultados mais satisfatórios, pois erraram apenas uma classificação na base de teste.

Conclusão

O SVM possui grande abrangência de aplicações em diversas áreas, como finanças, biologia, medicina, logística, entre outras. Isso ocorre devido às suas vantagens de aplicação como: bom desempenho de generalização; tratabilidade matemática; interpretação geométrica e a utilização para a exploração de dados não rotulados (YANG et al., 2002). Este tutorial é apenas uma pequena demonstração de como esta poderosa ferramenta pode ser utilizada. Esperamos que tenha sido útil para os nossos leitores!

Referências

BOSER, B. E.; GUYON, I. M.; VAPNIK, V. N. A Training Algorithm for Optimal Margin Classifiers. In: ANNUAL WORKSHOP ON COMPUTACIONAL LEARNING, 5, 1992, Pittsburgh. ACM Press. Pittsburgh: Haussler D, jul 1992. p.144-152 .

DRUCKER, H.; BURGES, C. J.; KAUFMAN, L.; SMOLA, A.; VAPNIK, V. Support vector regression machines. Advances in neural information processing systems, Morgan Kaufmann Publishers, p. 155–161, 1997.

SARADHI, V., KAMIK, H., MITRA, P. A Decomposition Method for Support Vector Clustering. In Proc. of the 2nd International Conference on Intelligent Sensing and Information Processing (ICISIP), p. 268-271, 2005.