Neste relatório iremos trabalhar com uma base de dados com características de peixes. Segundo https://pt.wikipedia.org/wiki/Peixe e https://www.biologianet.com/, os peixes são animais vertebrados, aquáticos, tipicamente ectotérmicos, ou seja, não produzem calor suficiente para a termorregulação, assim, ajustam suas temperaturas corporais por meio de mecanismos comportamentais. Além disso, possuem o corpo fusiforme (mais espesso ao centro e atenuando-se em direção às extremidades), os membros transformados em barbatanas ou nadadeiras (ausentes em alguns grupos) sustentadas por raios ósseos ou cartilaginosos, guelras ou brânquias com que respiram o oxigénio dissolvido na água (embora os dipnóicos usem pulmões) e, na sua maior parte, o corpo coberto de escamas.
Aqui temos como objetivo predizer o peso (regressão) e espécie (classificação). A base de dados é composta pelas seguintes variáveis:
Species: Determina as características de um determinado grupo de peixes.
Weigth: Peso do peixe (em gramas).
Length1, Length2 e Length3: Variáveis relacionadas ao comprimento do peixe (em centímetros).
Height: Altura do peixe (em centímetros).
Width: Largura do peixe (em centímetros).
Iremos iniciar importando a base de dados, verificando como estão nomeadas as variáveis, a existência de dados faltantes e entendendo quais é a classe de cada uma das variáveis que estamos trabalhando:
library(tidyverse)
library(patchwork)
library(knitr)
library(Metrics)
library(parallel)
library(lasso2)
library(randomForest)
library(MASS)
# Importando os dados
dados <- read.csv("Fish.csv")
# Nomes das variáveis
names(dados)
## [1] "ï..Species" "Weight" "Length1" "Length2" "Length3"
## [6] "Height" "Width"
# Renomeando a variável sobre espécies
dados <- dados %>%
rename(Species = ï..Species)
# Verificando as variáveis novamente
names(dados)
## [1] "Species" "Weight" "Length1" "Length2" "Length3" "Height" "Width"
# Verificação de dados faltantes na base de dados
table(is.na(dados))
##
## FALSE
## 1113
# Classes de cada variável
str(dados)
## 'data.frame': 159 obs. of 7 variables:
## $ Species: chr "Bream" "Bream" "Bream" "Bream" ...
## $ Weight : num 242 290 340 363 430 450 500 390 450 500 ...
## $ Length1: num 23.2 24 23.9 26.3 26.5 26.8 26.8 27.6 27.6 28.5 ...
## $ Length2: num 25.4 26.3 26.5 29 29 29.7 29.7 30 30 30.7 ...
## $ Length3: num 30 31.2 31.1 33.5 34 34.7 34.5 35 35.1 36.2 ...
## $ Height : num 11.5 12.5 12.4 12.7 12.4 ...
## $ Width : num 4.02 4.31 4.7 4.46 5.13 ...
# Tornando cada variável em um vetor para facilitar o código
attach(dados)
A partir de agora iremos fazer uma análise exploratória. Abaixo veremos alguns histogramas para entendermos a distribuição das variáveis numéricas, as quais estão presentes na base de dados em análise.
p1 <- ggplot(dados, aes(Weight)) + geom_histogram(fill = "#1B9E77", color = "grey", bins = 30)
p2 <- ggplot(dados, aes(Length1)) + geom_histogram(fill = "#1B9E77", color = "grey", bins = 30)
p3 <- ggplot(dados, aes(Length2)) + geom_histogram(fill = "#1B9E77", color = "grey", bins = 30)
p4 <- ggplot(dados, aes(Length3)) + geom_histogram(fill = "#1B9E77", color = "grey", bins = 30)
p5 <- ggplot(dados, aes(Height)) + geom_histogram(fill = "#1B9E77", color = "grey", bins = 30)
p6 <- ggplot(dados, aes(Width)) + geom_histogram(fill = "#1B9E77", color = "grey", bins = 30)
(p1 | p2) / (p3 | p4) / (p5 | p6) # juntando gráficos dos objetos p1,...,p6
Podemos ver que a variável Weight pode ter a presença de uma observação de um peixe com 0 gramas, o que não faz sentido. Para verificar se realmente temos esse zero iremos utilizar o seguinte comando:
table(dados$Weight==0) # verificando se existe alguma observação em Weight igual a 0
##
## FALSE TRUE
## 158 1
order(dados$Weight, decreasing = FALSE)[1] # encontrando a linha do 0
## [1] 41
dados <- dados[-41,] # excluindo a linha com a observação Weight igual a 0
table(dados$Weight==0) # verificando novamente
##
## FALSE
## 158
Agora, para entender também o comportamente da variável categorica Species, iremos criar uma tabela que nos mostre o quanto cada uma das espécies representam em relação ao todo.
# Gerando tabela de frequencia relativa das espécies
kable(table(Species)/length(Species), col.names = c("Species", "Freq. Relativa"), format = "html")
| Species | Freq. Relativa |
|---|---|
| Bream | 0.2215190 |
| Parkki | 0.0696203 |
| Perch | 0.3544304 |
| Pike | 0.1075949 |
| Roach | 0.1202532 |
| Smelt | 0.0886076 |
| Whitefish | 0.0379747 |
Iremos predizer primeiramente a variável Weigth e para isso vamos dar uma olhada em qual é o comportamento das demais variáveis quando a temos como variável resposta. Para as variáveis númericas utilizaremos gráficos de dispersão e para a categórica um boxplot.
p7 <- ggplot(dados, aes(x = Length1, y = Weight)) + geom_point(aes(color = Species))+ scale_color_brewer(palette = "Dark2")
p8 <- ggplot(dados, aes(x = Length2, y = Weight)) + geom_point(aes(color = Species))+ scale_color_brewer(palette = "Dark2")
p9 <- ggplot(dados, aes(x = Length3, y = Weight)) + geom_point(aes(color = Species))+ scale_color_brewer(palette = "Dark2")
p10 <- ggplot(dados, aes(x = Height, y = Weight)) + geom_point(aes(color = Species)) + scale_color_brewer(palette = "Dark2")
p11 <- ggplot(dados, aes(x = Width, y = Weight)) + geom_point(aes(color = Species))+ scale_color_brewer(palette = "Dark2")
p12 <- ggplot(dados, aes(x = Species, y = Weight)) + geom_boxplot(aes(fill=Species)) + scale_fill_brewer(palette = "Dark2")
combined <- (p7 | p8) / (p9 | p10) / (p11|p12) & theme(legend.position = "bottom")
combined + plot_layout(guides = "collect") #juntando gráficos dos objetos p7,...,p12
Com a imagem acima podemos perceber que as variáveis númericas tem uma relação positiva com a variável resposta Weight. Podemos citar também que nas variáveis de comprimento Length1, Length2 e Length3 temos um leve deslocamento para a direita devido ao que cada uma dessas variáveis representa e temos um destaque para a espécie Pike tem os peixes mais compridos e é muito fácil de distinguir-la do restante das espécies quando analisamos as variáveis de comprimento. Além disso, podemos ver também que a variável Height relacionada com Weight distingue muito bem cada uma das espécies dos peixes e pode ser de suma importância para a predição das espécies.
Por fim, quando analisado o boxplot podemos ver de forma clara que os peixes mais pesados pertencem a espécie Pike, os mais leves a Smelt, a maior mediana de peso pertence à espécie Bream e é também a que tem maior concentração em um peso elevado se comparado ao restante. Importante ressaltar também que Roach é a única espécie com outliers (2).
Iremos criar algumas novas variáveis que podem ser úteis para a predição. Como estamos querendo obter a predição da variável Weight, a primeira nova variável a ser adicionada na base de dados será a seguinte:
\[ \mbox{area} = \mbox{Height*Length1} \]
dados <- dados %>%
mutate(area = Height*Length1)
names(dados)
## [1] "Species" "Weight" "Length1" "Length2" "Length3" "Height" "Width"
## [8] "area"
Uma outra variável que iremos criar é uma que nos dê uma informação um de algo relacionado ao volume:
\[ \mbox{vol} = \mbox{area*Width} \]
dados <- dados %>%
mutate(vol = area*Width)
names(dados)
## [1] "Species" "Weight" "Length1" "Length2" "Length3" "Height" "Width"
## [8] "area" "vol"
Uma mais voltada para uma proporção tamanho do peixe inteiro (incluso rabo) em relação ao comprimento do “corpo” dos peixes:
\[ \mbox{rabo} = \frac{\mbox{Length3}}{Length1} \]
dados <- dados %>%
mutate(rabo = Length3/Length1)
names(dados)
## [1] "Species" "Weight" "Length1" "Length2" "Length3" "Height" "Width"
## [8] "area" "vol" "rabo"
Aqui a ideia será a criação de algo como um Índice de Massa Corporal:
\[ \mbox{i_massa} = \frac{\mbox{Weight}}{Height} \]
dados <- dados %>%
mutate(i_massa = Weight/Height)
names(dados)
## [1] "Species" "Weight" "Length1" "Length2" "Length3" "Height" "Width"
## [8] "area" "vol" "rabo" "i_massa"
Vamos criar uma medida da “quadratura” do peixe:
\[ \mbox{h_l1} = \frac{\mbox{Height}}{Length1} \]
dados <- dados %>%
mutate(h_l1 = Height/Length1)
names(dados)
## [1] "Species" "Weight" "Length1" "Length2" "Length3" "Height" "Width"
## [8] "area" "vol" "rabo" "i_massa" "h_l1"
Agora agora criar uma que nos permite entender se o peixe é mais inchado e coisas do tipo a partir de:
\[ \mbox{h_width} = \frac{\mbox{Height}}{Width} \]
dados <- dados %>%
mutate(h_width = Height/Width)
names(dados)
## [1] "Species" "Weight" "Length1" "Length2" "Length3" "Height" "Width"
## [8] "area" "vol" "rabo" "i_massa" "h_l1" "h_width"
Iremos criar uma medida sobre características do rabo do peixe:
\[ \mbox{l3_l2} = \frac{\mbox{Length3}}{Length2} \]
dados <- dados %>%
mutate(l3_l2 = Length3/Length2)
names(dados)
## [1] "Species" "Weight" "Length1" "Length2" "Length3" "Height" "Width"
## [8] "area" "vol" "rabo" "i_massa" "h_l1" "h_width" "l3_l2"
Por fim, podemos observar que as variáveis foram adicionadas uma por uma em nossa base de dados. Essas são algumas variáveis que podem vir contribuir com as predições. Iremos separar a base de dados em duas amostras aleatórias, sendo uma com 80% das observações para treinamento e 20% para a aplicação do modelo de predição.
# Separando as observações de treino e de aplicação do modelo de predição
set.seed(1) #semente
treino <- dados[sample(1:nrow(dados), round(0.8 * nrow(dados), 0),
replace = F), ] #objeto com base de dados para treino
aplicacao <- dados[sample(1:nrow(dados), round(0.2 * nrow(dados), 0),
replace = F), ]#objeto com base de dados para aplicação do modelo
head(treino) # 10 primeiras observações da base de treino
## Species Weight Length1 Length2 Length3 Height Width area vol
## 68 Parkki 145 19.8 21.5 24.1 9.7364 3.1571 192.7807 608.6280
## 129 Pike 300 31.7 34.0 37.8 5.7078 4.1580 180.9373 752.3371
## 43 Roach 150 20.4 22.0 24.7 5.8045 3.7544 118.4118 444.5653
## 14 Bream 340 29.5 32.0 37.3 13.9129 5.0728 410.4306 2082.0321
## 51 Roach 180 23.6 25.2 27.9 7.0866 3.9060 167.2438 653.2541
## 85 Perch 130 19.3 21.3 22.8 6.3840 3.5340 123.2112 435.4284
## rabo i_massa h_l1 h_width l3_l2
## 68 1.217172 14.89257 0.4917374 3.083969 1.120930
## 129 1.192429 52.55966 0.1800568 1.372727 1.111765
## 43 1.210784 25.84202 0.2845343 1.546053 1.122727
## 14 1.264407 24.43775 0.4716237 2.742647 1.165625
## 51 1.182203 25.40005 0.3002797 1.814286 1.107143
## 85 1.181347 20.36341 0.3307772 1.806452 1.070423
head(aplicacao) # 10 primeiras observações da base de aplicação
## Species Weight Length1 Length2 Length3 Height Width area vol
## 44 Roach 145 20.5 22.0 24.3 6.6339 3.5478 135.99495 482.4829
## 103 Perch 260 25.4 27.5 28.9 7.1672 4.3350 182.04688 789.1732
## 105 Perch 250 25.4 27.5 28.9 7.2828 4.5662 184.98312 844.6699
## 124 Perch 1000 39.8 43.0 45.2 11.9328 7.2772 474.92544 3456.1274
## 77 Perch 100 16.2 18.0 19.2 5.2224 3.3216 84.60288 281.0169
## 98 Perch 188 22.6 24.6 26.2 6.7334 4.1658 152.17484 633.9299
## rabo i_massa h_l1 h_width l3_l2
## 44 1.185366 21.85743 0.3236049 1.869863 1.104545
## 103 1.137795 36.27637 0.2821732 1.653333 1.050909
## 105 1.137795 34.32746 0.2867244 1.594937 1.050909
## 124 1.135678 83.80263 0.2998191 1.639752 1.051163
## 77 1.185185 19.14828 0.3223704 1.572254 1.066667
## 98 1.159292 27.92052 0.2979381 1.616352 1.065041
Com isso feito, já podemos começar a pensar em nosso modelo de predição.
Finalmente, criaremos o nosso primeiro modelo partindo de uma regrassão linear. A regressão linear encontra a linha que melhor representa as variáveis de entrada com a variável de saída, ou variável resposta.Por esse motivo, é uma possível método para termos uma boa predição dos dados, lembrando sempre que trata-se de um modelo probabilístico e estamos sempre lidando com um erro aleatório. Iniciaremos com um modelo básico com todas as covariáveis, exceto a variável i_massa, e veremos como ele desempenha.
fit1 <- lm(Weight ~ Species + Length1 + Length2 + Length3 + Height + Width+ area + vol + rabo + h_l1 + h_width + l3_l2,
data = treino) # definindo modelo de regressão
summary(fit1) # informações sobre o modelo criado
##
## Call:
## lm(formula = Weight ~ Species + Length1 + Length2 + Length3 +
## Height + Width + area + vol + rabo + h_l1 + h_width + l3_l2,
## data = treino)
##
## Residuals:
## Min 1Q Median 3Q Max
## -174.874 -25.850 -3.285 22.965 165.591
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -1.072e+03 1.084e+03 -0.989 0.32502
## SpeciesParkki 6.912e+01 5.501e+01 1.257 0.21163
## SpeciesPerch 2.807e+02 9.912e+01 2.832 0.00552 **
## SpeciesPike 1.533e+02 1.230e+02 1.247 0.21521
## SpeciesRoach 1.905e+02 7.965e+01 2.392 0.01848 *
## SpeciesSmelt 4.008e+02 1.203e+02 3.332 0.00118 **
## SpeciesWhitefish 2.594e+02 7.898e+01 3.285 0.00138 **
## Length1 -7.554e+01 6.707e+01 -1.126 0.26255
## Length2 3.172e+01 6.614e+01 0.480 0.63249
## Length3 4.693e+01 3.847e+01 1.220 0.22516
## Height -2.136e+02 3.646e+01 -5.858 5.13e-08 ***
## Width 9.068e+01 5.526e+01 1.641 0.10371
## area 5.498e+00 1.344e+00 4.090 8.33e-05 ***
## vol -1.335e-01 9.839e-02 -1.357 0.17757
## rabo -1.460e+03 1.399e+03 -1.044 0.29900
## h_l1 2.984e+03 5.672e+02 5.262 7.29e-07 ***
## h_width 3.954e+01 8.997e+01 0.440 0.66117
## l3_l2 1.642e+03 1.428e+03 1.149 0.25297
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 54.26 on 108 degrees of freedom
## Multiple R-squared: 0.9808, Adjusted R-squared: 0.9778
## F-statistic: 324.9 on 17 and 108 DF, p-value: < 2.2e-16
prediction1 <- predict(fit1, aplicacao) # salvando predições no objeto prediction1
df1 <- cbind(aplicacao, prediction = prediction1) # fazendo uma junção das predições com a base de dados para aplicação do modelo
rmse(aplicacao$Weight, predict(fit1, aplicacao)) # ROOT MEAN SQUARE DEVIATION
## [1] 49.95565
mae(aplicacao$Weight, predict(fit1, aplicacao)) # MEAN ABSOLUT PERCENT ERROR
## [1] 32.8559
ggplot(df1) + geom_point(aes(x = Weight, y = prediction, color = Species)) +
geom_line(aes(x = Weight, y = Weight)) + scale_color_brewer(palette = "Dark2") + theme(legend.position = "bottom") # gráico com valores verdadeiros no eixo x, valores preditos na variável resposta e também uma reta verdade
LASSO (Least Absolute Shrinkage and Selection Operator) nos permite fazer a regularização como a inserção de bias em um modelo. Ou em outras palavras, essa técnica desencoraja o ajuste excessivo dos dados, afim de diminuir a sua variância. Dentro da equação nos utilizaremos o LASSO para regularizar o modelo a partir de “penalidade”, nós alteramos os fatores de forma a priorizar ou não certas parcelas da equação e, assim, evitamos ‘overfitting’ (sobreajuste) e melhoramos a qualidade de predição.
fit_lasso <- lasso2::l1ce(Weight~Length1+Length2+Length3+Height+Width+area+vol+ rabo+h_l1+h_width+l3_l2,
data = treino,
sweep.out = NULL,
standardize = FALSE
) # LASSO com todas as variáveis colocadas sob restrição
summary(fit_lasso) # informações do modelo
## $call
## lasso2::l1ce(formula = Weight ~ Length1 + Length2 + Length3 +
## Height + Width + area + vol + rabo + h_l1 + h_width + l3_l2,
## data = treino, sweep.out = NULL, standardize = FALSE)
##
## $terms
## Weight ~ Length1 + Length2 + Length3 + Height + Width + area +
## vol + rabo + h_l1 + h_width + l3_l2
## attr(,"variables")
## list(Weight, Length1, Length2, Length3, Height, Width, area,
## vol, rabo, h_l1, h_width, l3_l2)
## attr(,"factors")
## Length1 Length2 Length3 Height Width area vol rabo h_l1 h_width l3_l2
## Weight 0 0 0 0 0 0 0 0 0 0 0
## Length1 1 0 0 0 0 0 0 0 0 0 0
## Length2 0 1 0 0 0 0 0 0 0 0 0
## Length3 0 0 1 0 0 0 0 0 0 0 0
## Height 0 0 0 1 0 0 0 0 0 0 0
## Width 0 0 0 0 1 0 0 0 0 0 0
## area 0 0 0 0 0 1 0 0 0 0 0
## vol 0 0 0 0 0 0 1 0 0 0 0
## rabo 0 0 0 0 0 0 0 1 0 0 0
## h_l1 0 0 0 0 0 0 0 0 1 0 0
## h_width 0 0 0 0 0 0 0 0 0 1 0
## l3_l2 0 0 0 0 0 0 0 0 0 0 1
## attr(,"term.labels")
## [1] "Length1" "Length2" "Length3" "Height" "Width" "area" "vol"
## [8] "rabo" "h_l1" "h_width" "l3_l2"
## attr(,"order")
## [1] 1 1 1 1 1 1 1 1 1 1 1
## attr(,"intercept")
## [1] 1
## attr(,"response")
## [1] 1
## attr(,".Environment")
## <environment: R_GlobalEnv>
##
## $bound
## [1] 5060.412
##
## $relative.bound
## [1] 0.5
##
## $Lagrangian
## [1] 2.025343
##
## $residuals
## [1] -5.573904e+00 7.136561e+00 -9.120172e+00 -1.865303e+02 -7.693285e+00
## [6] 4.155466e-03 -6.560690e+01 3.707250e+00 -2.343239e+00 7.273019e+01
## [11] -5.880138e+00 -4.781125e+00 -1.753180e+01 -1.981020e+01 -5.631297e+01
## [16] -1.197240e+02 1.761686e+01 -8.581393e+01 6.683036e+00 -8.306691e+01
## [21] -1.933844e+01 4.600149e+01 2.776697e+01 1.132785e+00 8.357215e+01
## [26] 4.201495e+01 1.380813e+01 1.105230e+02 -7.644857e+00 -1.030293e+02
## [31] -3.631267e+01 -1.096190e+01 -2.159073e+01 -6.978736e+00 -2.442932e+01
## [36] 2.091778e+01 2.637600e+01 -1.851376e+01 4.734562e+01 1.677639e+01
## [41] 2.703088e+01 -1.742219e+01 2.044900e+01 1.406601e+01 -4.201843e+00
## [46] -1.726637e+01 1.105057e+02 3.147659e+01 -6.220297e+00 -2.601745e+01
## [51] 2.334387e+01 2.028255e+01 -3.043854e+00 -3.600336e+01 2.200800e+02
## [56] 1.444852e+01 5.758570e-01 3.471986e+01 -1.965445e+01 -4.405020e+00
## [61] -6.656313e+01 -8.997482e+01 -2.418156e+01 -1.793948e+01 -4.947097e+01
## [66] -1.144050e+02 8.345177e+01 2.463528e+01 -6.310246e+01 -4.849653e+01
## [71] 6.678126e+01 -1.649635e+00 2.022692e+01 5.695024e+00 -1.405638e+01
## [76] 1.142626e+02 6.848028e+00 1.010929e+00 -1.904447e-01 1.428798e+02
## [81] 1.374041e+02 1.700800e+02 2.351441e+01 -1.858121e+01 4.791643e+01
## [86] 8.681488e+01 1.719980e+01 6.226392e+01 -9.137637e+00 9.796364e+00
## [91] -9.139756e+01 5.106995e+00 1.783912e+01 1.756873e+01 3.778395e+01
## [96] -4.003507e+01 1.894607e+01 -7.128958e+01 -1.447888e+01 1.157212e+00
## [101] -1.366538e+01 -7.056027e+01 -1.439235e+02 -1.006829e+02 -6.764274e+00
## [106] 2.615148e+01 4.730949e+00 -9.377607e+01 -3.180652e+01 -6.728269e+01
## [111] -1.335428e+01 1.665279e-04 2.107454e+01 3.515091e+01 -5.766266e+01
## [116] 1.241467e+01 1.668775e+01 2.007445e+01 1.304813e+01 3.363875e+01
## [121] -1.066234e+01 8.965007e+00 5.805329e+01 1.584396e+01 1.467215e+01
## [126] -6.489263e+01
##
## $coefficients
## Value Std. Error Z score Pr(>|Z|)
## (Intercept) -776.5456684 1.050649e+03 -0.739110111 4.598401e-01
## Length1 -96.3043574 5.195241e+01 -1.853703330 6.378162e-02
## Length2 74.1614499 4.242227e+01 1.748172393 8.043418e-02
## Length3 0.2499556 3.798750e+01 0.006579944 9.947500e-01
## Height -261.3269143 3.597801e+01 -7.263518525 3.772538e-13
## Width 228.1238421 5.065257e+01 4.503697112 6.678137e-06
## area 7.5332289 1.215149e+00 6.199425999 5.666945e-10
## vol -0.2524026 8.976788e-02 -2.811725662 4.927651e-03
## rabo -789.7620029 1.052141e+03 -0.750623656 4.528792e-01
## h_l1 1390.8582409 4.132950e+02 3.365291629 7.646280e-04
## h_width 217.7527821 8.927638e+01 2.439086187 1.472446e-02
## l3_l2 1217.5409148 7.053538e+02 1.726142119 8.432185e-02
##
## $sigma
## [1] 60.29727
##
## $sigma.provided
## [1] FALSE
##
## $df
## [1] 11.50111 114.49889
##
## $cov.unscaled
## (Intercept) Length1 Length2 Length3
## (Intercept) 3.036130e+02 -7.9541584192 -3.5338011983 1.048964e+01
## Length1 -7.954158e+00 0.7423625695 -0.3671504845 -2.892366e-01
## Length2 -3.533801e+00 -0.3671504845 0.4949855941 -1.505849e-01
## Length3 1.048964e+01 -0.2892365877 -0.1505848768 3.969045e-01
## Height -2.966629e+00 0.2281592268 -0.0065685419 -1.467053e-01
## Width 2.271924e+00 -0.2978828933 0.0339244954 1.567019e-01
## area -1.386982e-02 -0.0041180129 0.0016547048 2.363719e-04
## vol 1.780994e-03 0.0003064647 -0.0001587548 1.471716e-05
## rabo -2.398484e+02 11.7633273454 -2.5809647631 -8.118428e+00
## h_l1 5.148414e+01 -0.4454150891 -0.9987644397 1.539211e+00
## h_width 4.156118e+00 -0.5258539785 0.1063160447 2.680771e-01
## l3_l2 -4.045808e+01 -4.5091730308 6.1011561119 -1.694599e+00
## Height Width area vol
## (Intercept) -2.9666287980 2.271923604 -1.386982e-02 1.780994e-03
## Length1 0.2281592268 -0.297882893 -4.118013e-03 3.064647e-04
## Length2 -0.0065685419 0.033924495 1.654705e-03 -1.587548e-04
## Length3 -0.1467052527 0.156701948 2.363719e-04 1.471716e-05
## Height 0.3560236387 -0.448311098 -1.066833e-02 7.436815e-04
## Width -0.4483110977 0.705679750 1.367008e-02 -1.007491e-03
## area -0.0106683344 0.013670080 4.061290e-04 -2.952016e-05
## vol 0.0007436815 -0.001007491 -2.952016e-05 2.216392e-06
## rabo 2.6040282801 -1.539272492 5.241925e-03 -6.287763e-04
## h_l1 -0.5494096628 -1.595353071 9.302399e-04 6.940567e-04
## h_width -0.5483596155 1.055813616 1.367089e-02 -1.025868e-03
## l3_l2 0.4142804892 -1.179041878 4.023724e-03 -7.625331e-04
## rabo h_l1 h_width l3_l2
## (Intercept) -2.398484e+02 5.148414e+01 4.156117750 -4.045808e+01
## Length1 1.176333e+01 -4.454151e-01 -0.525853978 -4.509173e+00
## Length2 -2.580965e+00 -9.987644e-01 0.106316045 6.101156e+00
## Length3 -8.118428e+00 1.539211e+00 0.268077074 -1.694599e+00
## Height 2.604028e+00 -5.494097e-01 -0.548359616 4.142805e-01
## Width -1.539272e+00 -1.595353e+00 1.055813616 -1.179042e+00
## area 5.241925e-03 9.302399e-04 0.013670891 4.023724e-03
## vol -6.287763e-04 6.940567e-04 -0.001025868 -7.625331e-04
## rabo 3.044757e+02 -5.600273e+01 -1.740370701 -9.021232e+01
## h_l1 -5.600273e+01 4.698129e+01 -5.708744434 1.222443e+01
## h_width -1.740371e+00 -5.708744e+00 2.192187929 -3.634312e+00
## l3_l2 -9.021232e+01 1.222443e+01 -3.634312136 1.368418e+02
##
## $correlation
## (Intercept) Length1 Length2 Length3 Height
## (Intercept) 1.00000000 -0.52981716 -0.28826084 0.95555900 -0.28534062
## Length1 -0.52981716 1.00000000 -0.60567520 -0.53284655 0.44380336
## Length2 -0.28826084 -0.60567520 1.00000000 -0.33973637 -0.01564708
## Length3 0.95555900 -0.53284655 -0.33973637 1.00000000 -0.39026824
## Height -0.28534062 0.44380336 -0.01564708 -0.39026824 1.00000000
## Width 0.15521358 -0.41156052 0.05740018 0.29609259 -0.89440917
## area -0.03949833 -0.23716339 0.11670575 0.01861748 -0.88720747
## vol 0.06865609 0.23891817 -0.15156796 0.01569126 0.83719048
## rabo -0.78886086 0.78243062 -0.21023716 -0.73850353 0.25010937
## h_l1 0.43107297 -0.07542137 -0.20711154 0.35644513 -0.13433661
## h_width 0.16109749 -0.41220973 0.10206190 0.28739403 -0.62070773
## l3_l2 -0.19848869 -0.44738305 0.74132137 -0.22994008 0.05935342
## Width area vol rabo h_l1
## (Intercept) 0.15521358 -0.039498333 0.06865609 -0.78886086 0.431072974
## Length1 -0.41156052 -0.237163393 0.23891817 0.78243062 -0.075421368
## Length2 0.05740018 0.116705749 -0.15156796 -0.21023716 -0.207111543
## Length3 0.29609259 0.018617479 0.01569126 -0.73850353 0.356445133
## Height -0.89440917 -0.887207475 0.83719048 0.25010937 -0.134336611
## Width 1.00000000 0.807486409 -0.80558965 -0.10501114 -0.277070633
## area 0.80748641 1.000000000 -0.98392822 0.01490673 0.006734424
## vol -0.80558965 -0.983928221 1.00000000 -0.02420452 0.068015702
## rabo -0.10501114 0.014906734 -0.02420452 1.00000000 -0.468242007
## h_l1 -0.27707063 0.006734424 0.06801570 -0.46824201 1.000000000
## h_width 0.84887656 0.458169239 -0.46540320 -0.06736380 -0.562521624
## l3_l2 -0.11998199 0.017068165 -0.04378507 -0.44195717 0.152460257
## h_width l3_l2
## (Intercept) 0.1610975 -0.19848869
## Length1 -0.4122097 -0.44738305
## Length2 0.1020619 0.74132137
## Length3 0.2873940 -0.22994008
## Height -0.6207077 0.05935342
## Width 0.8488766 -0.11998199
## area 0.4581692 0.01706817
## vol -0.4654032 -0.04378507
## rabo -0.0673638 -0.44195717
## h_l1 -0.5625216 0.15246026
## h_width 1.0000000 -0.20983310
## l3_l2 -0.2098331 1.00000000
##
## attr(,"class")
## [1] "summary.l1ce"
prediction2 <- predict(fit_lasso, aplicacao) # salvando predições no objeto prediction2
df2 <- cbind(aplicacao, prediction = prediction2)# fazendo uma junção das predições com a base de dados para aplicação do modelo
rmse(aplicacao$Weight, predict(fit_lasso, aplicacao)) # ROOT MEAN SQUARE DEVIATION
## [1] 53.03882
mae(aplicacao$Weight, predict(fit_lasso, aplicacao)) # MEAN ABSOLUT PERCENT ERROR
## [1] 33.94291
ggplot(df2) + geom_point(aes(x = Weight, y = prediction, color = Species)) +
geom_line(aes(x = Weight, y = Weight)) + scale_color_brewer(palette = "Dark2") + theme(legend.position = "bottom") # gráico com valores verdadeiros no eixo x, valores preditos na variável resposta e também uma reta verdade
Random Forest é um algoritmo que irá criar muitas árvores de decisão, de maneira aleatória, formando o que podemos enxergar como uma floresta, onde cada árvore será utilizada na escolha do resultado final. As Árvores de Decisão, ou Decision Trees, estabelecem regras para tomada de decisão. O algoritmo criará uma estrutura similar a um fluxograma, com “nós” onde uma condição é verificada, e se atendida o fluxo segue por um ramo, caso contrário, por outro, sempre levando ao próximo “nó”, até a finalização da árvore. Com os dados de treino, o algoritmo busca as melhores condições, e onde inserir cada uma dentro do fluxo.
fit_rf <-
randomForest(
Weight ~ Species+Length1+Length2+Length3+Height+Width+area+vol+ rabo+h_l1+h_width+l3_l2,
data = treino,
importance = TRUE
) # Random Forest
summary(fit_rf) # informações geradas pela aplicação do método
## Length Class Mode
## call 4 -none- call
## type 1 -none- character
## predicted 126 -none- numeric
## mse 500 -none- numeric
## rsq 500 -none- numeric
## oob.times 126 -none- numeric
## importance 24 -none- numeric
## importanceSD 12 -none- numeric
## localImportance 0 -none- NULL
## proximity 0 -none- NULL
## ntree 1 -none- numeric
## mtry 1 -none- numeric
## forest 11 -none- list
## coefs 0 -none- NULL
## y 126 -none- numeric
## test 0 -none- NULL
## inbag 0 -none- NULL
## terms 3 terms call
prediction3 <-
predict(fit_rf, aplicacao) # salvando predições no objeto prediction3
df3 <-
cbind(aplicacao, prediction = prediction3)# fazendo uma junção das predições com a base de dados para aplicação do modelo
rmse(aplicacao$Weight, predict(fit_rf, aplicacao)) # ROOT MEAN SQUARE DEVIATION
## [1] 25.83664
mae(aplicacao$Weight, predict(fit_rf, aplicacao)) # MEAN ABSOLUT PERCENT ERROR
## [1] 13.02426
ggplot(df3) + geom_point(aes(x = Weight, y = prediction, color = Species)) +
geom_line(aes(x = Weight, y = Weight)) + scale_color_brewer(palette = "Dark2") + theme(legend.position = "bottom")# gráico com valores verdadeiros no eixo x, valores preditos na variável resposta e também uma reta verdade
Durante o desenvolvimento de Random Forest, cada árvore usa apenas um subconjunto das variáveis de entrada. Se em uma árvore subsequente, a exclusão de recursos usados anteriormente resulta em uma classificação inferior, esses recursos, por sua vez, teriam um aumento % maior no MSE(Mean Square Error). Portanto, logicamente, as variáveis de entrada que geram %IncMSE maior quando excluídas têm uma importância de recurso maior.
importance(fit_rf, type = 1)
## %IncMSE
## Species 2.448690
## Length1 12.424589
## Length2 13.127369
## Length3 14.059062
## Height 8.546022
## Width 14.207847
## area 14.767174
## vol 17.457193
## rabo 1.865045
## h_l1 5.846283
## h_width 4.491742
## l3_l2 2.596086
importance <- data.frame(importance(fit_rf, type = 1))[, 1]
names <-c("Species",
"Length1",
"Length2",
"Length3",
"Height",
"Width",
"area",
"vol",
"rabo",
"h_l1",
"h_width",
"l3_l2")
feature_importance <- data.frame(variable = names, IncMSE = importance)
ggplot(feature_importance) + geom_col(aes(
x = reorder(variable, IncMSE),
y = IncMSE/sum(IncMSE)
), show.legend = F, fill = "#1B9E77", color = "grey") + coord_flip() + labs(y = "%IncMSE", x = "Variável") + theme(aspect.ratio = .7)
Como vimos anteriormente, o algorítimo Random Forest foi o método que teve o melhor desempenho para predição da variável Weight. Além disso, dado que por Random Forest montamos árvores de decisão, pode ser que ele sirva muito bem para predizer variáveis categóricas, como é o caso da variável Species. Veremos a seguir a predição com este método e analisaremos como ele desempenha.
treino$Species <- as.factor(treino$Species)
aplicacao$Species <- as.factor(aplicacao$Species)
fit_rf <- randomForest(Species ~ .,
data = treino,
importance = TRUE
) # Random Forest
pred <- predict(fit_rf, newdata=aplicacao[-1])
cm <- table(aplicacao[,1], pred)
cm
## pred
## Bream Parkki Perch Pike Roach Smelt Whitefish
## Bream 7 0 0 0 0 0 0
## Parkki 0 1 0 0 0 0 0
## Perch 0 0 15 0 0 0 0
## Pike 0 0 0 2 0 0 0
## Roach 0 0 0 0 4 0 0
## Smelt 0 0 0 0 0 3 0
Como este é um problema de classificação, usamos uma matriz de confusão para avaliar o desempenho de nosso modelo. Lembrando que os valores na diagonal correspondem a verdadeiros positivos e verdadeiros negativos (previsões corretas), enquanto os outros correspondem a falsos positivos e falsos negativos. Sabendo disso, podemos concluir que o resultado é bastante satisfatório e por isso não imagino ser necessário a aplicação de qualquer outro método para esse problema. Para compreendermos melhor, abaixo iremos analisar as variáveis de maior importância na predição da variável Species.
importance(fit_rf, type = 1)
## MeanDecreaseAccuracy
## Weight 11.46595
## Length1 12.67321
## Length2 11.79294
## Length3 11.45048
## Height 17.77870
## Width 11.90339
## area 12.80231
## vol 11.25257
## rabo 20.98471
## i_massa 13.69355
## h_l1 27.54277
## h_width 15.03239
## l3_l2 28.60484
importance <- data.frame(importance(fit_rf, type = 1))[, 1]
names <-c("Weight",
"Length1",
"Length2",
"Length3",
"Height",
"Width",
"area",
"vol",
"rabo",
"i_massa",
"h_l1",
"h_width",
"l3_l2")
feature_importance <- data.frame(variable = names, IncMSE = importance)
ggplot(feature_importance) + geom_col(aes(
x = reorder(variable, IncMSE),
y = IncMSE/sum(IncMSE)
), show.legend = F, fill = "#1B9E77", color = "grey") + coord_flip() + labs(y = "%IncMSE", x = "Variável") + theme(aspect.ratio = .7)
Podemos ver que agora as variáveis criadas que dizem respeito a aspectos físicos do peixe tiveram grande destaque. Vamos gerar alguns gráficos que relacionam as 3 primeiras mais importantes variáveis para a predição.
ggplot(dados) + geom_point(aes(x = l3_l2, y=h_l1, color = Species)) + scale_color_brewer(palette = "Dark2")+ theme(legend.position = "bottom")
ggplot(dados) + geom_point(aes(x = l3_l2, y=rabo, color = Species)) + scale_color_brewer(palette = "Dark2")+ theme(legend.position = "bottom")
ggplot(dados) + geom_point(aes(x = h_l1, y=rabo, color = Species)) + scale_color_brewer(palette = "Dark2") + theme(legend.position = "bottom")
Portanto, podemos ver que elas nos permitem separar as espécies de maneira bastante interessante, algumas espécies podem ser mais bem definidas relacionando duas dessas variáveis a outras e assim é construída a resposta sobre qual espécie se encaixa melhor para peixes com determinadas caracteríticas.