A região de decisão de um classificador Gaussiano Naive Bayes. Imagem do Autor.
Acho que esse é um clássico no início de cada carreira em ciência de dados: o Classificador Naive Bayes. Ou eu deveria dizer o família de classificadores ingênuos de Bayes, pois eles vêm em muitos sabores. Por exemplo, existe um Bayes ingênuo multinomial, um Bayes ingênuo de Bernoulli e também um classificador Bayes ingênuo Gaussiano, cada um diferente em apenas um pequeno detalhe, como veremos. Os algoritmos ingênuos de Bayes são bastante simples em design, mas provaram ser úteis em muitas situações complexas do mundo real.
Neste artigo, você pode aprender
- como funcionam os classificadores ingênuos de Bayes,
- por que faz sentido defini-los do jeito que são e
- como implementá-los em Python usando NumPy.
Você pode encontrar o código em meu Github.
Pode ajudar um pouco verificar minha cartilha sobre estatísticas bayesianas Uma introdução suave à inferência bayesiana para se acostumar com a fórmula de Bayes. Como iremos implementar o classificador de forma scikit para aprender, também vale a pena conferir meu artigo Crie sua própria regressão scikit-learn personalizada. No entanto, a sobrecarga do scikit-learn é muito pequena e você deve conseguir acompanhar de qualquer maneira.
Começaremos explorando a teoria surpreendentemente simples da classificação ingênua de Bayes e depois passaremos para a implementação.
Em que estamos realmente interessados ao classificar? O que estamos realmente fazendo, qual é a entrada e a saída? A resposta é simples:
Dado um ponto de dados x, qual é a probabilidade de x pertencer a alguma classe c?
Isso é tudo o que queremos responder com qualquer classificação. Você pode modelar diretamente esta declaração como uma probabilidade condicional: p(c|x).
Por exemplo, se houver
- aulas 3 c₁, c₂, c₃ e
- x consiste em 2 recursos x₁, x₂,
o resultado de um classificador pode ser algo como p(c₁|x₁, x₂) = 0.3, p(c₂|x₁, x₂)=0.5 e p(c₃|x₁, x₂) = 0.2. Se nos importarmos com um único rótulo como saída, escolheríamos aquele com a maior probabilidade, ou seja, c₂ com uma probabilidade de 50% aqui.
O classificador ingênuo de Bayes tenta calcular essas probabilidades diretamente.
Baías ingénuas
Ok, dado um ponto de dados x, queremos calcular p(c|x) para todas as classes c e, em seguida, emitir o c com a maior probabilidade. Em fórmulas, você costuma ver isso como
Imagem do Autor.
Observação: max p(c|x) retorna a probabilidade máxima enquanto argmax p(c|x) retorna o c com esta maior probabilidade.
Mas antes que possamos otimizar p(c|x), temos que ser capazes de calculá-lo. Para isso, utilizamos Teorema de Bayes:
Teorema de Bayes. Imagem do Autor.
Esta é a parte de Bayes do ingênuo Bayes. Mas agora, temos o seguinte problema: Quais são p(x|c) e p(c)?
É disso que se trata o treinamento de um classificador ingênuo de Bayes.
O treinamento
Para ilustrar tudo, vamos usar um conjunto de dados de brinquedo com duas características reais x₁, x₂ e três classes c₁, c₂, c₃ no seguinte.
Os dados, visualizados. Imagem do Autor.
Você pode criar este conjunto de dados exato via
from sklearn.datasets import make_blobs X, y = make_blobs(n_samples=20, centers=[(0,0), (5,5), (-5, 5)], random_state=0)
Vamos começar com o probabilidade de classe p(c), a probabilidade de que alguma classe c é observado no conjunto de dados rotulado. A maneira mais simples de estimar isso é apenas calcular as frequências relativas das classes e usá-las como probabilidades. Podemos usar nosso conjunto de dados para ver o que isso significa exatamente.
Há 7 de 20 pontos rotulados como classe c₁ (azul) no conjunto de dados, portanto dizemos p(c₁)=7/20. Temos 7 pontos para a classe c₂ (vermelho) também, portanto, definimos p(c₂)=7/20. a última aula c₃ (amarelo) tem apenas 6 pontos, portanto p(c₃) = 6/20.
Esse cálculo simples das probabilidades de classe se assemelha a uma abordagem de máxima verossimilhança. Você pode, no entanto, também usar outro prévio distribuição, se quiser. Por exemplo, se você sabe que este conjunto de dados não é representativo da população real porque a classe c₃ deve aparecer em 50% dos casos, então você define p(c₁) = 0.25, p(c₂)=0.25 e p(c₃) = 0.5. O que quer que ajude você a melhorar o desempenho no conjunto de teste.
Agora nos voltamos para o probabilidade p(x|c)=p(x₁, x₂|c). Uma abordagem para calcular essa probabilidade é filtrar o conjunto de dados para amostras com rótulo c e, em seguida, tente encontrar uma distribuição (por exemplo, um gaussiano bidimensional) que capture os recursos x₁, x₂.
Infelizmente, geralmente não temos amostras suficientes por classe para fazer uma estimativa adequada da probabilidade.
Para poder construir um modelo mais robusto, fazemos o suposição ingênua que as características x₁, x₂ e guarante que os mesmos estão estocasticamente independente, dado c. Esta é apenas uma maneira elegante de tornar a matemática mais fácil por meio de
Imagem do autor
para cada aula c. É aqui que o ingénuo parte do ingênuo Bayes vem porque esta equação não se sustenta em geral. Ainda assim, mesmo assim, o ingênuo Bayes produz resultados bons, às vezes excelentes, na prática. Especialmente para problemas de PNL com recursos de bag-of-words, o multinomial ingênuo Bayes brilha.
Os argumentos fornecidos acima são os mesmos para qualquer classificador ingênuo de Bayes que você possa encontrar. Agora só depende de como você modela p(x₁|c₁), p(x₂|c₁), p(x₁|c₂), p(x₂|c₂), p(x₁|c₃) e p(x₂|c₃).
Se seus recursos são 0 e 1 apenas, você pode usar um Distribuição Bernoulli. Se forem números inteiros, um Distribuição multinomial. No entanto, temos valores reais de recursos e decidimos por um Gaussian distribuição, daí o nome Gaussian Naive Bayes. Assumimos a seguinte forma
Imagem do Autor.
onde μᵢ,ⱼ é a média e σᵢ,ⱼ é o desvio padrão que temos que estimar a partir dos dados. Isso significa que obtemos uma média para cada recurso i juntamente com uma classe cⱼ, no nosso caso 2*3=6 significa. O mesmo vale para os desvios padrão. Isso pede um exemplo.
Vamos tentar estimar μ₂,₁ e σ₂,₁. Porque j=1, estamos interessados apenas na classe c₁, vamos manter apenas amostras com este rótulo. Restam as seguintes amostras:
# samples with label = c_1 array([[ 0.14404357, 1.45427351], [ 0.97873798, 2.2408932 ], [ 1.86755799, -0.97727788], [ 1.76405235, 0.40015721], [ 0.76103773, 0.12167502], [-0.10321885, 0.4105985 ], [ 0.95008842, -0.15135721]])
Agora, por causa i=2 temos que considerar apenas a segunda coluna. µ₂,₁ é a média e σ₂,₁ o desvio padrão para esta coluna, ou seja µ₂,₁ = 0.49985176 e σ₂,₁ = 0.9789976.
Esses números fazem sentido se você olhar o gráfico de dispersão de cima novamente. As características x₂ das amostras da classe c₁ estão em torno de 0.5, como você pode ver na foto.
Calculamos isso agora para as outras cinco combinações e terminamos!
Em Python, você pode fazer assim:
from sklearn.datasets import make_blobs
import numpy as np # Create the data. The classes are c_1=0, c_2=1 and c_3=2.
X, y = make_blobs( n_samples=20, centers=[(0, 0), (5, 5), (-5, 5)], random_state=0
) # The class probabilities.
# np.bincounts counts the occurence of each label.
prior = np.bincount(y) / len(y) # np.where(y==i) returns all indices where the y==i.
# This is the filtering step.
means = np.array([X[np.where(y == i)].mean(axis=0) for i in range(3)])
stds = np.array([X[np.where(y == i)].std(axis=0) for i in range(3)])
Recebemos
# priors
array([0.35, 0.35, 0.3 ])
# means array([[ 0.90889988, 0.49985176], [ 5.4111385 , 4.6491892 ], [-4.7841679 , 5.15385848]])
# stds
array([[0.6853714 , 0.9789976 ], [1.40218915, 0.67078568], [0.88192625, 1.12879666]])
Este é o resultado do treinamento de um classificador Gaussiano Naive Bayes.
Fazendo previsões
A fórmula de previsão completa é
Imagem do Autor.
Vamos supor um novo ponto de dados x*=(-2, 5) entra.
Imagem do Autor.
Para ver a qual classe ele pertence, vamos calcular p(c|x*) para todas as classes. Pela foto, deve pertencer à classe c₃ = 2, mas vamos ver. Ignoremos o denominador p(x) por um segundo. Usando o loop a seguir, calculou os nominadores para j = 1, 2, 3.
x_new = np.array([-2, 5]) for j in range(3): print( f"Probability for class {j}: {(1/np.sqrt(2*np.pi*stds[j]**2)*np.exp(-0.5*((x_new-means[j])/stds[j])**2)).prod()*p[j]:.12f}" )
Recebemos
Probability for class 0: 0.000000000263
Probability for class 1: 0.000000044359
Probability for class 2: 0.000325643718
Claro, estes probabilidades (não devemos chamá-los assim) não somam um, pois ignoramos o denominador. No entanto, isso não é problema, pois podemos simplesmente pegar essas probabilidades não normalizadas e dividi-las por sua soma, então elas somarão um. Assim, dividindo esses três valores pela soma de cerca de 0.00032569, obtemos
Imagem do Autor.
Um vencedor claro, como esperávamos. Agora, vamos implementá-lo!
Esta implementação não é de longe eficiente, não é numericamente estável, apenas serve a um propósito educacional. Discutimos a maioria das coisas, então deve ser fácil acompanhar agora. Você pode ignorar todos os check
funções ou leia meu artigo Crie seu próprio scikit-learn personalizado se você estiver interessado no que eles fazem exatamente.
Apenas observe que eu implementei um predict_proba
método primeiro para calcular probabilidades. O método predict
apenas chama esse método e retorna o índice (=classe) com a maior probabilidade usando uma função argmax (aí está de novo!). A classe aguarda classes de 0 a k-1, onde k é o número de aulas.
import numpy as np
from sklearn.base import BaseEstimator, ClassifierMixin
from sklearn.utils.validation import check_X_y, check_array, check_is_fitted class GaussianNaiveBayesClassifier(BaseEstimator, ClassifierMixin): def fit(self, X, y): X, y = check_X_y(X, y) self.priors_ = np.bincount(y) / len(y) self.n_classes_ = np.max(y) + 1 self.means_ = np.array( [X[np.where(y == i)].mean(axis=0) for i in range(self.n_classes_)] ) self.stds_ = np.array( [X[np.where(y == i)].std(axis=0) for i in range(self.n_classes_)] ) return self def predict_proba(self, X): check_is_fitted(self) X = check_array(X) res = [] for i in range(len(X)): probas = [] for j in range(self.n_classes_): probas.append( ( 1 / np.sqrt(2 * np.pi * self.stds_[j] ** 2) * np.exp(-0.5 * ((X[i] - self.means_[j]) / self.stds_[j]) ** 2) ).prod() * self.priors_[j] ) probas = np.array(probas) res.append(probas / probas.sum()) return np.array(res) def predict(self, X): check_is_fitted(self) X = check_array(X) res = self.predict_proba(X) return res.argmax(axis=1)
Testando a Implementação
Embora o código seja bastante curto, ainda é muito longo para ter certeza absoluta de que não cometemos nenhum erro. Então, vamos verificar como ele se sai em relação ao classificador GaussianNB scikit-learn.
my_gauss = GaussianNaiveBayesClassifier()
my_gauss.fit(X, y)
my_gauss.predict_proba([[-2, 5], [0,0], [6, -0.3]])
outputs
array([[8.06313823e-07, 1.36201957e-04, 9.99862992e-01], [1.00000000e+00, 4.23258691e-14, 1.92051255e-11], [4.30879705e-01, 5.69120295e-01, 9.66618838e-27]])
As previsões usando o predict
método são
# my_gauss.predict([[-2, 5], [0,0], [6, -0.3]])
array([2, 0, 1])
Agora, vamos usar o scikit-learn. Jogando em algum código
from sklearn.naive_bayes import GaussianNB gnb = GaussianNB()
gnb.fit(X, y)
gnb.predict_proba([[-2, 5], [0,0], [6, -0.3]])
rendimentos
array([[8.06314158e-07, 1.36201959e-04, 9.99862992e-01], [1.00000000e+00, 4.23259111e-14, 1.92051343e-11], [4.30879698e-01, 5.69120302e-01, 9.66619630e-27]])
Os números se parecem um pouco com os do nosso classificador, mas estão um pouco errados nos últimos dígitos exibidos. Fizemos algo errado? Não. A versão scikit-learn apenas usa outro hiperparâmetro var_smoothing=1e-09
. Se definirmos este para zero, obtemos exatamente nossos números. Perfeito!
Dê uma olhada nas regiões de decisão do nosso classificador. Também marquei os três pontos que usamos para testar. Aquele ponto próximo à fronteira tem apenas 56.9% de chance de pertencer à classe vermelha, como você pode ver no predict_proba
saídas. Os outros dois pontos são classificados com muito mais confiança.
As regiões de decisão com os 3 novos pontos. Imagem do Autor.
Neste artigo, aprendemos como o classificador Gaussiano Naive Bayes funciona e demos uma intuição sobre por que ele foi projetado dessa forma - é uma abordagem direta para modelar a probabilidade de interesse. Compare isso com a regressão logística: lá, a probabilidade é modelada usando uma função linear com uma função sigmoide aplicada sobre ela. Ainda é um modelo fácil, mas não parece tão natural quanto um classificador ingênuo de Bayes.
Continuamos calculando alguns exemplos e coletando algumas partes úteis de código no caminho. Por fim, implementamos um classificador Gaussiano Naive Bayes completo de uma maneira que funciona bem com o scikit-learn. Isso significa que você pode usá-lo em pipelines ou pesquisa em grade, por exemplo.
No final, fizemos uma pequena verificação de sanidade importando o próprio classificador Gaussian Naive Bayes do scikit-learns e testando se ambos, nosso classificador e o do scikit-learn, produzem o mesmo resultado. Este teste foi bem-sucedido.
Dr. Robert Kubler é Cientista de Dados da Publicis Media e Autor da Towards Data Science.
Óptimo estado. Original. Republicado com permissão.
- Conteúdo com tecnologia de SEO e distribuição de relações públicas. Seja amplificado hoje.
- Platoblockchain. Inteligência Metaverso Web3. Conhecimento Ampliado. Acesse aqui.
- Fonte: https://www.kdnuggets.com/2023/03/gaussian-naive-bayes-explained.html?utm_source=rss&utm_medium=rss&utm_campaign=gaussian-naive-bayes-explained
- :é
- $UP
- 1
- 7
- 8
- 9
- a
- Capaz
- Sobre
- acima
- contra
- algoritmos
- Todos os Produtos
- e
- Outro
- responder
- aparecer
- aplicado
- abordagem
- SOMOS
- argumentos
- por aí
- artigo
- AS
- At
- autor
- base
- Bayesiano
- BE
- Porque
- antes
- Começo
- Pouco
- Azul
- fronteira
- construir
- by
- calcular
- cálculo
- chamada
- chamadas
- CAN
- capturas
- Cuidado
- Oportunidades
- casas
- casos
- chance
- verificar
- Escolha
- classe
- aulas
- clássico
- classificação
- classificado
- remover filtragem
- Fechar
- código
- Coleta
- Coluna
- combinações
- como
- comparar
- completar
- completamente
- integrações
- Computar
- confiança
- Considerar
- continuou
- poderia
- acoplado
- curso
- crio
- personalizadas
- dados,
- ciência de dados
- cientista de dados
- conjuntos de dados
- decidir
- decisão
- depende
- Design
- projetado
- detalhe
- desvio
- DID
- diferente
- dígitos
- diretamente
- diretamente
- discutido
- distribuição
- fazer
- não
- e
- cada
- mais fácil
- educacional
- eficiente
- suficiente
- especialmente
- estimativa
- Mesmo
- Cada
- tudo
- exatamente
- exemplo
- exemplos
- esperado
- explicado
- Explorando
- Característica
- Funcionalidades
- poucos
- filtro
- filtragem
- Finalmente
- Encontre
- Primeiro nome
- seguir
- seguinte
- Escolha
- Fórmula
- da
- função
- funções
- Geral
- suave
- ter
- dado
- vai
- Bom estado, com sinais de uso
- Grade
- Ter
- ajudar
- ajuda
- SUA PARTICIPAÇÃO FAZ A DIFERENÇA
- superior
- mais
- segurar
- Como funciona o dobrador de carta de canal
- Contudo
- HTML
- HTTPS
- i
- imagem
- executar
- implementação
- implementado
- importar
- importador
- melhorar
- in
- índice
- Índices
- entrada
- interesse
- interessado
- Introdução
- intuição
- IT
- KDnuggetsGenericName
- Guarda
- Tipo
- Saber
- O rótulo
- Sobrenome
- aprendido
- como
- pequeno
- longo
- olhar
- fazer
- FAZ
- Fazendo
- muitos
- marcado
- matemática
- máximo
- significa
- Mídia
- apenas
- método
- poder
- erros
- modelo
- mais
- a maioria
- nome
- natural
- Novo
- PNL
- número
- números
- numpy
- of
- on
- ONE
- Outros
- saída
- marcante
- próprio
- parte
- atuação
- permissão
- fotografia
- peças
- platão
- Inteligência de Dados Platão
- PlatãoData
- ponto
- pontos
- população
- prática
- predição
- Previsões
- primeiro
- Prévio
- probabilidade
- Problema
- problemas
- adequado
- provou
- propósito
- Python
- em vez
- Leia
- reais
- mundo real
- Vermelho
- região
- regiões
- regressão
- permanecem
- representante
- se assemelha
- resultar
- Resultados
- retorno
- Retorna
- ROBERT
- uma conta de despesas robusta
- mesmo
- Ciência
- Cientista
- scikit-learn
- Pesquisar
- Segundo
- AUTO
- sentido
- serve
- conjunto
- Baixo
- rede de apoio social
- semelhante
- simples
- desde
- solteiro
- situações
- pequeno
- So
- alguns
- algo
- estável
- padrão
- começo
- Declaração
- Passo
- Ainda
- bem sucedido
- Tire
- teste
- ensaio
- que
- A
- deles
- Eles
- assim sendo
- Este
- coisas
- três
- Jogando
- para
- também
- topo
- para
- brinquedo
- Training
- verdadeiro
- VIRAR
- us
- usar
- geralmente
- validação
- Valores
- versão
- Caminho..
- BEM
- O Quê
- O que é a
- qual
- enquanto
- Wikipedia
- precisarão
- de
- Atividades:
- trabalho
- que vale a pena
- seria
- Errado
- X
- Produção
- rendimentos
- investimentos
- zefirnet