Implementando SVM e Kernel SVM com Scikit-Learn do Python

Implementando SVM e Kernel SVM com Scikit-Learn do Python

Introdução

Este guia é a primeira parte de três guias sobre Support Vector Machines (SVMs). Nesta série, trabalharemos em um caso de uso de cédulas falsificadas, aprenderemos sobre o SVM simples, depois sobre os hiperparâmetros do SVM e, finalmente, aprenderemos um conceito chamado truque do kernel e explore outros tipos de SVMs.

Se você deseja ler todos os guias ou ver quais deles mais lhe interessam, segue abaixo a tabela de tópicos abordados em cada guia:

1. Implementando SVM e Kernel SVM com Scikit-Learn do Python

  • Caso de uso: esqueça notas bancárias
  • Histórico de SVMs
  • Modelo SVM Simples (Linear)
    • Sobre o conjunto de dados
    • Importando o conjunto de dados
    • Explorando o conjunto de dados
  • Implementando SVM com Scikit-Learn
    • Dividindo dados em conjuntos de treinamento/teste
    • Treinando o modelo
    • Fazendo previsões
    • Avaliando o Modelo
    • Interpretando os resultados

2. Compreendendo os hiperparâmetros SVM (em breve!)

  • O Hiperparâmetro C
  • O Hiperparâmetro Gama

3. Implementando outros tipos de SVM com Scikit-Learn do Python (em breve!)

  • A ideia geral de SVMs (uma recapitulação)
  • Kernel (truque) SVM
  • Implementando kernel não linear SVM com Scikit-Learn
  • Importando bibliotecas
    • Importando o conjunto de dados
    • Dividindo dados em recursos (X) e alvo (y)
    • Dividindo dados em conjuntos de treinamento/teste
    • Treinando o Algoritmo
  • núcleo polinomial
    • Fazendo previsões
    • Avaliando o Algoritmo
  • Kernel gaussiano
    • Previsão e avaliação
  • Núcleo Sigmoide
    • Previsão e avaliação
  • Comparação de Desempenhos de Kernel Não Lineares

Caso de Uso: Notas Bancárias Falsificadas

Às vezes, as pessoas encontram uma maneira de falsificar notas bancárias. Se houver uma pessoa olhando para essas notas e verificando sua validade, pode ser difícil ser enganado por elas.

Mas o que acontece quando não há uma pessoa para olhar cada nota? Existe uma maneira de saber automaticamente se as notas bancárias são falsas ou reais?

Há muitas maneiras de responder a essas perguntas. Uma resposta é fotografar cada nota recebida, comparar sua imagem com a imagem de uma nota forjada e, então, classificá-la como real ou forjada. Como pode ser tedioso ou crítico aguardar a validação da nota, também seria interessante fazer essa comparação rapidamente.

Como as imagens estão sendo usadas, elas podem ser compactadas, reduzidas a tons de cinza e ter suas medidas extraídas ou quantizadas. Desta forma, a comparação seria entre as medidas das imagens, ao invés do pixel de cada imagem.

Até agora, encontramos uma maneira de processar e comparar as notas bancárias, mas como elas serão classificadas em reais ou falsificadas? Podemos usar o aprendizado de máquina para fazer essa classificação. Existe um algoritmo de classificação chamado Máquina de vetores de suporte, conhecido principalmente por sua forma abreviada: SVM.

Histórico de SVMs

Os SVMs foram introduzidos inicialmente em 1968, por Vladmir Vapnik e Alexey Chervonenkis. Naquela época, seu algoritmo limitava-se à classificação de dados que podiam ser separados por apenas uma linha reta, ou dados que eram linearmente separável. Podemos ver como seria essa separação:

Implementando SVM e Kernel SVM com Scikit-Learn PlatoBlockchain Data Intelligence do Python. Pesquisa vertical. Ai.

Na imagem acima temos uma linha no meio, à qual alguns pontos estão à esquerda, e outros à direita dessa linha. Observe que ambos os grupos de pontos estão perfeitamente separados, não há pontos entre ou mesmo próximos da linha. Parece haver uma margem entre os pontos semelhantes e a linha que os divide, essa margem se chama margem de separação. A função da margem de separação é tornar maior o espaço entre os pontos semelhantes e a linha que os divide. O SVM faz isso usando alguns pontos e calcula seus vetores perpendiculares para apoiar a decisão pela margem da linha. Esses são os vetores de suporte que fazem parte do nome do algoritmo. Vamos entender mais sobre eles mais tarde. E a linha reta que vemos no meio é encontrada por métodos que maximizar aquele espaço entre a linha e os pontos, ou que maximizem a margem de separação. Esses métodos são originários do campo da Teoria da Otimização.

No exemplo que acabamos de ver, ambos os grupos de pontos podem ser facilmente separados, pois cada ponto individual está próximo de seus pontos semelhantes e os dois grupos estão distantes um do outro.

Mas o que acontece se não houver como separar os dados usando uma linha reta? Se houver pontos confusos fora do lugar ou se for necessária uma curva?

Para resolver esse problema, o SVM foi posteriormente refinado na década de 1990 para poder também classificar dados que tinham pontos distantes de sua tendência central, como outliers, ou problemas mais complexos que tinham mais de duas dimensões e não eram separáveis ​​linearmente .

O curioso é que apenas nos últimos anos os SVM's passaram a ser amplamente adotados, principalmente devido à sua capacidade de atingir às vezes mais de 90% de acertos ou precisão, para problemas difíceis.

SVMs são implementados de forma única quando comparados a outros algoritmos de aprendizado de máquina, uma vez que são baseados em explicações estatísticas sobre o que é aprendizado, ou em Teoria da aprendizagem estatística.

Neste artigo, veremos o que são algoritmos de máquinas de vetores de suporte, a breve teoria por trás de uma máquina de vetores de suporte e sua implementação na biblioteca Scikit-Learn do Python. Passaremos então para outro conceito de SVM, conhecido como Núcleo SVMou truque do kernel, e também o implementará com a ajuda do Scikit-Learn.

Modelo SVM Simples (Linear)

Sobre o conjunto de dados

Seguindo o exemplo dado na introdução, usaremos um conjunto de dados que possui medições de imagens de cédulas reais e falsificadas.

Ao olhar para duas notas, nossos olhos geralmente as examinam da esquerda para a direita e verificam onde podem haver semelhanças ou diferenças. Procuramos um ponto preto antes de um ponto verde ou uma marca brilhante que está acima de uma ilustração. Isso significa que há uma ordem na qual olhamos para as notas. Se soubéssemos que existem pontos verdes e pretos, mas não se o ponto verde vinha antes do preto, ou se o preto vinha antes do verde, seria mais difícil discriminar as notas.

Existe um método semelhante ao que acabamos de descrever que pode ser aplicado às imagens das cédulas. Em linhas gerais, esse método consiste em traduzir os pixels da imagem em um sinal, levando em consideração a ordem em que cada sinal diferente acontece na imagem, transformando-a em pequenas ondas, ou ondas. Após a obtenção das wavelets, existe uma forma de saber a ordem em que um sinal acontece antes do outro, ou o tempo, mas não exatamente o sinal. Para saber isso, é preciso obter as frequências da imagem. Eles são obtidos por um método que faz a decomposição de cada sinal, chamado método de Fourier.

Uma vez obtida a dimensão de tempo através das wavelets, e a dimensão de frequência através do método de Fourier, faz-se uma sobreposição de tempo e frequência para ver quando ambos coincidem, este é o convolução análise. A convolução obtém um ajuste que combina as wavelets com as frequências da imagem e descobre quais frequências são mais proeminentes.

Esse método que envolve encontrar as wavelets, suas frequências e depois ajustar ambas é chamado Transformada Wavelet. A transformada wavelet tem coeficientes, e esses coeficientes foram usados ​​para obter as medições que temos no conjunto de dados.

Importando o conjunto de dados

O conjunto de dados de cédulas que vamos usar nesta seção é o mesmo que foi usado na seção de classificação do tutorial árvore de decisão.

Observação: Você pode baixar o conjunto de dados SUA PARTICIPAÇÃO FAZ A DIFERENÇA.

Vamos importar os dados para um pandas dataframe estrutura e dê uma olhada em suas cinco primeiras linhas com o head() método.

Observe que os dados são salvos em um txt (texto) formato de arquivo, separado por vírgulas, e sem cabeçalho. Podemos reconstruí-lo como uma tabela lendo-o como um csv, especificando o separator como uma vírgula e adicionando os nomes das colunas com o names argumento.

Vamos seguir essas três etapas de uma vez e, em seguida, examinar as primeiras cinco linhas dos dados:

import pandas as pd data_link = "https://archive.ics.uci.edu/ml/machine-learning-databases/00267/data_banknote_authentication.txt"
col_names = ["variance", "skewness", "curtosis", "entropy", "class"] bankdata = pd.read_csv(data_link, names=col_names, sep=",", header=None)
bankdata.head()

Isto resulta em:

	variance skewness curtosis entropy class
0 3.62160 8.6661 -2.8073 -0.44699 0
1 4.54590 8.1674 -2.4586 -1.46210 0
2 3.86600 -2.6383 1.9242 0.10645 0
3 3.45660 9.5228 -4.0112 -3.59440 0
4 0.32924 -4.4552 4.5718 -0.98880 0

Observação: Você também pode salvar os dados localmente e substituir data_link para data_pathe passe o caminho para seu arquivo local.

Podemos ver que há cinco colunas em nosso conjunto de dados, ou seja, variance, skewness, curtosis, entropy e class. Nas cinco linhas, as primeiras quatro colunas são preenchidas com números como 3.62160, 8.6661, -2.8073 ou contínuo valores e o último class coluna tem suas primeiras cinco linhas preenchidas com 0s, ou um discreto valor.

Como nosso objetivo é prever se uma cédula de banco é autêntica ou não, podemos fazer isso com base nos quatro atributos da cédula:

  • variance da imagem Wavelet Transformed. Geralmente, a variância é um valor contínuo que mede o quanto os pontos de dados estão próximos ou distantes do valor médio dos dados. Se os pontos estiverem mais próximos do valor médio dos dados, a distribuição está mais próxima de uma distribuição normal, o que geralmente significa que seus valores são mais bem distribuídos e um pouco mais fáceis de prever. No contexto da imagem atual, esta é a variância dos coeficientes que resultam da transformada wavelet. Quanto menor a variação, mais próximos os coeficientes estavam da tradução da imagem real.

  • skewness da imagem Wavelet Transformed. A assimetria é um valor contínuo que indica a assimetria de uma distribuição. Se houver mais valores à esquerda da média, a distribuição é enviesado negativamente, se houver mais valores à direita da média, a distribuição é positivamente inclinado, e se a média, moda e mediana forem iguais, a distribuição é simétrico. Quanto mais simétrica for uma distribuição, mais próxima ela está de uma distribuição normal, tendo também seus valores mais bem distribuídos. No presente contexto, esta é a assimetria dos coeficientes que resultam da transformada wavelet. Quanto mais simétricos, mais próximos os coeficientes quevariance, skewness, curtosis, entropyre para traduzir a imagem real.

Implementando SVM e Kernel SVM com Scikit-Learn PlatoBlockchain Data Intelligence do Python. Pesquisa vertical. Ai.

  • curtosis (ou curtose) da imagem Wavelet Transformed. A curtose é um valor contínuo que, assim como a assimetria, também descreve a forma de uma distribuição. Dependendo do coeficiente de curtose (k), uma distribuição – quando comparada com a distribuição normal pode ser mais ou menos plana – ou ter mais ou menos dados em suas extremidades ou caudas. Quando a distribuição é mais espalhada e achatada, ela é chamada platicúrtico; quando está menos espalhado e mais concentrado no meio, mesocúrtico; e quando a distribuição está quase toda concentrada no meio, é chamada leptocúrtico. Este é o mesmo caso dos casos anteriores de variância e assimetria, quanto mais mesocúrtica for a distribuição, mais próximos os coeficientes estarão da tradução da imagem real.

Implementando SVM e Kernel SVM com Scikit-Learn PlatoBlockchain Data Intelligence do Python. Pesquisa vertical. Ai.

  • entropy de imagem. A entropia também é um valor contínuo, geralmente mede a aleatoriedade ou desordem em um sistema. No contexto de uma imagem, a entropia mede a diferença entre um pixel e seus pixels vizinhos. Para o nosso contexto, quanto mais entropia os coeficientes tiverem, mais perda houve ao transformar a imagem – e quanto menor a entropia, menor a perda de informação.

Implementando SVM e Kernel SVM com Scikit-Learn PlatoBlockchain Data Intelligence do Python. Pesquisa vertical. Ai.

A quinta variável foi a class variável, que provavelmente tem valores 0 e 1, que dizem se a nota era real ou falsificada.

Podemos verificar se a quinta coluna contém zeros e uns com Pandas' unique() método:

bankdata['class'].unique()

O método acima retorna:

array([0, 1]) 

O método acima retorna uma matriz com valores 0 e 1. Isso significa que os únicos valores contidos em nossas linhas de classe são zeros e uns. Está pronto para ser usado como alvo em nosso aprendizado supervisionado.

  • class de imagem. Este é um valor inteiro, é 0 quando a imagem é forjada e 1 quando a imagem é real.

Como temos uma coluna com as anotações das imagens reais e esquecidas, isso significa que nosso tipo de aprendizado é supervisionou.

Conselho: para saber mais sobre o raciocínio por trás da Transformada Wavelet nas imagens das cédulas e o uso do SVM, leia o artigo publicado pelos autores.

Também podemos ver quantos registros ou imagens temos, observando o número de linhas nos dados por meio do shape propriedade:

bankdata.shape

Isso resulta em:

(1372, 5)

A linha acima significa que existem 1,372 linhas de imagens de cédulas transformadas e 5 colunas. Esses são os dados que iremos analisar.

Importamos nosso conjunto de dados e fizemos algumas verificações. Agora podemos explorar nossos dados para entendê-los melhor.

Explorando o conjunto de dados

Acabamos de ver que há apenas zeros e uns na coluna da classe, mas também podemos saber em que proporção eles estão – ou seja, se há mais zeros que uns, mais uns que zeros, ou se os números de zeros é o mesmo que o número de uns, o que significa que eles são balanced.

Para saber a proporção, podemos contar cada um dos valores zero e um nos dados com value_counts() método:

bankdata['class'].value_counts()

Isso resulta em:

0 762
1 610
Name: class, dtype: int64

No resultado acima, podemos ver que existem 762 zeros e 610 uns, ou 152 zeros a mais do que uns. Isso significa que temos um pouco mais de imagens forjadas do que reais, e se essa discrepância fosse maior, por exemplo, 5500 zeros e 610 uns, isso poderia impactar negativamente nossos resultados. Uma vez que estamos tentando usar esses exemplos em nosso modelo – quanto mais exemplos houver, geralmente significa que mais informações o modelo terá para decidir entre notas forjadas ou reais – se houver poucos exemplos de notas reais, o modelo é propenso a ser equivocados ao tentar reconhecê-los.

Já sabemos que existem mais 152 notas forjadas, mas podemos ter certeza de que são exemplos suficientes para o modelo aprender? Saber quantos exemplos são necessários para o aprendizado é uma pergunta muito difícil de responder, ao contrário, podemos tentar entender, em termos percentuais, quanto é essa diferença entre as aulas.

O primeiro passo é usar pandas value_counts() método novamente, mas agora vamos ver a porcentagem incluindo o argumento normalize=True:

bankdata['class'].value_counts(normalize=True)

A normalize=True calcula a porcentagem dos dados para cada classe. Até agora, a porcentagem de dados forjados (0) e reais (1) é:

0 0.555394
1 0.444606
Name: class, dtype: float64

Isso significa que aproximadamente (~) 56% do nosso conjunto de dados é forjado e 44% é real. Isso nos dá uma proporção de 56%-44%, que é o mesmo que uma diferença de 12%. Isso é considerado estatisticamente uma pequena diferença, pois está um pouco acima de 10%, portanto os dados são considerados equilibrados. Se ao invés de uma proporção de 56:44, houvesse uma proporção de 80:20 ou 70:30, então nossos dados seriam considerados desbalanceados e precisaríamos fazer algum tratamento de desbalanceamento, mas, felizmente, não é o caso.

Também podemos ver essa diferença visualmente, observando a classe ou a distribuição do alvo com um histograma imbuído do Pandas, usando:

bankdata['class'].plot.hist();

Isso plota um histograma usando a estrutura do dataframe diretamente, em combinação com o matplotlib biblioteca que está nos bastidores.

Implementando SVM e Kernel SVM com Scikit-Learn PlatoBlockchain Data Intelligence do Python. Pesquisa vertical. Ai.

Olhando para o histograma, podemos ter certeza de que nossos valores-alvo são 0 ou 1 e que os dados estão balanceados.

Esta foi uma análise da coluna que estávamos tentando prever, mas que tal analisar as outras colunas de nossos dados?

Podemos dar uma olhada nas medições estatísticas com o describe() método dataframe. Também podemos usar .T de transposição – para inverter colunas e linhas, tornando mais direta a comparação entre os valores:

Confira nosso guia prático e prático para aprender Git, com práticas recomendadas, padrões aceitos pelo setor e folha de dicas incluída. Pare de pesquisar comandos Git no Google e realmente aprender -lo!

bankdata.describe().T

Isto resulta em:

 count mean std min 25% 50% 75% max
variance 1372.0 0.433735 2.842763 -7.0421 -1.773000 0.49618 2.821475 6.8248
skewness 1372.0 1.922353 5.869047 -13.7731 -1.708200 2.31965 6.814625 12.9516
curtosis 1372.0 1.397627 4.310030 -5.2861 -1.574975 0.61663 3.179250 17.9274
entropy 1372.0 -1.191657 2.101013 -8.5482 -2.413450 -0.58665 0.394810 2.4495
class 1372.0 0.444606 0.497103 0.0000 0.000000 0.00000 1.000000 1.0000

Observe que as colunas de assimetria e curtose possuem valores médios distantes dos valores de desvio padrão, isso indica que aqueles valores que estão mais distantes da tendência central dos dados, ou seja, possuem uma variabilidade maior.

Também podemos dar uma olhada na distribuição de cada recurso visualmente, traçando o histograma de cada recurso dentro de um loop for. Além de olhar a distribuição, seria interessante ver como os pontos de cada classe são separados em relação a cada feição. Para fazer isso, podemos traçar um gráfico de dispersão fazendo uma combinação de recursos entre eles e atribuir cores diferentes a cada ponto em relação à sua classe.

Vamos começar com a distribuição de cada recurso e plotar o histograma de cada coluna de dados, exceto para o class coluna. o class coluna não será levada em consideração por sua posição no array de colunas bankdata. Todas as colunas serão selecionadas, exceto a última com columns[:-1]:

import matplotlib.pyplot as plt for col in bankdata.columns[:-1]: plt.title(col) bankdata[col].plot.hist() plt.show();

Depois de executar o código acima, podemos ver que ambos skewness e entropy distribuições de dados são negativamente assimétricas e curtosis é enviesado positivamente. Todas as distribuições são simétricas e variance é a única distribuição que está próxima do normal.

Agora podemos passar para a segunda parte e traçar o gráfico de dispersão de cada variável. Para fazer isso, também podemos selecionar todas as colunas, exceto a classe, com columns[:-1], use Seaborn scatterplot() e dois loops for para obter as variações de emparelhamento para cada um dos recursos. Também podemos excluir o emparelhamento de um recurso consigo mesmo, testando se o primeiro recurso é igual ao segundo com um if statement.

import seaborn as sns for feature_1 in bankdata.columns[:-1]: for feature_2 in bankdata.columns[:-1]: if feature_1 != feature_2: print(feature_1, feature_2) sns.scatterplot(x=feature_1, y=feature_2, data=bankdata, hue='class') plt.show();

Observe que todos os gráficos têm pontos de dados reais e forjados não claramente separados uns dos outros, isso significa que há algum tipo de superposição de classes. Como um modelo SVM usa uma linha para separar as classes, algum desses grupos nos gráficos pode ser separado usando apenas uma linha? Parece improvável. É assim que a maioria dos dados reais se parece. O mais próximo que podemos chegar de uma separação é na combinação de skewness e varianceou entropy e variance parcelas. Isso provavelmente se deve a variance dados com uma forma de distribuição mais próxima do normal.

Mas olhar para todos esses gráficos em sequência pode ser um pouco difícil. Temos a alternativa de olhar todos os gráficos de distribuição e dispersão juntos usando o método de Seaborn. pairplot().

Ambos os loops for anteriores que fizemos podem ser substituídos por apenas esta linha:

sns.pairplot(bankdata, hue='class');

Olhando para o gráfico de pares, parece que, na verdade, curtosis e variance seria a combinação mais fácil de recursos, então as diferentes classes poderiam ser separadas por uma linha, ou linearmente separável.

Se a maioria dos dados estiver longe de ser linearmente separável, podemos tentar pré-processá-los, reduzindo suas dimensões, e também normalizar seus valores para tentar tornar a distribuição mais próxima de um normal.

Para este caso, vamos usar os dados como estão, sem mais pré-processamento e, posteriormente, podemos voltar uma etapa, adicionar ao pré-processamento de dados e comparar os resultados.

Conselho: Ao trabalhar com dados, geralmente se perde informação ao transformá-los, pois estamos fazendo aproximações, ao invés de coletar mais dados. Trabalhar primeiro com os dados iniciais, se possível, oferece uma linha de base antes de tentar outras técnicas de pré-processamento. Ao seguir esse caminho, o resultado inicial usando dados brutos pode ser comparado com outro resultado que usa técnicas de pré-processamento nos dados.

Observação: Normalmente em Estatística, ao construir modelos, é comum seguir um procedimento dependendo do tipo de dado (discreto, contínuo, categorial, numérico), sua distribuição e as hipóteses do modelo. Já na Ciência da Computação (CS), há mais espaço para tentativa, erro e novas iterações. Em CS, é comum ter uma linha de base para comparar. No Scikit-learn, há uma implementação de modelos fictícios (ou estimadores fictícios), alguns não são melhores do que jogar uma moeda e apenas responder sim (ou 1) 50% do tempo. É interessante usar modelos fictícios como linha de base para o modelo real ao comparar os resultados. Espera-se que os resultados reais do modelo sejam melhores do que um palpite aleatório, caso contrário, o uso de um modelo de aprendizado de máquina não seria necessário.

Implementando SVM com Scikit-Learn

Antes de entrar mais na teoria de como o SVM funciona, podemos construir nosso primeiro modelo de linha de base com os dados e o Scikit-Learn Classificador de vetores de suporte or SVC classe.

Nosso modelo receberá os coeficientes wavelet e tentará classificá-los com base na classe. O primeiro passo neste processo é separar os coeficientes ou características da classe ou alvo. Após essa etapa, a segunda etapa é dividir ainda mais os dados em um conjunto que será usado para o aprendizado do modelo ou conjunto de trem e outro que será utilizado para avaliação do modelo ou Conjunto de teste.

Observação: A nomenclatura de teste e avaliação pode ser um pouco confusa, porque você também pode dividir seus dados entre conjuntos de treinamento, avaliação e teste. Dessa forma, ao invés de ter dois conjuntos, você teria um conjunto intermediário só para usar e ver se o desempenho do seu modelo está melhorando. Isso significa que o modelo seria treinado com o conjunto de treinamento, aprimorado com o conjunto de avaliação e obtendo uma métrica final com o conjunto de teste.

Algumas pessoas dizem que a avaliação é aquele conjunto intermediário, outras dirão que o conjunto de teste é o conjunto intermediário e que o conjunto de avaliação é o conjunto final. Essa é outra forma de tentar garantir que o modelo não esteja vendo o mesmo exemplo de forma alguma, ou que algum tipo de Vazamento de informações não está acontecendo, e que há uma generalização do modelo pela melhoria das últimas métricas definidas. Se você quiser seguir essa abordagem, poderá dividir ainda mais os dados mais uma vez, conforme descrito neste Train_test_split() do Scikit-Learn – Conjuntos de treinamento, teste e validação guia.

Dividindo dados em conjuntos de treinamento/teste

Na sessão anterior, compreendemos e exploramos os dados. Agora, podemos dividir nossos dados em dois arrays – um para os quatro recursos e outro para o quinto, ou recurso de destino. Como queremos prever a classe dependendo dos coeficientes das wavelets, nosso y será o class coluna e nosso X será o variance, skewness, curtosis e entropy colunas.

Para separar o alvo e os recursos, podemos atribuir apenas o class coluna para y, depois descartando-o do dataframe para atribuir as colunas restantes a X de .drop() método:

y = bankdata['class']
X = bankdata.drop('class', axis=1) 

Depois que os dados são divididos em atributos e rótulos, podemos dividi-los ainda mais em conjuntos de treinamento e teste. Isso pode ser feito manualmente, mas o model_selection biblioteca do Scikit-Learn contém o train_test_split() método que nos permite dividir aleatoriamente os dados em conjuntos de treinamento e teste.

Para usá-lo, podemos importar a biblioteca, chamar o train_test_split() método, passe em X e y dados e definir um test_size passar como argumento. Neste caso, vamos defini-lo como 0.20– isso significa que 20% dos dados serão usados ​​para teste e os outros 80% para treinamento.

Este método pega amostras aleatoriamente respeitando a porcentagem que definimos, mas respeita os pares Xy, para que a amostragem não confunda totalmente a relação.

Como o processo de amostragem é inerentemente aleatório, sempre teremos resultados diferentes ao executar o método. Para podermos ter os mesmos resultados, ou resultados reprodutíveis, podemos definir uma constante chamada SEED com o valor de 42.

Você pode executar o seguinte script para fazer isso:

from sklearn.model_selection import train_test_split SEED = 42 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.20, random_state = SEED)

Observe que o train_test_split() método já retorna o X_train, X_test, y_train, y_test conjuntos nesta ordem. Podemos imprimir o número de amostras separadas para treinar e testar obtendo o primeiro (0) elemento do shape propriedade retornada tupla:

xtrain_samples = X_train.shape[0]
xtest_samples = X_test.shape[0] print(f'There are {xtrain_samples} samples for training and {xtest_samples} samples for testing.')

Isso mostra que existem 1097 amostras para treinamento e 275 para teste.

Treinando o modelo

Dividimos os dados em conjuntos de treinamento e teste. Agora é hora de criar e treinar um modelo SVM nos dados do trem. Para fazer isso, podemos importar os arquivos do Scikit-Learn svm biblioteca juntamente com o Classificador de vetores de suporte classe, ou SVC classe.

Depois de importar a classe, podemos criar uma instância dela – como estamos criando um modelo SVM simples, estamos tentando separar nossos dados linearmente, então podemos traçar uma linha para dividir nossos dados – que é o mesmo que usar um Função linear – ao definir kernel='linear' como um argumento para o classificador:

from sklearn.svm import SVC
svc = SVC(kernel='linear')

Dessa forma, o classificador tentará encontrar uma função linear que separe nossos dados. Depois de criar o modelo, vamos treiná-lo, ou caber com os dados do trem, empregando o fit() método e dando o X_train Recursos e y_train alvos como argumentos.

Podemos executar o seguinte código para treinar o modelo:

svc.fit(X_train, y_train)

Assim, o modelo é treinado. Até agora, entendemos os dados, os dividimos, criamos um modelo SVM simples e ajustamos o modelo aos dados do trem.

O próximo passo é entender o quão bem esse ajuste conseguiu descrever nossos dados. Em outras palavras, para responder se um SVM linear foi uma escolha adequada.

Fazendo previsões

Uma forma de responder se o modelo conseguiu descrever os dados é calcular e olhar para alguma classificação métrica.

Considerando que o aprendizado é supervisionado, podemos fazer previsões com X_test e compare os resultados da previsão - que podemos chamar y_pred – com o real y_testou verdade fundamental.

Para prever alguns dos dados, o modelo predict() método pode ser empregado. Este método recebe os recursos de teste, X_test, como um argumento e retorna uma previsão, 0 ou 1, para cada um dos X_testlinhas de.

Depois de prever o X_test dados, os resultados são armazenados em um y_pred variável. Portanto, cada uma das classes previstas com o modelo SVM linear simples está agora no y_pred variável.

Este é o código de previsão:

y_pred = svc.predict(X_test)

Considerando que temos as previsões, agora podemos compará-las com os resultados reais.

Avaliando o Modelo

Existem várias maneiras de comparar previsões com resultados reais e elas medem diferentes aspectos de uma classificação. Algumas métricas de classificação mais usadas são:

  1. Matriz de Confusão: quando precisamos saber quantas amostras acertamos ou erramos cada aula. Os valores que foram corretos e corretamente previstos são chamados verdadeiros positivos, aqueles que foram previstos como positivos, mas não foram positivos, são chamados falso-positivo. A mesma nomenclatura de verdadeiros negativos e falsos negativos é usado para valores negativos;

  2. Precisão: quando nosso objetivo é entender quais valores de predição corretos foram considerados corretos por nosso classificador. A precisão dividirá esses valores positivos verdadeiros pelas amostras que foram previstas como positivas;

$$
precisão = frac{texto{verdadeiros positivos}}{texto{verdadeiros positivos} + texto{falsos positivos}}
$$

  1. Recordar: comumente calculado com precisão para entender quantos dos verdadeiros positivos foram identificados pelo nosso classificador. O recall é calculado dividindo os verdadeiros positivos por qualquer coisa que deveria ter sido prevista como positiva.

$$
recall = frac{texto{verdadeiros positivos}}{texto{verdadeiros positivos} + texto{falsos negativos}}
$$

  1. Pontuação F1: é o balanceado ou média harmônica de precisão e revocação. O valor mais baixo é 0 e o mais alto é 1. Quando f1-score é igual a 1, significa que todas as classes foram previstas corretamente – esta é uma pontuação muito difícil de obter com dados reais (exceções quase sempre existem).

$$
text{f1-score} = 2* frac{text{precisão} * text{recall}}{text{precisão} + text{recall}}
$$

Já estamos familiarizados com medidas de matriz de confusão, precisão, recall e pontuação F1. Para calculá-los, podemos importar os arquivos do Scikit-Learn metrics biblioteca. Esta biblioteca contém o classification_report e confusion_matrix métodos, o método de relatório de classificação retorna a pontuação de precisão, recall e f1. Ambos classification_report e confusion_matrix pode ser facilmente usado para descobrir os valores para todas essas métricas importantes.

Para calcular as métricas, importamos os métodos, os chamamos e passamos como argumentos as classificações previstas, y_test, e os rótulos de classificação, ou y_true.

Para uma melhor visualização da matriz de confusão, podemos plotá-la em um Seaborn's heatmap juntamente com as anotações de quantidade, e para o relatório de classificação, é melhor imprimir seu resultado, assim seus resultados são formatados. Este é o seguinte código:

from sklearn.metrics import classification_report, confusion_matrix cm = confusion_matrix(y_test,y_pred)
sns.heatmap(cm, annot=True, fmt='d').set_title('Confusion matrix of linear SVM') print(classification_report(y_test,y_pred))

Isso exibe:

 precision recall f1-score support 0 0.99 0.99 0.99 148 1 0.98 0.98 0.98 127 accuracy 0.99 275 macro avg 0.99 0.99 0.99 275
weighted avg 0.99 0.99 0.99 275

Implementando SVM e Kernel SVM com Scikit-Learn PlatoBlockchain Data Intelligence do Python. Pesquisa vertical. Ai.

No relatório de classificação, sabemos que há uma precisão de 0.99, revocação de 0.99 e uma pontuação f1 de 0.99 para as notas falsificadas, ou classe 0. Essas medições foram obtidas com 148 amostras conforme mostrado na coluna de suporte. Enquanto isso, para a classe 1, ou notas reais, o resultado foi uma unidade abaixo, 0.98 de precisão, 0.98 de recordação e a mesma nota f1. Desta vez, 127 medições de imagem foram usadas para obter esses resultados.

Se olharmos para a matriz de confusão, também podemos ver que de 148 amostras de classe 0, 146 foram classificadas corretamente e houve 2 falsos positivos, enquanto para 127 amostras de classe 1, houve 2 falsos negativos e 125 verdadeiros positivos.

Podemos ler o relatório de classificação e a matriz de confusão, mas o que eles significam?

Interpretando os resultados

Para descobrir o significado, vamos analisar todas as métricas combinadas.

Quase todas as amostras da classe 1 foram classificadas corretamente, houve 2 erros para o nosso modelo ao identificar as cédulas reais. Isso é o mesmo que 0.98, ou 98%, de recordação. Algo semelhante pode ser dito da classe 0, apenas 2 amostras foram classificadas incorretamente, enquanto 148 são verdadeiros negativos, totalizando uma precisão de 99%.

Além desses resultados, todos os outros estão marcando 0.99, que é quase 1, uma métrica muito alta. Na maioria das vezes, quando uma métrica tão alta acontece com dados da vida real, isso pode estar indicando um modelo superajustado aos dados ou superajustado.

Quando há um overfit, o modelo pode funcionar bem ao prever os dados que já são conhecidos, mas perde a capacidade de generalizar para novos dados, o que é importante em cenários do mundo real.

Um teste rápido para descobrir se um overfit está acontecendo também é com os dados do trem. Se o modelo tiver memorizado um pouco os dados do trem, as métricas estarão muito próximas de 1 ou 100%. Lembre-se que os dados do trem são maiores que os dados do teste – por isso – tente olhar proporcionalmente, mais amostras, mais chances de errar, a não ser que tenha ocorrido algum overfit.

Para prever com dados de trem, podemos repetir o que fizemos para dados de teste, mas agora com X_train:

y_pred_train = svc.predict(X_train) cm_train = confusion_matrix(y_train,y_pred_train)
sns.heatmap(cm_train, annot=True, fmt='d').set_title('Confusion matrix of linear SVM with train data') print(classification_report(y_train,y_pred_train))

Isso resulta em:

 precision recall f1-score support 0 0.99 0.99 0.99 614 1 0.98 0.99 0.99 483 accuracy 0.99 1097 macro avg 0.99 0.99 0.99 1097
weighted avg 0.99 0.99 0.99 1097

Implementando SVM e Kernel SVM com Scikit-Learn PlatoBlockchain Data Intelligence do Python. Pesquisa vertical. Ai.

É fácil ver que parece haver um overfit, uma vez que as métricas do trem são 99% ao ter 4 vezes mais dados. O que pode ser feito neste cenário?

Para reverter o overfit, podemos adicionar mais observações de treinamento, usar um método de treinamento com diferentes partes do conjunto de dados, como validação cruzada, e também alterar os parâmetros padrão que já existem antes do treinamento, ao criar nosso modelo, ou hiperparâmetros. Na maioria das vezes, o Scikit-learn define alguns parâmetros como padrão, e isso pode acontecer silenciosamente se não houver muito tempo dedicado à leitura da documentação.

Você pode verificar a segunda parte deste guia (em breve!) para ver como implementar a validação cruzada e executar um ajuste de hiperparâmetro.

Conclusão

Neste artigo, estudamos o SVM de kernel linear simples. Obtivemos a intuição por trás do algoritmo SVM, usamos um conjunto de dados real, exploramos os dados e vimos como esses dados podem ser usados ​​junto com o SVM, implementando-os com a biblioteca Scikit-Learn do Python.

Para continuar praticando, você pode tentar outros conjuntos de dados do mundo real disponíveis em locais como Kaggle, UCI, Conjuntos de dados públicos do BigQuery, universidades e sites governamentais.

Eu também sugeriria que você explorasse a matemática real por trás do modelo SVM. Embora você não precise necessariamente dele para usar o algoritmo SVM, ainda é muito útil saber o que realmente está acontecendo nos bastidores enquanto seu algoritmo está encontrando limites de decisão.

Carimbo de hora:

Mais de Abuso de pilha