-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpred.qmd
108 lines (69 loc) · 6.22 KB
/
pred.qmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# Predição
Queremos então construir um algoritmo "preditor" capaz de inferir se um dado pertence ou não a uma certa categoria. O preditor será formado dos seguintes componentes:
Pergunta → Amostra de entrada → Características → Algoritmo → Parâmetros → Avaliação
## **Pergunta**
O nosso objetivo é responder a uma pergunta de tipo "O dado A é do tipo x ou do tipo y?". Por exemplo, podemos querer saber se é possível detectar automaticamente se um e-mail é um spam ou um "ham", isto é, não spam. O que na verdade queremos saber é: "É possível usar características quantitativas para classificar um e-mail como spam?".
## **Amostra de Entrada**
Uma vez formulada a pergunta, precisamos obter uma amostra de onde tentaremos extrair informações que caracterizam a categoria a qual um dado pertence e então usar essas informações para classificar outros dados não categorizados. O ideal é que se tenha uma amostra grande, assim teremos melhores parâmetros para construir nosso preditor.
No caso da pergunta sobre um e-mail ser spam ou não, temos acesso a base de dados "spam" disponível no pacote "kernlab", onde cada linha dessa base é um e-mail e nas colunas temos a porcentagem de palavras e números contidos em cada e-mail e, entre outras coisas, a nossa variável de interesse "type" que classifica o e-mail como spam ou não:
```{r}
library(kernlab)
data(spam)
head(spam)
```
Obtida a amostra, precisamos dividi-la em duas partes que chamaremos de *Conjunto de Treino* e *Conjunto de Teste*. O conjunto de treino será usado para construir o algoritmo. É dele que vamos extrair as informações que julgarmos utéis para classificar uma categoria de dado. É importante que o modelo de previsão seja feito com base **apenas** no conjunto de treino.
```{r}
set.seed(127)
indices = sample(dim(spam)[1], size = 2760)
treino = spam[indices,]
teste = spam[-indices,]
```
Após construido o algoritmo, usaremos o conjunto de teste para obter a estimativa de erro, que será detalhada mais a frente.
## **Características**
Temos que encontrar agora características que possam indicar a categoria dos dados. Podemos, por exemplo, vizualizar algumas variáveis graficamente para obter uma ideia do que podemos fazer. No nosso exemplo de e-mails, podemos querer avaliar se a frequência de palavras "your" em um e-mail pode indicar se ele é um spam ou não.
```{r}
plot(density(treino$your[treino$type=="nonspam"]), col="blue",
main = "Densidade de 'your' em ham (azul) e spam (vermelho)",
xlab = "Frequência de 'your'", ylab = "densidade")
lines(density(treino$your[treino$type=="spam"]), col="red")
```
Pelo gráfico podemos notar que a maioria dos e-mails que são spam têm uma frequência maior da palavra "your". Por outro lado, aqueles que são classificados como ham (não spam) têm um pico mais alto perto do 0.
## **Algoritmo**
Com base nisso podemos construir um algoritmo para prever se um e-mail é spam ou ham. Podemos estimar um modelo onde queremos encontrar uma constante *c* tal que se a frequência da palavra "your" for maior que *c*, então classificamos o e-mail como spam. Caso contrário, classificamos o e-mail como não spam.
Vamos observar graficamente como ficaria esse modelo se *c*=0.8.
```{r}
plot(density(treino$your[treino$type=="nonspam"]), col="blue",
main = "Densidade de 'your' em ham (azul) e spam (vermelho)",
xlab = "Frequência de 'your'", ylab = "densidade")
lines(density(treino$your[treino$type=="spam"]), col="red")
abline(v=0.8,col="black")
```
Os e-mails à direita da linha preta seriam classificados como spam, enquanto que os à esquerda seriam classificados como não spam.
### **Avaliação**
Agora vamos avaliar nosso modelo de predição.
```{r}
predicao=ifelse(treino$your>0.8,"spam","nonspam")
table(predicao,treino$type)/length(treino$type)
```
Podemos ver que quando os e-mails não eram spam e classificamos como "não spam", de acordo com nosso modelo, em 50% do tempo nós acertamos. Quando os e-mails eram spam e classificamos ele em spam, por volta de 26% do tempo nós acertamos. Então, ao total, nós acertamos por volta de 50+26=76% do tempo. Então nosso algoritmo de previsão tem uma precisão por volta de 76% na amostra treino.
```{r}
predicao=ifelse(teste$your>0.8,"spam","nonspam")
table(predicao,teste$type)/length(teste$type)
```
Já na amostra teste acertamos 48+27=75% das vezes. O erro na amostra teste é o que chamamos de erro real. É o erro que esperamos em amostras novas que passarem por nosso preditor.
### **Como construir um bom algoritmo de aprendizado de máquina?**
O "melhor" método de aprendizado de máquina é caracterizado por:
- Uma boa base de dados;
- Uma base de dados com dados suficientes para que o modelo possa explicar a realidade além daqueles dados
- Uma base de dados que seja equilibrada em variáveis resposta
- Uma base de dados que não tenha ou que tenha poucos dados faltantes
- Reter informações relevantes;
- Ser bem interpretável;
- Fácil de ser explicado e entendido;
- Ser preciso;
- Fácil de se construir e de se testar em pequenas amostras;
- Fácil aplicar a um grande conjunto de dados.
Os erros mais comuns, que se deve tomar um certo cuidado, são:
- Tentar automatizar a seleção de variáveis (características) de uma maneira que não permita que você entenda como essas variáveis estão sendo aplicadas para fazer previsões;
- Não prestar atenção a peculiaridades específicas de alguns dados, como comportamentos estranhos de variáveis específicas (algo que pode ocorrer no formato de **outliers**, ou variação quase-nula fraccionada, quando a variabilidade é normal até certo ponto da variável resposta, e aí a variabilidade é completamente nula, dentre outras infinitudes de possíveis comportamentos estranhos que dependem do nosso senso crítico);
- Jogar fora informações desnecessariamente. Isso pode ocorrer quando realizamos seleções de variáveis de maneira restrita demais, ou quando nossa análise de outliers jogou fora outliers que na verdade eram importantes pra explicação da variável resposta, dentre (novamente) diversas outras formas de manipulação de dados que diminuem a eficiência do nosso modelo preditor por estar descartando informações valiosas.