-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patherros-amostrais.qmd
144 lines (104 loc) · 6.1 KB
/
erros-amostrais.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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# Erros Amostrais
Este é um dos conceitos mais fundamentais com os quais lidamos na aprendizagem de máquina e previsão. Temos dois tipos de erros amostrais: o **erro dentro da amostra (*in sample error*)** e o **erro fora da amostra (*out of sample error*)**.
## **Erro dentro da Amostra (*In Sample Error*)**
A taxa de erro dentro da amostra refere-se ao erro calculado no mesmo conjunto de dados utilizado para treinar o modelo preditivo. Na literatura, isso é frequentemente denominado como "erro de resubstituição". Em outras palavras, essa taxa de erro mede o quanto algoritmo de previsão se ajusta exatamente aos mesmos dados utilizados para o treinamento do modelo. No entanto, quando o modelo é aplicado a um novo conjunto de dados, é esperado que essa precisão diminua.
## **Erro fora da Amostra (*Out of Sample Error*)**
É a taxa de erro que você recebe em um novo conjunto de dados. Na literatura às vezes é chamado de erro de generalização. Uma vez que coletamos uma amostra de dados e construímos um modelo para ela, podemos querer testá-lo em uma nova amostra, por exemplo uma amostra coletada em um horário diferente ou em um local diferente. Daí podemos analisar o quão bem o algoritmo executará a predição nesse novo conjunto de dados.
### **Algumas ideias-chave**
1. Quase sempre o erro fora da amostra é o que interessa.
2. Erro dentro da amostra é menor que o erro fora da amostra.
3. Um erro frequente é ajustar muito o algoritmo aos dados que temos. Em outras palavras, criar um modelo sobreajustado (também chamado de *overfitting*(\*)).
(\*) ***Overfitting*** é um termo usado na estatística para descrever quando um modelo estatístico se ajusta muito bem a um conjunto de dados anteriormente observado e, como consequência, se mostra ineficaz para prever novos resultados.
Vejamos um exemplo de erro dentro da amostra *vs* erro fora da amostra:
```{r, include=FALSE}
library(kernlab)
data(spam)
head(spam)
set.seed(127)
indices = sample(dim(spam)[1], size = 2760)
treino = spam[indices,]
teste = spam[-indices,]
predicao=ifelse(treino$your>0.8,"spam","nonspam")
table(predicao,treino$type)/length(treino$type)
predicao=ifelse(teste$your>0.8,"spam","nonspam")
table(predicao,teste$type)/length(teste$type)
```
```{r}
set.seed(131)
# Vamos selecionar as linhas da base de dados spam através de uma amostra de tamanho 10 das 4601 linhas
# dos dados:
spamMenor = spam[sample(dim(spam)[1], size = 10), ]
# Vamos criar um vetor composto pelos rótulos "1" e "2".
# Se um e-mail da nossa amostra for spam, recebe "1", se não for spam, recebe "2".
spamRotulos = (spamMenor$type == "spam")*1 + 1
# Na nossa base a variável capitalAve representa a média de letras maiúsculas por linha.
plot(spamMenor$capitalAve, col = spamRotulos, xlab = "Quantidade de Letras Maiúsculas",
ylab = "Frequência", main = "Letras Maiúsculas em spam (vermelho) e em ham (preto)",
pch = 19)
```
Podemos notar que, em geral, as mensagens classificadas como spam possuem uma frequência maior de letras maiúsculas do que as mensagens classificadas como não spam. Com base nisso queremos construir um preditor, onde podemos classificar e-mails como spam se a frequência de letras maiúsculas for maior que uma determida constante, e não spam caso contrário.
Veja que se separarmos os dados pela frequência de letras maiúsculas maior que 2,5 e classificarmos o que está acima como spam e abaixo como não spam, ainda teríamos duas observações que não são spam acima da linha.
```{r}
plot(spamMenor$capitalAve, col = spamRotulos, xlab = "Quantidade de Letras Maiúsculas",
ylab = "Frequência", main = "Letras Maiúsculas em spam (vermelho) e em ham (preto)",
pch = 19)
abline(h = 2.5, lty = 3, col = "blue")
```
Então o melhor para esse caso é criar o seguinte modelo:
- letras maiúsculas \> 2,5 e \< 3,8 ⇒ spam;
- letras maiúsculas \< 2,5 ou \> 3,8 ⇒ não spam.
```{r}
plot(spamMenor$capitalAve, col = spamRotulos, xlab = "Quantidade de Letras Maiúsculas",
ylab = "Frequência", main = "Letras Maiúsculas em spam (vermelho) e em ham (preto)",
pch = 19)
abline(h = c(2.5, 3.8), lty = 3, col = "blue")
```
```{r}
# construindo o modelo sobreajustado
modelo.sobreajustado = function(x){
predicao = rep(NA, length(x))
predicao[(x>=2.5 & x<=3.8)] = "spam"
predicao[(x<2.5 | x>3.8)] = "nonspam"
return(predicao)
}
# avaliando o modelo sobreajustado
resultado = modelo.sobreajustado(spamMenor$capitalAve)
table(resultado, spamMenor$type)
```
Note que obtivemos uma precisão perfeita nessa amostra, como já era esperado. Nesse caso, o erro dentro da amostra é de 0%. Mas será que esse modelo é o mais eficiente em outros dados também?
Vamos usar essa segunda regra para criarmos um modelo mais geral:
- letras maiúsculas \> 2,5 ⇒ spam;
- letras maiúsculas \<= 2,5 ⇒ não spam.
```{r}
plot(spamMenor$capitalAve, col = spamRotulos, xlab = "Quantidade de Letras Maiúsculas",
ylab = "Frequência", main = "Letras Maiúsculas em spam (vermelho) e em ham (preto)",
pch = 19)
abline(h = 2.5, lty = 3, col = "blue")
```
```{r}
# construindo o modelo geral
modelo.geral = function(x){
predicao = rep(NA, length(x))
predicao[x>=2.5] = "spam"
predicao[x<2.5] = "nonspam"
return(predicao)
}
# avaliando o modelo geral
resultado2 = modelo.geral(spamMenor$capitalAve)
table(resultado2, spamMenor$type)
```
Observe que dessa forma temos um erro dentro da amostra de 20%. Vamos agora aplicar esses dois modelos para toda a base de dados:
```{r}
table(modelo.sobreajustado(spam$capitalAve), spam$type)
```
```{r}
table(modelo.geral(spam$capitalAve), spam$type)
```
Olhando para a precisão de nossos modelos:
```{r}
sum(modelo.sobreajustado(spam$capitalAve) == spam$type)
```
```{r}
sum(modelo.geral(spam$capitalAve) == spam$type)
```
Observe que utilizando o modelo sobreajustado obtivemos um erro fora da amostra de 40,77%, enquanto que com o modelo geral esse erro foi de 27,95%. Note que se queremos construir um modelo que melhor representa qualquer amostra que pegarmos, um modelo **não** sobreajustado possuirá uma precisão maior.