SUMÁRIO

🗒️ Resumo

🗒️ 1. Introdução

🗒️ 2. Fundamentação teórica

🗒️ 3. Primeiros passos Hands-on

🗒️ 4. Aplicações com SVM

🗒️ 5. Outros tipos de Modelos de Vetores de Suporte

🗒️ 6. Exercícios

🗒️ Apêndice


3. Primeiros passos Hands-on

Nesta seção são apresentados os principais pacotes para a utilização do SVM para as linguagens R e Python. Vale ressaltar que existem diversos pacotes para implementação do SVM. Para a linguagem R, tem-se os pacotes kernlab, e1071, rsvm, klaR e svmpath. Para a linguagem Python, tem-se os pacotes sklearn, pylibsvm, SVMlight, SVMpy e PySVM.

Muitos destes pacotes foram construídos ou adaptados da versão original do LIBSVM (Chang e Lin 2011). O LIBSVM é uma biblioteca muito conhecida para SVM e é implementada em C++. Essa biblioteca é altamente eficiente e utilizada usada para diversos tipos de modelos de vetores de suporte.

Neste caso, o kernlab será apresentado brevemente para linguagem R, devido sua versatilidade especificamente para trabalhar com kernels e o pacote sklearn será apresentada para a linguagem Python devido sua simplicidade e popularidade.

Adicionalmente, para ambas as linguagens será gerado um conjunto de dados artificial e linearmente não separável, de tal forma que as fronteiras de decisão possam ser visualizadas em ambas as linguagens. Os códigos em cada seção apresentam o ajuste do kernel polinomial, porém fica como exercício ao leitor a replicação dos códigos para visualizar as demais fronteiras de decisão dadas pelos outros kernels.

Esta seção não terá foco em capacidade preditiva ou na escolha o melhor modelo ajustado, o que será visto na próxima seção.

3.1 Pacote kernlab para Linguagem R

O kernlab (Karatzoglou et al. 2004) visa fornecer ao usuário da Linguagem R várias funcionalidades básicas para os métodos baseados em kernel, sendo o SVM um caso particular. O pacote fornece, por exemplo, como calcular uma matriz do kernel usando uma função kernel específica, bem como métodos de otimização para programação linear e quadrática.

A função específica para ajuste dos classificadores de SVM para esse pacote é a função ksvm, que pode ser utilizada para ajuste de vários tipos de modelos de vetores de suporte. Porém, neste momento iremos focar apenas para classificação, para isso deve utilizar o argumento type='C-svc', o que é utilizado para C-Support Vector Classification.

Dentre os principais argumentos desta função, têm-se:

  • C: Parâmetro de regularização. Valor numérico não positivo. Valor padrão=1;

  • kernel: \(\{\)’vanilladot’, ‘polydot’, ‘rbfdot’ \(\}\). Especifica o tipo de kernel a ser usado no algoritmo. Possui ao total nove tipos de kernels diferentes. O kernel ‘vanilladot’ é o kernel linear, ou seja, sem utilização do truque do kernel. Valor padrão=‘rbfdot’;

  • kpar: especifica a lista de hiperparâmetros do kernel. Esta é uma lista que contém os parâmetros a serem usados com a função kernel. Para parâmetros válidos para kernels existentes são:

    • sigma comprimento inverso da largura do kernel inversa para “rbfdot” e o kernel “laplacedot”;

    • degree, scale, offset para o kernel polinomial “polydot”.

O kernlab também possui uma forma de auto tunagem do parâmetro sigma através da função sigest, a qual utiliza uma heurística para calcular um bom valor sigma para os kernels gaussiano e laplaciano, a partir dos dados. Além disso, através dele é possível declarar funções kernels externamente. Maiores detalhes podem ser consultados em Karatzoglou, Meyer, e Hornik (2006).

#IMPORTANDO PACOTES UTILIZADOS
require(mlbench)
require(kernlab)

## DEFININDO FUNÇÃO PARA PLOT DAS MARGENS
plot_margins <- function(svm, X, y) {
  # valores da amplitude das variáveis de entrada
  xmin <- min(X[, 1])
  xmax <- max(X[, 1])
  ymin <- min(X[, 2])
  ymax <- max(X[, 2])
  
  # criação do grid para avaliar o modelo
  xx <- seq(xmin, xmax, length.out = 30)
  yy <- seq(ymin, ymax, length.out = 30)
  XY <- expand.grid(xx, yy)
  colnames(XY) <- c("X1", "X2")
  
  # predição para o grid
  Z <- predict(svm, newdata = XY, type = "decision")
  Z <- matrix(Z, ncol = length(xx))
  
  # plot da fronteira de decisão
  contour(xx, yy, Z, levels = c(-1, 0, 1), col = c("#bdbdbd", "black", "#bdbdbd"),
          lty = c("dashed", "solid", "dashed"), drawlabels = FALSE, add = TRUE)
}

## GERANDO CONJUNTO DE DADOS n=50
set.seed(1)
dados=data.frame(mlbench.circle(50,d=2))
colnames(dados)=c("X1","X2","Y")

## PLOTANDO CONJUNTO DE DADOS GERADOS
plot(dados[,1:2],col=dados[,3],pch=19)

## AJUSTE DO MODELO SVM COM KERNEL POLINOMIAL DE GRAU 2
svmMOD = ksvm(Y~., dados, C=1, kernel=polydot(degree=2))

## PLOT DAS MARGENS DO MODELO AJUSTADO
plot_margins(svmMOD,dados[,1:2],dados[,3])
legend(0.85,0.95,c(0,1),col=1:2,pch=19,cex=0.7)

## PLOT DOS VETORES DE SUPORTE
points(dados[svmMOD@alphaindex[[1]],1:2],cex=1.5)
Figura 3.1. Fronteiras e margens de decisão do SVM polinomial de grau 2, ajustado em R através do código acima.

Figura 3.1. Fronteiras e margens de decisão do SVM polinomial de grau 2, ajustado em R através do código acima.

Figura 3.2. Fronteiras e margens de decisão do SVM linear, ajustado em R através do código acima.

Figura 3.2. Fronteiras e margens de decisão do SVM linear, ajustado em R através do código acima.

Figura 3.3. Fronteiras e margens de decisão do SVM gaussiano, ajustado em R através do código acima.

Figura 3.3. Fronteiras e margens de decisão do SVM gaussiano, ajustado em R através do código acima.

3.2 Pacote scikit-learn para Python

O scikit-learn é um pacote específico para aprendizado de máquina para a linguagem Python. Esse pacote incorpora diversos algoritmos de classificação, regressão e agrupamento, incluindo implementações eficientes das máquinas de vetores de suporte.

O módulo específico para ajuste dos classificadores de SVM para esse pacote é o módulo sklearn.svm.SVC, sendo SVC também se referindo a C-Support Vector Classification.

Dentre seus principais argumentos, têm-se:

  • C: Parâmetro de regularização. Valor numérico não positivo. Valor padrão=1.0;

  • kernel: \(\{\)’linear’, ‘poly’, ‘rbf’ \(\}\). Especifica o tipo de kernel a ser usado no algoritmo. Valor padrão=‘rbf’;

  • degree: Grau da função kernel polinomial (‘poly’). Deve ser não negativo. Ignorado por todos os outros kernels. Valor padrão=3;

  • gamma: \(\{\)’scale’, ‘auto’\(\}\) ou um valor numérico positivo. Valor padrão=‘scale’. Coeficiente para os kernels ‘rbf’ e ‘poly’.

Mais detalhes sobre outros parâmetros podem ser consultados em Sklearn (2020).

## IMPORTANDO PACOTES UTILIZADOS
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.svm import SVC
from sklearn.datasets import make_circles # utilização do módulo datasets para gerar os dados

## DEFININDO FUNÇÃO PARA PLOT DAS MARGENS
def plot_margins(svm, X, y):
  # valores da amplitude das variáveis de entrada
  xmin, xmax = plt.xlim()
  ymin, ymax = plt.ylim()
  # criação do grid para avaliar o modelo
  xx = np.linspace(xmin, xmax, 30)
  yy = np.linspace(ymin, ymax, 30)
  XX, YY = np.meshgrid(xx, yy)
  xy = np.vstack([XX.ravel(), YY.ravel()]).T
  Z = svm.decision_function(xy).reshape(XX.shape)
  plt.scatter(svm.support_vectors_[:, 0], svm.support_vectors_[:, 1], s=80,facecolors='none', zorder=10, edgecolors='k')
  # plot da fronteira de decisão
  plt.contour(XX, YY, Z, colors=['#bdbdbd','black','#bdbdbd'], levels=[-1, 0, 1], linestyles=['--', '-', '--'])
  plt.show()

## GERANDO CONJUNTO DE DADOS n=50
X, y = make_circles(n_samples=50, noise=0.1, factor=0.5, random_state=1)
df = pd.DataFrame(X,columns=['X1','X2'])

## PLOTANDO CONJUNTO DE DADOS GERADOS
plt.figure()
sns.scatterplot(data=df, x="X1", y="X2",hue=y)
plt.legend(bbox_to_anchor=(0.98, 0.98),borderaxespad=0,fontsize=5)

## AJUSTE DO MODELO SVM COM KERNEL POLINOMIAL DE GRAU 2
svmMOD = SVC(C=1, kernel='poly', degree=2, random_state=1)
svmMOD = svmMOD.fit(X, y)

## PLOT DAS MARGENS DO MODELO AJUSTADO
plot_margins(svmMOD,X, y)
Figura 3.4. Fronteiras e margens de decisão do SVM polinomial de grau 2, ajustado em Python através do código acima.

Figura 3.4. Fronteiras e margens de decisão do SVM polinomial de grau 2, ajustado em Python através do código acima.

Figura 3.5. Fronteiras e margens de decisão do SVM linear, ajustado em Python através do código acima.

Figura 3.5. Fronteiras e margens de decisão do SVM linear, ajustado em Python através do código acima.

Figura 3.6. Fronteiras e margens de decisão do SVM gaussiano, ajustado em Python através do código acima.

Figura 3.6. Fronteiras e margens de decisão do SVM gaussiano, ajustado em Python através do código acima.

3.3 Comentários gerais

De uma forma geral, nem todas as bibliotecas e funcionalidades do Python têm equivalentes exatos no R, portanto, pode ser necessário fazer alguns ajustes. Porém, para este caso foi possível replicar ambos os exemplos introdutórios.

É importante notar algumas diferenças, especificamente os casos acima não utilizam dados com o mesmo comportamento. A função circle do pacote mlbench gera um conjunto de dados, para duas dimensões, em que uma classe está distribuída em um círculo inscrito em um quadrado, ao qual pertence a outra classe. Já a função make_cicles gera duas classes baseadas em circunferências com raios diferentes.

Diferenças sutis ainda permeiam o restante das comparações gerais entre scripts em R e Python, não só para esta aplicação mas para diversos outros tipos de análise de dados. Por isso é sempre sugerido uma leitura atenta de documentação de qualquer linguagem ou software que esteja sendo utilizado.

De uma forma geral para o caso específico de SVM, nota-se a grande diferença da forma de indicação do kernel utilizado, bem como seus hiperparâmetros. Como por exemplo, o kernel polinomal para kernlab tem grau 1 por padrão, mas o kernel polinomal para sklearn tem grau 3 por padrão. Além da grande diferença de a estimação para o hiperparâmetro do kernel gaussiano, o que justifica a grande diferença das fronteiras de decisão geradas pelas Figuras 3.3 e 3.6. Maiores detalhes sobre tais diferenças na estimação do hiperparâmetro gaussiano podem ser consultados em Caputo et al. (2002) e Gondim et al. (2021).

Referências

Caputo, Barbara, K Sim, Fredrik Furesjo, e Alex Smola. 2002. «Appearance-based object recognition using SVMs: which kernel should I use?» Em Proc of NIPS workshop on Statistical methods for computational experiments in visual processing and computer vision, Whistler. Vol. 2002.
Chang, Chih-Chung, e Chih-Jen Lin. 2011. «LIBSVM: a library for support vector machines». ACM transactions on intelligent systems and technology (TIST) 2 (3): 1–27.
Gondim, João, Mateus Maia, Ana Caroline Lopes Rocha, Felipe Argolo, Anderson Ara, e Alexandre Andrade Loch. 2021. «Support Vector Machines in Smile detection: A comparison of auto-tuning standard processes in Gaussian kernel». Em Anais do XVII Workshop de Visão Computacional, 118–23. SBC.
Karatzoglou, Alexandros, David Meyer, e Kurt Hornik. 2006. «Support vector machines in R». Journal of statistical software 15: 1–28.
Karatzoglou, Alexandros, Alexandros Smola, Kurt Hornik, e Achim Zeileis. 2004. «kernlab - An S4 Package for Kernel Methods in R». Journal of Statistical Software 11 (9): 1–20. https://doi.org/10.18637/jss.v011.i09.
Sklearn. 2020. «sklearn.svm.SVC». scikit-learn. https://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html.