🗒️ Resumo
🗒️ 3. Primeiros passos Hands-on
🗒️ 5. Outros tipos de Modelos de Vetores de Suporte
🗒️ Apêndice
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.
kernlab
para Linguagem RO 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.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.
scikit-learn
para PythonO 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.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.
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).