All Posts By

diogowolff

Dicas de R: fazendo uma classificação KNN

By | Dicas de R

No Dicas de R de hoje, vamos falar como funciona a classificação KNN (K nearest neighbours), aplicar o método em um exemplo, e visualizar o resultado a partir da amostra. O escopo de métodos como o KNN é de problemas de classificação. Ao invés de utilizar dados para prever resultados contínuos como em regressões lineares, são criadas regras de decisão para a classe esperada de uma observação. Ademais, tais classes podem ser utilizadas para a previsão de variáveis supostas contínuas, sendo um dos métodos mais simples de estimação não-paramétrica.

O desenvolvimento de métodos de classificação é baseado em distribuições condicionais. Considerando como melhor classificador aquele que minimiza o valor esperado da taxa de erros de teste (o número de classificações feitas erradas sobre o total, a partir da estimação de treino), podemos provar que a melhor regra de decisão é aquela que assinala a classe de maior probabilidade, dado os valores das variáveis de previsão. Essa regra é chama de classificador de Bayes, e depende do conhecimento completo das distribuições condicionais da variável a ser classificada, logo muitas vezes não é possível utilizá-lo.

Com isso, vamos explicar como funciona o classificador KNN. Após separarmos os dados entre treino e teste, definimos a seguinte regra: para uma observação das variáveis regressoras de teste, são identificados os K pontos de treino mais próximos à posição da amostra, e a probabilidade condicional de cada classe é a frequência relativa de sua ocorrência entre os pontos escolhidos. Desse modo, a classificação estimada para o ponto de teste é igual à classe que ocorre mais vezes dentre os K pontos de treino. A escolha do número K é importante: quanto menor for K, menor será a taxa de erro de treino (para K=1, a amostra será perfeitamente classificada), porém a classificação gerará padrões complicados e pode ter alta taxa de erro de teste, dependendo da amostra. Isso condiz com o tradeoff de viés-variância, de modo que, quanto menor o K, menor é o viés da classificação (pois está mais próxima dos dados reais), porém maior a variância da classificação entre amostras distintas, enquanto que, quanto maior o K, menor é o impacto de amostras diferentes de treino sobre o classificador final, abrindo mão de parte da acurácia do modelo.

Vamos então partir para um exemplo. Os dados utilizados serão do clássico dataset iris, contendo 4 dados de medição de flores, e suas respectivas espécies. Primeiramente, vamos utilizar a classificação KNN para tentar prever a espécie de cada flor a partir das medições de suas pétalas. Gerando os dados:

dados <- iris
class <- dados[,3:5]

train <- c(1:30, 51:80, 101:130)
class_train <- dados[train,]
class_test <- dados[-train,]

Então, podemos realizar a classificação utilizando a função knn(), do pacote class. Seus inputs são os dados de treino, teste, o número K e a classificação correta do treino. Abaixo, o modelo e sua previsão, comparada com os valores reais:


library(class)

pred = knn(train = class_train[,1:2], test = class_test[1:2], cl = class_train[,3], k = 4)

table(pred, class_test[,3])

pred setosa versicolor virginica
setosa 20 0 0
versicolor 0 20 1
virginica 0 0 19

Como podemos ver, o modelo acertou quase todas as classificações, com apenas um erro. Ele funcionou tão bem pois as variáveis se separam em grupos bem distintos, e, como o comprimento das pétalas se diferencia bastante entre as espécies - e possui escala maior, logo tem muito mais impacto na regra de decisão -, ele facilita a regra de decisão. Abaixo, vamos plotar o classificador para K=4, em conjunto com os pontos de teste. O código gera uma malha de pontos que cobrem o gráfico, e então faz a classificação KNN sobre cada um dos pontos da malha. Após isso, geramos um dataframe que indica os pontos onde o contorno deve ser de uma espécie, e onde não deve ser, para cada uma das 3 espécies, de modo a gerar 3 contornos que, por hipótese, não se sobrepõem. Com esse dataframe, podemos utilizar a geom_contour() do ggplot2, criando assim o gráfico abaixo:


library(ggplot2)
library(tidyverse)
library(MASS)

cover <- expand.grid(x=seq(min(class_train[,1]-1), max(class_train[,1]+1),
by=0.1),
y=seq(min(class_train[,2]-1), max(class_train[,2]+1),
by=0.1))

cover_class <- knn(train = class_train[,1:2], cover, cl = class_train[,3], k = 4)

dataf <- bind_rows(mutate(cover,
cls="setosa",
prob_cls=ifelse(cover_class==cls,
T, F)),
mutate(cover,
cls="versicolor",
prob_cls=ifelse(cover_class==cls,
T, F)),
mutate(cover,
cls="virginica",
prob_cls=ifelse(cover_class==cls,
T, F)))

ggplot(dataf) +
geom_point(aes(x=x, y=y, color=cls),
data = mutate(cover, cls=cover_class),
size=1.2) +
geom_contour(aes(x=x, y=y, z=prob_cls, group=cls, color=cls),
bins=2,
data=dataf) +
geom_point(aes(x=Petal.Length, y=Petal.Width, col=Species),
size=3,
data=class_test)+
labs(x='Petal Length',y = 'Petal Width', colour = 'Species')+
theme_minimal()

 

Conteúdos como esse podem ser encontrados no nosso Curso de Machine Learning usando o R.


Semana de calmaria nos indicadores do FOCUS

By | Indicadores

No boletim FOCUS dessa semana, vemos uma estabilidade quase plena nas previsões, refletindo a falta de choques dos últimos dias. A única variação digna de nota é a do IGP, que aumentou de 13.15% para 14.32%, porém esse movimento parece ser apenas parte da escalada do índice que já vem ocorrendo há meses.

As expectativas do IPCA fecharam a semana com média de 5.4% e desvio-padrão de 0.35%. A SELIC continua sendo estimada com mediana de 5.50%, porém houve um aumento de seu desvio-padrão de 0.59% para 0.6%. Ao mesmo tempo, vemos que sua média continua abaixo da mediana, em 5.41%, indicando que há uma minoria no mercado que ainda vê cenários de valores mais baixos para a SELIC no final do ano. Abaixo, o gráfico das variáveis:

A maior expectativa do IGP foi de 20.17% para 19.10%, porém a média das observações tem se mantido consideravelmente acima da mediana (pelo menos 0.2%) há 8 semanas, indicando que há um menor número de observações mais elevado puxando a estimação média para cima.

Membros do Clube AM, por suposto, têm acesso a todos os códigos desse exercício.

____________________________

Dicas de R: usando Python dentro do R

By | Dicas de R

No Dicas de R de hoje, vamos mostrar como você pode rodar código em Python dentro do próprio R, facilitando a integração para pessoas que estão começando no R e já têm conhecimento de Python, ou que querem embutir em seu código o ferramental de Python, que muitas vezes pode agilizá-lo e resolver problemas. Essa integração pode ser feita através do pacote reticulate, como mostraremos a seguir. Vamos supor aqui que você já tem tanto o R como o Python instalados, e também já possui todos os pacotes de Python e de R que quer usar. Para carregar o Python no R, basta rodar:


library(reticulate)

O R irá carregar a sua versão padrão de Python. Se quiser utilizar outra (como ao começar um projeto), basta adicionar o código

use_python("/usr/local/bin/python")

Substituindo o argumento pelo caminho até a versão utilizada. Feito isso, vamos carregar o pandas como exemplo:

 
pd = import('pandas')

Após carregar a library, ela se torna um objeto no R como qualquer outro. Suas funções podem ser acessadas com o operador $, como se fossem colunas. Com isso, o código fica semelhante a um código de Python, usando pd$read_csv ao invés de pd.read_csv, por exemplo.

Para rodar códigos básicos de Python, existem as funções py_run_string(), que recebe strings de código como argumento, e py_run_file(), que recebe um script completo.

Como os objetos de uma linguagem não podem ser operados diretamente por outra, o reticulate transforma objetos de R em objetos de Python sempre que você chama uma função do Python sobre um objeto de seu environment base, e os transforma de volta após finalizar a função. Caso queira trabalhar com objetos de Python ao longo de várias funções, também é possível importar um módulo do Python e impedir que a transformação automática seja feita após suas funções:

 
pd = import('pandas', convert = FALSE)

Com isso, os objetos trabalhados serão de Python, e depois disso para transformá-los em objetos de R basta rodar py_to_r(nome_do_objeto).

O pacote apresentado aqui permite integração total entre o Python e o R, facilitando o uso de ferramentas estatísticas integradas no R para usuários de Python. Para mais informações sobre ele, recomendamos sua página principal, disponível aqui.


A perda de confiança no BACEN

By | Indicadores

No boletim FOCUS dessa semana, vemos a confirmação da trajetória crescente das expectativas do IPCA, indo de 4.92% para 5.01%, assim como uma forte correção para o IGP-M, que foi de 12.66% para 13.15%. Apesar disso, os dados para 2021 não contam toda a história. A expectativa do IPCA para 2022 se manteve no nível de semana passada de 3.60%, acima da meta para o ano, que é de 3.5%. Isso indica uma certa desconfiança sobre o comprometimento do BACEN com a sustentação da meta, correndo o risco de desancoragem das expectativas. Como resultado, as expectativas da SELIC seguem aumentando para o final de 2021, indo de 5.25% para 5.50%, indicando que nos próximos meses é esperada uma correção forte da trajetória de inflação por parte do BACEN.

Abaixo, as expectativas das principais variáveis disponibilizadas:

Membros do Clube AM, por suposto, têm acesso a todos os códigos desse exercício.

____________________________

Dicas de R: alguns truques para melhorar seus gráficos

By | Dicas de R

No Dicas de R de hoje, vamos apresentar algumas funções que podem melhorar a qualidade dos seus gráficos em ggplot, utilizando para nossas visualizações usando o clássico mtcars. Um gráfico comumente utilizado para a exploração de uma base é o seu histograma, como a seguir:


library(ggplot2)
library(tidyverse)

dados <- mtcars

dados %>% ggplot(aes(x=factor(cyl), y = mpg))+
geom_boxplot()+
labs(y='Milhas por Galão', x = 'Número de cilindros')+
theme_bw()

Porém, podemos utilizar uma alternativa que facilita a visualização da distribuição estimada dos valores, chamada de Kernel Density Estimation. Ela é parente do histograma, e permite uma visualização mais suavizada dos dados. Ademais, com o pacote ggridges, podemos fazer uma visualização semelhante à acima, exibindo os quartis estimados:


library(ggridges)

dados %>% ggplot(aes(x=mpg, y = factor(cyl),
fill = factor(stat(quantile))))+
labs(x='Milhas por Galão', y = 'Número de cilindros')+
scale_x_continuous(breaks = seq(10, 35, by = 5))+
stat_density_ridges(geom = "density_ridges_gradient",
quantile_lines = TRUE, alpha = 1,
rel_min_height = 0.01,
scale = 0.9,
size = 1)+
scale_fill_viridis_d(name = "Quartis")+
theme_minimal()

Agora, vamos adicionar à análise o peso dos carros. Para isso, o modo mais simples de visualizarmos os dados é o gráfico de dispersão:


dados %>% ggplot(aes(x=mpg, y=wt, color=factor(cyl), shape = factor(cyl)))+
geom_point(size = 3) +
labs(x='Milhas por Galão', y = 'Peso', color='Cilindros', shape='Cilindros')

A visualização é facilitada pela inclusão de tanto cores como formatos para cada tipo de variável, permitindo distinguir os pontos que estabelecem a relação descrita. Como podemos ver, a correlação negativa entre as variáveis é fortemente ditada pelos grupos que se definem pelo número de cilindros. Podemos facilitar a visualização da posição dos grupos adicionando elipses em torno de cada um:


dados %>% ggplot(aes(x=mpg, y=wt, color=factor(cyl), shape = factor(cyl)))+
geom_point(size = 3) +
labs(x='Milhas por Galão', y = 'Peso', color='Cilindros', shape='Cilindros')+
stat_ellipse(size=1.05)

 


Seja avisado da nossa próxima aula ao vivo de R para Análise de Dados, toda terça-feira, às 21h!

Quero ser avisado
{"cart_token":"","hash":"","cart_data":""}