Máquina de vetores de suporte (SVM)
Introdução ao SVM
As máquinas de vetores de suporte (SVMs) são algoritmos de aprendizado de máquina supervisionados poderosos, porém flexíveis, usados para classificação e regressão. Mas geralmente, eles são usados em problemas de classificação. Na década de 1960, os SVMs foram introduzidos pela primeira vez, mas depois foram aprimorados em 1990. Os SVMs têm sua maneira única de implementação em comparação com outros algoritmos de aprendizado de máquina. Ultimamente, eles são extremamente populares devido à sua capacidade de lidar com várias variáveis contínuas e categóricas.
Trabalho de SVM
Um modelo SVM é basicamente uma representação de diferentes classes em um hiperplano no espaço multidimensional. O hiperplano será gerado de forma iterativa pelo SVM para que o erro possa ser minimizado. O objetivo do SVM é dividir os conjuntos de dados em classes para encontrar um hiperplano marginal máximo (MMH).
Os seguintes são conceitos importantes em SVM -
Support Vectors- Os pontos de dados mais próximos do hiperplano são chamados de vetores de suporte. A linha de separação será definida com a ajuda desses pontos de dados.
Hyperplane - Como podemos ver no diagrama acima, é um plano ou espaço de decisão que se divide entre um conjunto de objetos de diferentes classes.
Margin- Pode ser definido como a lacuna entre duas linhas nos pontos de dados do armário de classes diferentes. Pode ser calculada como a distância perpendicular da linha aos vetores de suporte. A margem grande é considerada uma margem boa e a margem pequena é considerada uma margem ruim.
O objetivo principal do SVM é dividir os conjuntos de dados em classes para encontrar um hiperplano marginal máximo (MMH) e isso pode ser feito nas duas etapas a seguir -
Primeiro, o SVM irá gerar hiperplanos iterativamente que segregam as classes da melhor maneira.
Em seguida, ele escolherá o hiperplano que separa as classes corretamente.
Implementando SVM em Python
Para implementar SVM em Python, começaremos com a importação de bibliotecas padrão da seguinte maneira -
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
import seaborn as sns; sns.set()
Em seguida, estamos criando um conjunto de dados de amostra, com dados linearmente separáveis, de sklearn.dataset.sample_generator para classificação usando SVM -
from sklearn.datasets.samples_generator import make_blobs
X, y = make_blobs(n_samples=100, centers=2, random_state=0, cluster_std=0.50)
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='summer');
O seguinte seria a saída após gerar um conjunto de dados de amostra com 100 amostras e 2 clusters -
Sabemos que o SVM oferece suporte à classificação discriminativa. ele divide as classes umas das outras simplesmente encontrando uma linha no caso de duas dimensões ou variedade no caso de várias dimensões. Ele é implementado no conjunto de dados acima da seguinte forma -
xfit = np.linspace(-1, 3.5)
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='summer')
plt.plot([0.6], [2.1], 'x', color='black', markeredgewidth=4, markersize=12)
for m, b in [(1, 0.65), (0.5, 1.6), (-0.2, 2.9)]:
plt.plot(xfit, m * xfit + b, '-k')
plt.xlim(-1, 3.5);
O resultado é o seguinte -
Podemos ver na saída acima que existem três separadores diferentes que discriminam perfeitamente as amostras acima.
Conforme discutido, o principal objetivo do SVM é dividir os conjuntos de dados em classes para encontrar um hiperplano marginal máximo (MMH), portanto, em vez de desenhar uma linha zero entre as classes, podemos traçar ao redor de cada linha uma margem de alguma largura até o ponto mais próximo. Isso pode ser feito da seguinte forma -
xfit = np.linspace(-1, 3.5)
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='summer')
for m, b, d in [(1, 0.65, 0.33), (0.5, 1.6, 0.55), (-0.2, 2.9, 0.2)]:
yfit = m * xfit + b
plt.plot(xfit, yfit, '-k')
plt.fill_between(xfit, yfit - d, yfit + d, edgecolor='none',
color='#AAAAAA', alpha=0.4)
plt.xlim(-1, 3.5);
A partir da imagem acima na saída, podemos facilmente observar as “margens” dentro dos classificadores discriminativos. O SVM escolherá a linha que maximiza a margem.
A seguir, usaremos o classificador de vetor de suporte do Scikit-Learn para treinar um modelo SVM nesses dados. Aqui, estamos usando kernel linear para ajustar SVM da seguinte forma -
from sklearn.svm import SVC # "Support vector classifier"
model = SVC(kernel='linear', C=1E10)
model.fit(X, y)
O resultado é o seguinte -
SVC(C=10000000000.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape='ovr', degree=3, gamma='auto_deprecated',
kernel='linear', max_iter=-1, probability=False, random_state=None,
shrinking=True, tol=0.001, verbose=False)
Agora, para uma melhor compreensão, o seguinte irá traçar as funções de decisão para SVC 2D -
def decision_function(model, ax=None, plot_support=True):
if ax is None:
ax = plt.gca()
xlim = ax.get_xlim()
ylim = ax.get_ylim()
Para avaliar o modelo, precisamos criar a grade da seguinte forma -
x = np.linspace(xlim[0], xlim[1], 30)
y = np.linspace(ylim[0], ylim[1], 30)
Y, X = np.meshgrid(y, x)
xy = np.vstack([X.ravel(), Y.ravel()]).T
P = model.decision_function(xy).reshape(X.shape)
Em seguida, precisamos traçar os limites de decisão e margens da seguinte forma -
ax.contour(X, Y, P, colors='k',
levels=[-1, 0, 1], alpha=0.5,
linestyles=['--', '-', '--'])
Agora, da mesma forma plote os vetores de suporte da seguinte forma -
if plot_support:
ax.scatter(model.support_vectors_[:, 0],
model.support_vectors_[:, 1],
s=300, linewidth=1, facecolors='none');
ax.set_xlim(xlim)
ax.set_ylim(ylim)
Agora, use esta função para ajustar nossos modelos da seguinte maneira -
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='summer')
decision_function(model);
Podemos observar a partir da saída acima que um classificador SVM se ajusta aos dados com margens, ou seja, linhas tracejadas e vetores de suporte, os elementos principais desse ajuste, tocando a linha tracejada. Esses pontos do vetor de suporte são armazenados no atributo support_vectors_ do classificador da seguinte maneira -
model.support_vectors_
O resultado é o seguinte -
array([[0.5323772 , 3.31338909],
[2.11114739, 3.57660449],
[1.46870582, 1.86947425]])
SVM Kernels
Na prática, o algoritmo SVM é implementado com kernel que transforma um espaço de dados de entrada na forma necessária. O SVM usa uma técnica chamada truque do kernel, na qual o kernel pega um espaço de entrada de baixa dimensão e o transforma em um espaço de dimensão superior. Em palavras simples, o kernel converte problemas não separáveis em problemas separáveis, adicionando mais dimensões a ele. Isso torna o SVM mais poderoso, flexível e preciso. A seguir estão alguns dos tipos de kernels usados pelo SVM -
Kernel Linear
Ele pode ser usado como um produto escalar entre quaisquer duas observações. A fórmula do kernel linear é a seguinte -
k (x, x i ) = soma (x * x i )
Pela fórmula acima, podemos ver que o produto entre dois vetores diz & é a soma da multiplicação de cada par de valores de entrada.
Kernel polinomial
É uma forma mais generalizada de kernel linear e distingue espaço de entrada curvo ou não linear. A seguir está a fórmula para o kernel polinomial -
K (x, xi) = 1 + soma (x * xi) ^ d
Aqui d é o grau de polinômio, que precisamos especificar manualmente no algoritmo de aprendizado.
Kernel de função de base radial (RBF)
O kernel RBF, usado principalmente na classificação SVM, mapeia o espaço de entrada em um espaço dimensional indefinido. A fórmula a seguir explica isso matematicamente -
K (x, xi) = exp (-gama * soma ((x - xi ^ 2))
Aqui, gama varia de 0 a 1. Precisamos especificá-lo manualmente no algoritmo de aprendizagem. Um bom valor padrão de gama é 0,1.
Como implementamos o SVM para dados linearmente separáveis, podemos implementá-lo em Python para os dados que não são linearmente separáveis. Isso pode ser feito usando kernels.
Exemplo
A seguir está um exemplo de criação de um classificador SVM usando kernels. Estaremos usando o conjunto de dados iris do scikit-learn -
Começaremos importando os seguintes pacotes -
import pandas as pd
import numpy as np
from sklearn import svm, datasets
import matplotlib.pyplot as plt
Agora, precisamos carregar os dados de entrada -
iris = datasets.load_iris()
A partir deste conjunto de dados, estamos pegando os dois primeiros recursos da seguinte forma -
X = iris.data[:, :2]
y = iris.target
A seguir, vamos traçar os limites do SVM com os dados originais da seguinte forma -
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
h = (x_max / x_min)/100
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
np.arange(y_min, y_max, h))
X_plot = np.c_[xx.ravel(), yy.ravel()]
Agora, precisamos fornecer o valor do parâmetro de regularização da seguinte forma -
C = 1.0
Em seguida, o objeto classificador SVM pode ser criado da seguinte maneira -
Svc_classifier = svm.SVC (kernel = 'linear', C = C) .fit (X, y)
Z = svc_classifier.predict(X_plot)
Z = Z.reshape(xx.shape)
plt.figure(figsize=(15, 5))
plt.subplot(121)
plt.contourf(xx, yy, Z, cmap=plt.cm.tab10, alpha=0.3)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Set1)
plt.xlabel('Sepal length')
plt.ylabel('Sepal width')
plt.xlim(xx.min(), xx.max())
plt.title('Support Vector Classifier with linear kernel')
Resultado
Text(0.5, 1.0, 'Support Vector Classifier with linear kernel')
Para criar classificador SVM com rbf kernel, podemos mudar o kernel para rbf como segue -
Svc_classifier = svm.SVC(kernel='rbf', gamma =‘auto’,C=C).fit(X, y)
Z = svc_classifier.predict(X_plot)
Z = Z.reshape(xx.shape)
plt.figure(figsize=(15, 5))
plt.subplot(121)
plt.contourf(xx, yy, Z, cmap=plt.cm.tab10, alpha=0.3)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Set1)
plt.xlabel('Sepal length')
plt.ylabel('Sepal width')
plt.xlim(xx.min(), xx.max())
plt.title('Support Vector Classifier with rbf kernel')
Resultado
Text(0.5, 1.0, 'Support Vector Classifier with rbf kernel')
Colocamos o valor de gama em 'auto', mas você também pode fornecer seu valor entre 0 e 1.
Prós e contras dos classificadores SVM
Prós dos classificadores SVM
Os classificadores SVM oferecem grande precisão e funcionam bem com espaços dimensionais elevados. Os classificadores SVM basicamente usam um subconjunto de pontos de treinamento, portanto, o resultado usa muito menos memória.
Contras dos classificadores SVM
Eles têm muito tempo de treinamento, portanto, na prática, não são adequados para grandes conjuntos de dados. Outra desvantagem é que os classificadores SVM não funcionam bem com classes sobrepostas.