- introdução: o que é o Keras
- classificação dos dígitos do MNIST com redes totalmente conectadas
- classificação dos dígitos do MNIST com redes convolucionais
- regressão: redshifts fotométricos para o S-PLUS com redes totalmente conectadas
referência básica: Deep Learning with R, F. Chollet & J.J. Allaire
https://www.manning.com/books/deep-learning-with-r-second-edition
https://www.manning.com/books/deep-learning-with-python-second-edition
O Keras (https://keras.rstudio.com) é uma excelente plataforma para aplicações em deep learning (DL), já que permite definir e treinar quase qualquer tipo de modelo de DL. Ele provê interface para várias implementações de DL, como TensorFlow, Theano e CNTK.
Vamos ilustrar o Keras com um problema “clássico” de classificação de imagens: a classificação dos dígitos do MNIST
O MNIST é uma base de dados contendo imagens digitalizadas (28x28 pixels cada uma) dos dígitos 0 a 9, com 256 níveis de cinza (a intensidade de cada pixel é um inteiro entre 0 e 255).
Nosso problema é: dada uma imagem, determine a probabilidade \(p_i\) dela ser do dígito \(i\) (0,….,9)
A base de dados do MNIST vem com o Keras. Vamos carregar os dados do e definir os conjuntos de treinamento e teste:
#tempo de processamento do script
t00 = Sys.time()
# reprodutibilidade
set.seed(1234)
# paralelização
library(doParallel)
## Loading required package: foreach
## Loading required package: iterators
## Loading required package: parallel
cl <- makePSOCKcluster(5)
registerDoParallel(cl)
# bibliotecas
library(keras3)
library(ggplot2)
# dados
mnist <- dataset_mnist()
train_images <- mnist$train$x
train_labels <- mnist$train$y
test_images <- mnist$test$x
test_labels <- mnist$test$y
# Algo sobre os dados:
dim(train_images)
## [1] 60000 28 28
length(train_labels)
## [1] 60000
dim(test_images)
## [1] 10000 28 28
length(test_labels)
## [1] 10000
# os pixels das imagens tem valores entre 0 e 255
summary(train_images[,14,14])
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.00 0.00 29.00 96.97 232.00 255.00
# os targets são dígitos de 0 a 9
# exemplo:
test_labels[1:10]
## [1] 7 2 1 0 4 1 4 9 5 9
Para visualizar as 4 primeiras imagens do conjunto de treinamento:
# visualização dos dígitos
par(mfcol=c(2,2))
# By default the ranges of xlim and ylim are enlarged by 6%, so that the specified values do not lie at the very edges of the plot region. This is appropriate for most types of plot, but sometimes we want the specified limits to lie at the edges of the plot window. This can be specified separately for each axis using the arguments xaxs="i" and yaxs="i"
par(mar=c(0, 0, 3, 0), xaxs='i', yaxs='i')
for (idx in 1:4) {
im <- train_images[idx,,]
im <- t(apply(im, 2, rev)) #rev provides a reversed version of its argument
image(1:28, 1:28, im, col=gray((0:255)/255),
xaxt='n', main=paste(train_labels[idx]))
}
—
Vamos definir a arquitetura da rede: camadas, conexões e funções de ativação.
Vamos considerar uma rede densamente conectada com uma camada de entrada com 28x28=784 neurônios (parâmetro ‘input shape’), 512 numa camada oculta e 10 na camada de saída (uma saida para cada dígito): 784:512:10
A camada de saída vai dar a probabilidade de cada dígito, dado o input. Para isso, em problemas com muitas classes, usa-se a função softmax como função de ativação na saída: \[p_i = {e^{-y_i} \over \sum_k e^{-y_k}}\]
A definição de um modelo no Keras tem duas partes:
1.) as camadas e as funções de ativação- vamos considerar funções de ativação tipo ReLU na camada oculta e softmax na de saída:
# o "multilayer perceptron" (MLP) é um exemplo de rede densamente conectada
# MLP com uma camada oculta com 512 unidades ReLU
modelo <- keras_model_sequential() %>%
layer_dense(units = 512, activation = "relu", input_shape = c(28 * 28)) %>%
layer_dense(units = 10, activation = "softmax")
# ativação 'softmax' na saída: apropriada para classificação multi-classe
# se quiser incluir uma nova camada oculta densamente conectada com, por exemplo, 64 unidades e ativação tanh, inclua o seguinte comando entre a camada de entrada e a de saída:
# layer_dense(units = 64, activation = "tanh") %>%
2.) e os parâmetros de treinamento- otimização, função de custo e métrica de desempenho, adequados para um problema de classificação multi-classe:
lembrando
acurácia: fração de detecções corretas \[\frac{TP+TN}{TP+TN+FP+FN}\]
em problemas de classificação é comum usar-se como função de perda a entropia cruzada categórica: \[\begin{align} \mathcal{L}({\mathbf w}) &= -\frac{1}{n}\sum_{i=1}^n\sum_{j=1}^m y_{ij}\log(t_{ij}) \\ &= -\frac{1}{n}\sum_{i=1}^n \left[y_i \log(t_i) + (1-y_i) \log(1-t_i)\right] \end{align}\] onde \(y_i\) é a previsão, \(t_i\) o target (0 para todas as saídas, exceto para a saída correta, que é 1) e \({\mathbf w}\) são os parâmetros da rede
modelo %>% compile(
optimizer = "rmsprop", # variante turbinada da descida do gradiente
loss = "categorical_crossentropy", # classificação multi-classe
metrics = c("accuracy") # classificação
)
# um resumo do modelo:
summary(modelo)
## Model: "sequential"
## ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
## ┃ Layer (type) ┃ Output Shape ┃ Param # ┃
## ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
## │ dense (Dense) │ (None, 512) │ 401,920 │
## ├───────────────────────────────────┼──────────────────────────┼───────────────┤
## │ dense_1 (Dense) │ (None, 10) │ 5,130 │
## └───────────────────────────────────┴──────────────────────────┴───────────────┘
## Total params: 407,050 (1.55 MB)
## Trainable params: 407,050 (1.55 MB)
## Non-trainable params: 0 (0.00 B)
Vamos fazer um pré-processamento dos dados:
- transformando a imagem em um vetor
- colocando os valores dos pixels entre 0 e 1
# pré-processamento do conjunto de treino
dim(train_images)
## [1] 60000 28 28
# muda o formato do arquivo train_images para o keras entender
train_images <- array_reshape(train_images, c(60000, 28 * 28))
dim(train_images)
## [1] 60000 784
# agora cada imagem é representada por um vetor com 784 valores de pixels
# divide-se os valores dos pixels por 255 para ficarem entre 0 e 1
range(train_images)
## [1] 0 255
train_images <- train_images / 255
# pré-processamento do conjunto de teste
test_images <- array_reshape(test_images, c(10000, 28 * 28))
test_images <- test_images / 255
Este é um problema de classificação: as classes são variáveis categóricas
train_labels <- to_categorical(train_labels)
test_labels <- to_categorical(test_labels)
# as classes são 'hot-coded': todas 0, exceto uma (o target) que é 1:
head(train_labels)
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
## [1,] 0 0 0 0 0 1 0 0 0 0
## [2,] 1 0 0 0 0 0 0 0 0 0
## [3,] 0 0 0 0 1 0 0 0 0 0
## [4,] 0 1 0 0 0 0 0 0 0 0
## [5,] 0 0 0 0 0 0 0 0 0 1
## [6,] 0 0 1 0 0 0 0 0 0 0
treinamento com 10 épocas:
épocas: número de vezes que a rede vê todo o conjunto de treunamento
batch-size: número de amostras que são propagadas por back-propagation antes que os pesos sejam atualizados
t0 = Sys.time()
historia <- modelo %>% fit(train_images, train_labels, epochs = 10, batch_size = 128,verbose=0,validation_data = list(test_images,test_labels))
plot(historia)
Sys.time()-t0
## Time difference of 33.17701 secs
note o baixo tempo de processamento: o Keras é muito eficiente!
desempenho do classificador no conjunto de teste:
metrics <- modelo %>% evaluate(test_images, test_labels, verbose = 0)
metrics
## $accuracy
## [1] 0.9809
##
## $loss
## [1] 0.06428362
esta rede tem um ótimo desempenho: a acurácia é de 98% no conjunto de teste
As CNNs revolucionaram a análise de imagens e de certo modo viraram o padrão para este tipo de análise. Mas note que o algoritmo pode ser usado com muitos outros tipos de dados, desde que tenham um formato adequado.
O “coração” de uma CNN são as pilhas de camadas de convolução e pooling, layer_conv_2d() e layer_max_pooling_2d(), com uma ou duas camadas densamente conectadas na saída.
Uma camada de convolução passa um filtro de largura kernel_size sobre uma imagem ou feature map e transfere este sinal para um número grande de “filtros”, usando uma certa função de ativação, gerando um novo feature map.
A camada de max_pooling tem o papel de reduzir o tamanho dos mapas de filtros gerados pela camada de convolução.
Vamos ilustrar uma CNN com o problema da classificação dos dígitos do MNIST.
Uma imagem pode ser descrita como um tensor de forma (altura, largura, número de canais). As imagens do MNIST são (28,28,1).
# reprodutibilidade
set.seed(123)
# Vamos construir o modelo em duas etapas: a convolucional e depois a densamente conectada.
# parte convolucional do modelo
model <- keras_model_sequential() %>%
layer_conv_2d(filters = 32, kernel_size = c(3, 3), activation = "relu",
input_shape = c(28, 28, 1)) %>%
layer_max_pooling_2d(pool_size = c(2, 2)) %>%
layer_conv_2d(filters = 64, kernel_size = c(3, 3), activation = "relu") %>%
layer_max_pooling_2d(pool_size = c(2, 2)) %>%
layer_conv_2d(filters = 64, kernel_size = c(3, 3), activation = "relu")
# resumo do modelo:
summary(model)
## Model: "sequential_1"
## ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
## ┃ Layer (type) ┃ Output Shape ┃ Param # ┃
## ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
## │ conv2d (Conv2D) │ (None, 26, 26, 32) │ 320 │
## ├───────────────────────────────────┼──────────────────────────┼───────────────┤
## │ max_pooling2d (MaxPooling2D) │ (None, 13, 13, 32) │ 0 │
## ├───────────────────────────────────┼──────────────────────────┼───────────────┤
## │ conv2d_1 (Conv2D) │ (None, 11, 11, 64) │ 18,496 │
## ├───────────────────────────────────┼──────────────────────────┼───────────────┤
## │ max_pooling2d_1 (MaxPooling2D) │ (None, 5, 5, 64) │ 0 │
## ├───────────────────────────────────┼──────────────────────────┼───────────────┤
## │ conv2d_2 (Conv2D) │ (None, 3, 3, 64) │ 36,928 │
## └───────────────────────────────────┴──────────────────────────┴───────────────┘
## Total params: 55,744 (217.75 KB)
## Trainable params: 55,744 (217.75 KB)
## Non-trainable params: 0 (0.00 B)
# notem a estrutura de funil
A saida de cada camada layer_conv_2d() e layer_max_pooling_2d() é um tensor tri-dimensional de forma (altura,largura,canais). A largura e a altura tendem a diminuir com a profundidade na rede.
O número de canais é controlado pelo primeiro argumento do layer_conv_2d() (32 ou 64)
A próxima etapa é conectar a saída desse modelo, um tensor de forma (3,3,64) a uma rede densamente conectada para classificação.
A entrada dessas redes são vetores, de modo que é necessário transformar o tensor 3D em um vetor 1D; o nome dessa operação no Keras é “flatten¨.
Vamos considerar uma rede densa de apenas uma camada:
model <- model %>%
# flatten
layer_flatten() %>%
# camada densamente conectada
layer_dense(units = 64, activation = "relu") %>%
# saída - classificação
layer_dense(units = 10, activation = "softmax")
# resumo do modelo:
summary(model)
## Model: "sequential_1"
## ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
## ┃ Layer (type) ┃ Output Shape ┃ Param # ┃
## ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
## │ conv2d (Conv2D) │ (None, 26, 26, 32) │ 320 │
## ├───────────────────────────────────┼──────────────────────────┼───────────────┤
## │ max_pooling2d (MaxPooling2D) │ (None, 13, 13, 32) │ 0 │
## ├───────────────────────────────────┼──────────────────────────┼───────────────┤
## │ conv2d_1 (Conv2D) │ (None, 11, 11, 64) │ 18,496 │
## ├───────────────────────────────────┼──────────────────────────┼───────────────┤
## │ max_pooling2d_1 (MaxPooling2D) │ (None, 5, 5, 64) │ 0 │
## ├───────────────────────────────────┼──────────────────────────┼───────────────┤
## │ conv2d_2 (Conv2D) │ (None, 3, 3, 64) │ 36,928 │
## ├───────────────────────────────────┼──────────────────────────┼───────────────┤
## │ flatten (Flatten) │ (None, 576) │ 0 │
## ├───────────────────────────────────┼──────────────────────────┼───────────────┤
## │ dense_2 (Dense) │ (None, 64) │ 36,928 │
## ├───────────────────────────────────┼──────────────────────────┼───────────────┤
## │ dense_3 (Dense) │ (None, 10) │ 650 │
## └───────────────────────────────────┴──────────────────────────┴───────────────┘
## Total params: 93,322 (364.54 KB)
## Trainable params: 93,322 (364.54 KB)
## Non-trainable params: 0 (0.00 B)
# o tensor (3, 3, 64) é "achatado" em um vetor de dimensão 3*3*64 = 576 antes de passar pelas camadas densas.
Vamos carregar os dados do MNIST, na forma de conjuntos de treino e teste e num formato adequado para este tipo de rede:
# para monitorar o tempo de processamento deste módulo
t0 = Sys.time()
mnist <- dataset_mnist()
c(c(train_images, train_labels), c(test_images, test_labels)) %<-% mnist
dim(train_images)
## [1] 60000 28 28
summary(train_images[,14,14])
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.00 0.00 29.00 96.97 232.00 255.00
# vamos transformar o tensor num vetor
train_images <- array_reshape(train_images, c(60000, 28, 28, 1))
# vamos colocar os valores dos pixels entre 0 e 1:
train_images <- train_images / 255
test_images <- array_reshape(test_images, c(10000, 28, 28, 1))
test_images <- test_images / 255
# em classificação os labels são variáveis categóricas:
train_labels <- to_categorical(train_labels)
test_labels <- to_categorical(test_labels)
# hiper-parâmetros do modelo
model %>% compile(
optimizer = "rmsprop",
loss = "categorical_crossentropy",
metrics = c("accuracy")
)
# ajuste
model %>% fit(
train_images, train_labels,
epochs = 5, batch_size=64,
verbose=0
)
# avaliação dos resultados no conjunto de teste
results <- model %>% evaluate(test_images, test_labels)
## 313/313 - 1s - 4ms/step - accuracy: 0.9901 - loss: 0.0336
results
## $accuracy
## [1] 0.9901
##
## $loss
## [1] 0.03356369
Sys.time() - t0
## Time difference of 1.557481 mins
compare a acurácia do conjunto de teste com o valor obtido com a rede densa anterior.
Vamos usar o mesmo conjunto de dados da aula anterior. Vamos carregar a biblioteca caret para usar suas rotinas de partição dos dados em treinamento e teste.
# reprodutibilidade
set.seed(42)
library(caret)
## Loading required package: lattice
dados = as.data.frame(read.table('splus-mag-z.dat', sep = "", header=TRUE))
# vamos examinar os dados:
dim(dados)
## [1] 55803 13
# cada linha
head(dados)
## uJAVA_petro F378_petro F395_petro F410_petro F430_petro g_petro F515_petro
## 1 18.71 18.69 18.50 18.12 17.78 17.43 17.09
## 2 18.26 18.12 18.28 17.32 16.95 16.67 16.24
## 3 19.38 19.45 18.76 18.60 18.50 18.07 17.69
## 4 20.30 19.73 20.01 19.18 18.91 18.36 18.00
## 5 19.49 18.98 18.64 18.64 18.02 17.14 16.61
## 6 19.86 19.38 18.93 18.75 18.15 17.44 16.94
## r_petro F660_petro i_petro F861_petro z_petro z_SDSS
## 1 16.89 16.83 16.56 16.54 16.45 0.111
## 2 15.97 15.90 15.61 15.52 15.41 0.082
## 3 17.55 17.47 17.25 17.31 17.18 0.086
## 4 17.75 17.68 17.51 17.46 17.34 0.111
## 5 16.06 15.93 15.65 15.54 15.38 0.162
## 6 16.58 16.48 16.24 16.11 16.00 0.082
# sumário dos dados
library(skimr)
sumario <- skim(dados)
sumario
Name | dados |
Number of rows | 55803 |
Number of columns | 13 |
_______________________ | |
Column type frequency: | |
numeric | 13 |
________________________ | |
Group variables | None |
Variable type: numeric
skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 | hist |
---|---|---|---|---|---|---|---|---|---|---|
uJAVA_petro | 0 | 1 | 20.03 | 1.35 | 9.86 | 19.32 | 20.04 | 20.76 | 31.02 | ▁▁▇▁▁ |
F378_petro | 0 | 1 | 19.78 | 1.32 | 9.53 | 19.10 | 19.80 | 20.50 | 28.69 | ▁▁▇▁▁ |
F395_petro | 0 | 1 | 19.62 | 1.37 | 9.43 | 18.91 | 19.64 | 20.37 | 29.16 | ▁▁▇▁▁ |
F410_petro | 0 | 1 | 19.43 | 1.36 | 8.12 | 18.74 | 19.47 | 20.19 | 28.80 | ▁▁▇▂▁ |
F430_petro | 0 | 1 | 19.18 | 1.36 | 8.14 | 18.49 | 19.24 | 19.97 | 29.13 | ▁▁▇▁▁ |
g_petro | 0 | 1 | 18.65 | 1.25 | 7.01 | 18.00 | 18.72 | 19.45 | 25.07 | ▁▁▂▇▁ |
F515_petro | 0 | 1 | 18.36 | 1.26 | 7.02 | 17.70 | 18.42 | 19.17 | 25.06 | ▁▁▃▇▁ |
r_petro | 0 | 1 | 17.90 | 1.20 | 6.39 | 17.26 | 17.99 | 18.76 | 21.04 | ▁▁▁▇▇ |
F660_petro | 0 | 1 | 17.78 | 1.20 | 6.18 | 17.12 | 17.87 | 18.65 | 21.11 | ▁▁▁▇▆ |
i_petro | 0 | 1 | 17.56 | 1.20 | 6.23 | 16.89 | 17.66 | 18.43 | 21.18 | ▁▁▁▇▅ |
F861_petro | 0 | 1 | 17.40 | 1.23 | 5.58 | 16.71 | 17.50 | 18.29 | 22.57 | ▁▁▁▇▁ |
z_petro | 0 | 1 | 17.36 | 1.23 | 6.05 | 16.66 | 17.46 | 18.26 | 21.60 | ▁▁▁▇▂ |
z_SDSS | 0 | 1 | 0.15 | 0.10 | 0.00 | 0.08 | 0.13 | 0.19 | 1.12 | ▇▂▁▁▁ |
# para o tempo de processamento não ficar muito grande, vamos considerar uma amostra com 10000 galáxias
ngal = 10000
dados = dados[1:ngal,]
z_SDSS = dados[,13]
# número das linhas dos objetos selecionados para o conjunto de treinamento
numlinhastreinamento = createDataPartition(z_SDSS, p=0.75, list=FALSE)
# conjunto de treinamento:
treinamento = dados[numlinhastreinamento,]
# conjunto de teste
teste = dados[-numlinhastreinamento,]
train_data = treinamento[,1:12]
train_targets = treinamento[,13]
test_data = teste[,1:12]
test_targets = teste[,13]
pré-processamento dos dados:
vamos padronizar os dados de entrada, as magnitudes (subtração da média e divisão pelo desvio padrão):
mean <- apply(train_data, 2, mean)
std <- apply(train_data, 2, sd)
train_data <- scale(train_data, center = mean, scale = std)
test_data <- scale(test_data, center = mean, scale = std)
arquitetura da rede- três camadas densas (com função de ativação ReLU) e uma unidade de saída linear (apropriada para regressão):
# Como vamos usar o mesmo modelo mais de uma vez, vamos usar uma função para construí-lo:
build_model <- function() {
model <- keras_model_sequential() %>%
layer_dense(units = 64, activation = "relu",
input_shape = dim(train_data)[[2]]) %>%
layer_dense(units = 32, activation = "relu") %>%
layer_dense(units = 8, activation = "relu") %>%
layer_dense(units = 1) #no activation = linear layer
model %>% compile(
optimizer = "rmsprop",
loss = "mse", #Mean Squared Error
metrics = c("mae") #Mean Absolute Error
)
}
Vamos treinar inicialmente o modelo com 500 épocas:
t0 = Sys.time()
model <- build_model()
historia <- model %>% fit(train_data, train_targets,
epochs = 500, batch_size = 16, verbose = 0,validation_data = list(test_data,test_targets))
summary(model)
## Model: "sequential_2"
## ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
## ┃ Layer (type) ┃ Output Shape ┃ Param # ┃
## ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
## │ dense_4 (Dense) │ (None, 64) │ 832 │
## ├───────────────────────────────────┼──────────────────────────┼───────────────┤
## │ dense_5 (Dense) │ (None, 32) │ 2,080 │
## ├───────────────────────────────────┼──────────────────────────┼───────────────┤
## │ dense_6 (Dense) │ (None, 8) │ 264 │
## ├───────────────────────────────────┼──────────────────────────┼───────────────┤
## │ dense_7 (Dense) │ (None, 1) │ 9 │
## └───────────────────────────────────┴──────────────────────────┴───────────────┘
## Total params: 6,372 (24.89 KB)
## Trainable params: 3,185 (12.44 KB)
## Non-trainable params: 0 (0.00 B)
## Optimizer params: 3,187 (12.45 KB)
plot(historia)
Sys.time()-t0
## Time difference of 7.911358 mins
Com 500 épocas temos um claro overfitting
Vamos treinar o modelo com 100 épocas e verificar sua convergência e se houve overfitting:
historia <- model %>% fit(train_data, train_targets, epochs = 100, batch_size = 128,verbose=0,validation_data = list(test_data,test_targets))
plot(historia)
results <- model %>% evaluate(test_data, test_targets, verbose = 0)
results
## $loss
## [1] 0.003876167
##
## $mae
## [1] 0.04020451
# predições
z_pred = model %>% predict(test_data)
## 79/79 - 0s - 2ms/step
z_pred = z_pred[,1]
# estatística da performance do algoritmo
# sigma equivalente da gaussiana
relz = (z_pred-test_targets)
sig_G = 0.7413*(quantile(relz,0.75,names = FALSE) - quantile(relz,0.25,names = FALSE))
sig_G
## [1] 0.03742269
# na aula anterior obtivemos 0.035 e 0.040 com rf e knn, respectivamente
# mas note que o desempenho do deep learning aumenta com o número de dados
#visualização do resultado
my_data = as.data.frame(cbind(predicted = z_pred,
observed = test_targets))
# Plot predictions vs test data
ggplot(my_data,aes(predicted, observed)) +
geom_point(color = "darkred", alpha = 0.5) +
geom_smooth(method=lm)+ ggtitle('GLM ') +
ggtitle("DL: prediction vs test data") +
xlab("prediction ") +
ylab("observed data") +
theme(plot.title = element_text(color="darkgreen",size=18,hjust = 0.5),
axis.text.y = element_text(size=12),
axis.text.x = element_text(size=12,hjust=.5),
axis.title.x = element_text(size=14),
axis.title.y = element_text(size=14))
## `geom_smooth()` using formula = 'y ~ x'
Sys.time()-t0
## Time difference of 8.24253 mins
tempo de processamento do script:
Sys.time()-t00
## Time difference of 10.53639 mins
Examine como a escolha da arquitetura do modelo afeta a acurácia do conjunto de teste no caso da classificação dos dígitos do MNIST. Considere o exemplo de nossa rede densamente conectada. No exemplo, ela tem 512 neurônios em uma camada oculta.
- inicialize a semente aleatória com seu número USP
- varie o número de neurônios em cada camada: use 32 e 64
- varie o número de camadas ocultas (com 64 neurônios em cada uma): use de 1 a 3
- varie a ativação no modelo com uma camada com 512 neurônios: compare ReLU com tanh
É bom variar um pouco o número de épocas para encontrar um valor que evita um grande overfitting ou underfitting (não precisa otimizar)
Escreva uma avaliação sobre o desempenho da acurácia do modelo em função desses parâmetros.