Se centrará la atención en la algorítmica de aprendizaje conocida como redes neuronales. Las redes neutrales son una idea bastante antigua, que hoy en día, se encuentran a la vanguardia para muchos problemas diferentes de aprendizaje automático. La discusión de las redes neuronales, sobre la regresión lineal y la regresión logística, viene impulsada para aprender hipótesis complejas no lineales puesto que incluir todas las características polinomiales de las regresiones puede sobreajustar al conjunto de entrenamiento, y también puede llegar a ser computacionalmente costoso. Se desarrollará esta metodología enmarcada en la fluidez de la tidysuite (Wickham et al. 2019; Kuhn and Wickham 2020).
Las redes neuronales son un algoritmo bastante antiguo que originalmente fue motivado por el objetivo de tener máquinas que puedan imitar el cerebro. Esta es sólo una hipótesis, pero se cuenta con algunas evidencias que respaldan esto.
Esta parte del cerebro (Figura 1), la parte marcada en verde, es la corteza auditiva y la forma en que se procesan sonidos es que el oído recibe esta señal y la enruta a la corteza auditiva y eso es lo que permite entender dicha señal. La neurociencia ha realizado diversos experimentos fascinantes en los que se corta el cable desde las orejas hasta la corteza auditiva y se vuelve a cablear, en este caso el cerebro de un animal, para que la señal de los ojos al nervio óptico finalmente se dirija a la corteza auditiva.
Figure 1: Auditory cortex learns to see
Al hacer esto, resulta que la corteza auditiva aprenderá a ver. Como otro ejemplo (Figura 2), se tiene al trozo azul de tejido cerebral, la corteza somatosensorial, encargada de procesar el sentido del tacto.
Figure 2: Somatosensory cortex learns to see
Al realiza un proceso de recableado similar, la corteza somatosensorial aprenderá a ver. Debido a este y otros experimentos similares, los llamados experimentos de cableado neurológico, hay esta sensación de que si la misma pieza de tejido cerebral físico puede procesar la vista o sonido o tacto, entonces tal vez haya un algoritmo de aprendizaje que pueda procesar la vista, el sonido o el tacto. Y en lugar de tener que implementar mil programas diferentes o mil algoritmos diferentes para hacer las cosas que hace el cerebro, tal vez lo necesario es descubrir alguna aproximación o lo que sea que haga el algoritmo de aprendizaje del cerebro e implementarlo. En cierta medida, parece posible conectar casi cualquier sensor a casi cualquier parte del cerebro y así, dentro de esta lógica, aprender a manejar este tipo de datos.
Se cuenta con otros ejemplos en la Figura 3.
Figure 3: Neural learning representations
En la parte superior izquierda hay un ejemplo de cómo aprender a ver con la lengua. La forma en que funciona es a trvés de un sistema llamado BrainPort que está siendo sometido a pruebas por la FDA, pero la forma en que funciona es que se coloca una cámara en escala de grises en la frente, mirando hacia la imagen en escala de grises de baja resolución de lo que está frente a una persona y luego se pasa un cable a una serie de electrodos que se colocan en la lengua para que cada píxel se asigne a una ubicación en la lengua donde tal vez un alto voltaje corresponde a un píxel oscuro y un voltaje bajo corresponde a un píxel brillante.
En la parte superior derecha hay un segundo ejemplo de eco-ubicación humana por sonar. Hay dos formas de hacer esto. Se pueden chasquear los dedos o hacer clic con la lengua. Hay personas ciegas que están siendo capacitadas en las escuelas para hacer esto y aprender a interpretar el patrón de sonidos que rebotan en su entorno: eso es el sonar. Al chasquear los dedos, se puede caminar y nunca golpear nada. El tercer ejemplo es el cinturón háptico, en el que si se tiene una correa alrededor de la cintura, se puede dar un sentido de dirección similar a como las aves pueden sentir dónde está el norte. Y, algunos de los ejemplos extraños, es conectar un tercer ojo a una rana. Entonces, la rana también aprenderá a usar ese ojo. Las principales líneas de investigación en este sentido las presenta (Ng 2017) de una manera introductoria.
Hay mucha paquetería que ofrece implementaciones de redes neuronales y que se pueden aplicar directamente. El conjunto de datos de ejemplo es del estudio de cáncer de Wisconsin. Se leen los datos y se eliminan las filas con datos faltantes. El siguiente código usa el paquete mlbench (Newman et al. 1998), que contiene esta base. A continuación se muestran las primeras líneas de los datos.
library(mlbench)
library(tidyverse)
library(tidymodels)
data("BreastCancer")
BCrec <- recipe(Class ~ ., data = BreastCancer) %>%
step_naomit(all_predictors()) %>%
prep(BreastCancer, verbose = FALSE) %>%
bake(new_data = NULL)
BCrec
## # A tibble: 683 x 11
## Id Cl.thickness Cell.size Cell.shape Marg.adhesion Epith.c.size
## <fct> <ord> <ord> <ord> <ord> <ord>
## 1 1000025 5 1 1 1 2
## 2 1002945 5 4 4 5 7
## 3 1015425 3 1 1 1 2
## 4 1016277 6 8 8 1 3
## 5 1017023 4 1 1 3 2
## 6 1017122 8 10 10 8 7
## 7 1018099 1 1 1 1 2
## 8 1018561 2 1 2 1 2
## 9 1033078 2 1 1 1 2
## 10 1033078 4 2 1 1 2
## # … with 673 more rows, and 5 more variables: Bare.nuclei <fct>,
## # Bl.cromatin <fct>, Normal.nucleoli <fct>, Mitoses <fct>, Class <fct>
En este conjunto de datos, hay cerca de \(700\) muestras de tejido tomadas en biopsias. Para cada biopsia, se registran nueve características diferentes, como el grosor celular, el tamaño celular y la forma celular. etc. Los nombres de las columnas en el conjunto de datos son los siguientes.
names(BreastCancer)
## [1] "Id" "Cl.thickness" "Cell.size" "Cell.shape"
## [5] "Marg.adhesion" "Epith.c.size" "Bare.nuclei" "Bl.cromatin"
## [9] "Normal.nucleoli" "Mitoses" "Class"
La última columna del conjunto de datos es Class, que es benigna o maligna. Entonces, el objetivo del análisis es construir un modelo que aprenda a decidir si el tumor es maligno o no.
La primera librería en R
que se explorará es deepnet (Rong 2014). Se aplica el paquete al conjunto de datos de cáncer de la siguiente manera. Primero, se crea la variable dependiente y también el conjunto de características de las variables independientes.
# librería vieja, no soporta tibbles
y <- BCrec %>% select(Class) %>% mutate(Class = ifelse(Class == "benign",0,1)) %>% as.matrix()
x <- BCrec %>% select(-Class,-Id) %>% mutate_all(as.numeric) %>% as.matrix()
Luego se usa la función nn.train()
para modelar la red neuronal. Como se puede ver en el código del programa a continuación, se tienen \(5\) nodos en la única capa oculta.
library(deepnet)
nn <- nn.train(x, y, hidden = c(5))
yy = nn.predict(nn, x)
print(head(yy))
## [,1]
## [1,] 0.2743921
## [2,] 0.4001388
## [3,] 0.2842532
## [4,] 0.4125720
## [5,] 0.2861675
## [6,] 0.4448299
Se toman la salidas de la red y se convierten en clases, de modo que la clase \(0\) es benigna y la clase \(1\) es maligna. Luego se construye la matriz de confusión para ver qué tan bien funciona el modelo en la muestra. La función table()
aquí crea la matriz de confusión, que es una tabulación de cuántas observaciones que fueron benignas y malignas se clasificaron correctamente, que es la forma práctica de evaluar qué tan exitosa fue la modelación de aprendizaje automático en la clasificación.
yhat <- yy %>% as_tibble() %>% mutate(yy = ifelse(yy > mean(yy),1,0)) %>% select(yy) %>% as.matrix()
cm <- table(y,yhat)
print(cm)
## yhat
## y 0 1
## 0 424 20
## 1 5 234
La diagonal de la matriz de confusión contiene la mayoría de las entradas, lo que sugiere que la red neuronal hace un muy buen trabajo de clasificación. La precisión se puede calcular fácilmente como el número de entradas de diagnóstico en la matriz de confusión dividido por el recuento total de valores en la matriz.
print(sum(diag(cm))/sum(cm))
## [1] 0.9633968
Se ha visto que el modelo funciona, por lo que se puede profundizar en la función con más detalle para examinar las opciones que permite con help("nn.train")
.
A modo de comparación, se prueba la librería neuralnet (Fritsch, Guenther, and Wright 2019). Los comandos son básicamente los mismos. La función básica en la paquetería también se llama neuralnet()
.
library(neuralnet)
df <- data.frame(cbind(x,y)) # no soporta tibbles
neuraln <- neuralnet(y~.,data=df,hidden = 5)
yy2 <- neuraln$net.result[[1]]
yhat2 <- yy2 %>% as_tibble() %>% mutate(yy2 = ifelse(yy2 > mean(yy2),1,0)) %>% select(yy2) %>% as.matrix()
cm2 <- table(y,yhat2)
print(cm2)
## yhat2
## y 0 1
## 0 444 0
## 1 0 239
La librería también funciona muy bien en este conjunto de datos. Además, se cuenta con una función interesante que permite trazar la red neuronal, heredadndo de la función plot()
y pasándole el objeto de salida, en este caso neuraln
. Esto debe ejecutarse de forma interactiva, pero aquí hay una muestra fuera de la trama en la Figura 4.
Figure 4: Output of the neural net fitting procedure
La gente en colaboración de h2o (LeDell et al. 2021), han desarrollado una versión de R
basada en Java
, en la que proporcionan una aplicación de aprendizaje profundo basada en redes.
H20
es de código abierto, en memoria, distribuida, rápida y proporciona una plataforma escalable de aprendizaje automático y análisis predictivo para construir modelos de aprendizaje automático en big data. El código central de H20
está escrito en Java
. Dentro de H20
, se utiliza un almacén de clave/valor distribuido para acceder y hacer referencia a datos, modelos, objetos, etc., en todos los nodos y máquinas. Los algoritmos se implementan en un marco Map/Reduce y utilizan subprocesos múltiples. Los datos se leen en paralelo y se distribuyen por el clúster y se almacenan en la memoria en un formato de columnas de forma comprimida. Por lo tanto, incluso en una sola máquina, el algoritmo de aprendizaje profundo en H2O
explotará todos los núcleos de la CPU en paralelo.
Aquí se inicia un servidor usando todos los núcleos de la máquina y luego se usa el kit de herramientas de aprendizaje profundo de la paquetería H2O
para ajustar un modelo.
library(h2o)
localH2O = h2o.init(ip="localhost", port = 54321,
startH2O = TRUE, nthreads=-1)
## Connection successful!
##
## R is connected to the H2O cluster:
## H2O cluster uptime: 56 minutes 9 seconds
## H2O cluster timezone: America/Mexico_City
## H2O data parsing timezone: UTC
## H2O cluster version: 3.32.1.3
## H2O cluster version age: 2 months and 1 day
## H2O cluster name: H2O_started_from_R_juan_acuna_uzt558
## H2O cluster total nodes: 1
## H2O cluster total memory: 1.53 GB
## H2O cluster total cores: 4
## H2O cluster allowed cores: 4
## H2O cluster healthy: TRUE
## H2O Connection ip: localhost
## H2O Connection port: 54321
## H2O Connection proxy: NA
## H2O Internal Security: FALSE
## H2O API Extensions: Amazon S3, XGBoost, Algos, AutoML, Core V3, TargetEncoder, Core V4
## R Version: R version 4.1.0 (2021-05-18)
write_csv(BreastCancer, "BreastCancer.csv")
train <- h2o.importFile("BreastCancer.csv")
##
|
| | 0%
|
|======================================================================| 100%
test <- h2o.importFile("BreastCancer.csv")
##
|
| | 0%
|
|======================================================================| 100%
y = names(train)[11]
x = names(train)[1:10]
train[,y] = as.factor(train[,y])
test[,y] = as.factor(train[,y])
model = h2o.deeplearning(x=x,
y=y,
training_frame=train,
validation_frame=test,
distribution = "multinomial",
activation = "RectifierWithDropout",
hidden = c(10,10,10,10),
input_dropout_ratio = 0.2,
l1 = 1e-5,
epochs = 50)
##
|
| | 0%
|
|======================================================================| 100%
print(model)
## Model Details:
## ==============
##
## H2OBinomialModel: deeplearning
## Model ID: DeepLearning_model_R_1626858183250_17
## Status of Neuron Layers: predicting Class, 2-class classification, multinomial distribution, CrossEntropy loss, 462 weights/biases, 12.3 KB, 34,950 training samples, mini-batch size 1
## layer units type dropout l1 l2 mean_rate rate_rms
## 1 1 10 Input 20.00 % NA NA NA NA
## 2 2 10 RectifierDropout 50.00 % 0.000010 0.000000 0.001070 0.000529
## 3 3 10 RectifierDropout 50.00 % 0.000010 0.000000 0.000843 0.000359
## 4 4 10 RectifierDropout 50.00 % 0.000010 0.000000 0.001021 0.000668
## 5 5 10 RectifierDropout 50.00 % 0.000010 0.000000 0.009634 0.028120
## 6 6 2 Softmax NA 0.000010 0.000000 0.001339 0.000738
## momentum mean_weight weight_rms mean_bias bias_rms
## 1 NA NA NA NA NA
## 2 0.000000 0.069286 0.330822 0.551820 0.091550
## 3 0.000000 -0.035002 0.369296 0.893014 0.232191
## 4 0.000000 -0.020622 0.322953 0.876605 0.206423
## 5 0.000000 0.007040 0.338101 0.785790 0.409117
## 6 0.000000 -0.570883 1.478064 0.002164 0.151419
##
##
## H2OBinomialMetrics: deeplearning
## ** Reported on training data. **
## ** Metrics reported on full training frame **
##
## MSE: 0.02418027
## RMSE: 0.1555001
## LogLoss: 0.09322254
## Mean Per-Class Error: 0.02369132
## AUC: 0.9934679
## AUCPR: 0.9860286
## Gini: 0.9869358
##
## Confusion Matrix (vertical: actual; across: predicted) for F1-optimal threshold:
## benign malignant Error Rate
## benign 442 16 0.034934 =16/458
## malignant 3 238 0.012448 =3/241
## Totals 445 254 0.027182 =19/699
##
## Maximum Metrics: Maximum metrics at their respective thresholds
## metric threshold value idx
## 1 max f1 0.328615 0.961616 228
## 2 max f2 0.122725 0.981194 233
## 3 max f0point5 0.895583 0.952583 209
## 4 max accuracy 0.328615 0.972818 228
## 5 max precision 0.973304 1.000000 0
## 6 max recall 0.005444 1.000000 290
## 7 max specificity 0.973304 1.000000 0
## 8 max absolute_mcc 0.328615 0.941376 228
## 9 max min_per_class_accuracy 0.553775 0.969432 222
## 10 max mean_per_class_accuracy 0.122725 0.977183 233
## 11 max tns 0.973304 458.000000 0
## 12 max fns 0.973304 240.000000 0
## 13 max fps 0.002681 458.000000 399
## 14 max tps 0.005444 241.000000 290
## 15 max tnr 0.973304 1.000000 0
## 16 max fnr 0.973304 0.995851 0
## 17 max fpr 0.002681 1.000000 399
## 18 max tpr 0.005444 1.000000 290
##
## Gains/Lift Table: Extract with `h2o.gainsLift(<model>, <data>)` or `h2o.gainsLift(<model>, valid=<T/F>, xval=<T/F>)`
## H2OBinomialMetrics: deeplearning
## ** Reported on validation data. **
## ** Metrics reported on full validation frame **
##
## MSE: 0.02418027
## RMSE: 0.1555001
## LogLoss: 0.09322254
## Mean Per-Class Error: 0.02369132
## AUC: 0.9934679
## AUCPR: 0.9860286
## Gini: 0.9869358
##
## Confusion Matrix (vertical: actual; across: predicted) for F1-optimal threshold:
## benign malignant Error Rate
## benign 442 16 0.034934 =16/458
## malignant 3 238 0.012448 =3/241
## Totals 445 254 0.027182 =19/699
##
## Maximum Metrics: Maximum metrics at their respective thresholds
## metric threshold value idx
## 1 max f1 0.328615 0.961616 228
## 2 max f2 0.122725 0.981194 233
## 3 max f0point5 0.895583 0.952583 209
## 4 max accuracy 0.328615 0.972818 228
## 5 max precision 0.973304 1.000000 0
## 6 max recall 0.005444 1.000000 290
## 7 max specificity 0.973304 1.000000 0
## 8 max absolute_mcc 0.328615 0.941376 228
## 9 max min_per_class_accuracy 0.553775 0.969432 222
## 10 max mean_per_class_accuracy 0.122725 0.977183 233
## 11 max tns 0.973304 458.000000 0
## 12 max fns 0.973304 240.000000 0
## 13 max fps 0.002681 458.000000 399
## 14 max tps 0.005444 241.000000 290
## 15 max tnr 0.973304 1.000000 0
## 16 max fnr 0.973304 0.995851 0
## 17 max fpr 0.002681 1.000000 399
## 18 max tpr 0.005444 1.000000 290
##
## Gains/Lift Table: Extract with `h2o.gainsLift(<model>, <data>)` or `h2o.gainsLift(<model>, valid=<T/F>, xval=<T/F>)`
La librería de aprendizaje profundo H2O
funciona muy bien. La tasa de error puede verse en la matriz de confusión como muy baja. También se nota que H2O
se puede usar para ejecutar análisis distintos del aprendizaje profundo en R
, ya que se proporcionan muchas otras funciones, utilizando una sintaxis casi idéntica a R
.
Como segundo caso, se utiliza el conjunto de datos MNIST, replicando un ejemplo del manual de aprendizaje profundo H2O
. Este ejemplo de reconocimiento de caracteres (dígitos numéricos) es uno de los clásicos del aprendizaje automático. Primero se leen los datos.
library(h2o)
localH2O = h2o.init(ip="localhost", port = 54321,
startH2O = TRUE)
## Connection successful!
##
## R is connected to the H2O cluster:
## H2O cluster uptime: 56 minutes 14 seconds
## H2O cluster timezone: America/Mexico_City
## H2O data parsing timezone: UTC
## H2O cluster version: 3.32.1.3
## H2O cluster version age: 2 months and 1 day
## H2O cluster name: H2O_started_from_R_juan_acuna_uzt558
## H2O cluster total nodes: 1
## H2O cluster total memory: 1.53 GB
## H2O cluster total cores: 4
## H2O cluster allowed cores: 4
## H2O cluster healthy: TRUE
## H2O Connection ip: localhost
## H2O Connection port: 54321
## H2O Connection proxy: NA
## H2O Internal Security: FALSE
## H2O API Extensions: Amazon S3, XGBoost, Algos, AutoML, Core V3, TargetEncoder, Core V4
## R Version: R version 4.1.0 (2021-05-18)
## Importar MNIST CSV como H2O
train <- h2o.importFile("mnist_train.csv")
##
|
| | 0%
|
|================= | 25%
|
|==================================================== | 75%
|
|======================================================================| 100%
test <- h2o.importFile("mnist_test.csv")
##
|
| | 0%
|
|======================================================================| 100%
print(dim(train))
## [1] 60000 785
print(dim(test))
## [1] 10000 785
Como se puede ver, hay \(70000\) observaciones en la base de datos y cada ejemplo contiene todos los \(784\) píxeles de cada imagen, lo que define el carácter. Esto sugiere un conjunto de datos de entrada muy grande. Ahora, se tiene un espacio de parámetros mucho más grande que debe ajustarse a la red de aprendizaje profundo. Usando un modelo de tres capas ocultas, y cada capa oculta tiene \(10\) nodos, se atacará el problema.
y <- "label"
x <- setdiff(names(train), y)
train[,y] <- as.factor(train[,y])
test[,y] <- as.factor(test[,y])
# Entrenar un modelo de aprendizaje profundo y validarlo en conjunto de prueba
model <- h2o.deeplearning(x = x,
y = y,
training_frame = train,
validation_frame = test,
distribution = "multinomial",
activation = "RectifierWithDropout",
hidden = c(10,10,10),
input_dropout_ratio = 0.2,
l1 = 1e-5,
epochs = 20)
##
|
| | 0%
|
|= | 2%
|
|== | 3%
|
|=== | 5%
|
|==== | 6%
|
|===== | 8%
|
|====== | 9%
|
|======= | 11%
|
|========= | 12%
|
|========== | 14%
|
|=========== | 15%
|
|============ | 17%
|
|============= | 18%
|
|============== | 20%
|
|=============== | 21%
|
|================ | 23%
|
|================= | 24%
|
|================== | 26%
|
|=================== | 28%
|
|==================== | 29%
|
|===================== | 31%
|
|====================== | 32%
|
|======================== | 34%
|
|========================= | 35%
|
|========================== | 37%
|
|=========================== | 38%
|
|============================ | 40%
|
|============================= | 41%
|
|============================== | 43%
|
|=============================== | 44%
|
|================================ | 46%
|
|================================= | 47%
|
|================================== | 49%
|
|=================================== | 50%
|
|==================================== | 52%
|
|===================================== | 53%
|
|======================================= | 55%
|
|======================================== | 57%
|
|========================================= | 58%
|
|========================================== | 60%
|
|=========================================== | 61%
|
|============================================ | 63%
|
|============================================= | 64%
|
|============================================== | 66%
|
|=============================================== | 67%
|
|================================================ | 69%
|
|================================================= | 70%
|
|================================================== | 72%
|
|=================================================== | 73%
|
|==================================================== | 75%
|
|===================================================== | 76%
|
|======================================================= | 78%
|
|======================================================== | 79%
|
|========================================================= | 81%
|
|========================================================== | 83%
|
|=========================================================== | 84%
|
|============================================================ | 86%
|
|============================================================= | 87%
|
|============================================================== | 89%
|
|======================================================================| 100%
print(model)
## Model Details:
## ==============
##
## H2OMultinomialModel: deeplearning
## Model ID: DeepLearning_model_R_1626858183250_22
## Status of Neuron Layers: predicting label, 10-class classification, multinomial distribution, CrossEntropy loss, 7,510 weights/biases, 237.7 KB, 1,081,966 training samples, mini-batch size 1
## layer units type dropout l1 l2 mean_rate rate_rms
## 1 1 717 Input 20.00 % NA NA NA NA
## 2 2 10 RectifierDropout 50.00 % 0.000010 0.000000 0.022629 0.061130
## 3 3 10 RectifierDropout 50.00 % 0.000010 0.000000 0.000150 0.000115
## 4 4 10 RectifierDropout 50.00 % 0.000010 0.000000 0.000268 0.000174
## 5 5 10 Softmax NA 0.000010 0.000000 0.001782 0.001453
## momentum mean_weight weight_rms mean_bias bias_rms
## 1 NA NA NA NA NA
## 2 0.000000 -0.000565 0.133451 0.447794 0.369733
## 3 0.000000 -0.057513 0.278600 0.996361 0.234576
## 4 0.000000 -0.051754 0.317745 0.457398 0.494862
## 5 0.000000 -0.696140 1.487919 -1.923697 0.970026
##
##
## H2OMultinomialMetrics: deeplearning
## ** Reported on training data. **
## ** Metrics reported on temporary training frame with 10083 samples **
##
## Training Set Metrics:
## =====================
##
## MSE: (Extract with `h2o.mse`) 0.5013734
## RMSE: (Extract with `h2o.rmse`) 0.7080773
## Logloss: (Extract with `h2o.logloss`) 1.325287
## Mean Per-Class Error: 0.4354626
## AUC: (Extract with `h2o.auc`) NaN
## AUCPR: (Extract with `h2o.aucpr`) NaN
## Confusion Matrix: Extract with `h2o.confusionMatrix(<model>,train = TRUE)`)
## =========================================================================
## Confusion Matrix: Row labels: Actual class; Column labels: Predicted class
## 0 1 2 3 4 5 6 7 8 9 Error Rate
## 0 740 0 0 13 0 210 0 1 6 0 0.2371 = 230 / 970
## 1 1 1039 0 47 0 5 1 2 37 0 0.0822 = 93 / 1,132
## 2 5 5 24 31 0 78 0 2 870 0 0.9764 = 991 / 1,015
## 3 11 3 0 796 0 124 0 7 65 0 0.2087 = 210 / 1,006
## 4 0 0 0 1 451 139 0 6 347 34 0.5389 = 527 / 978
## 5 17 1 0 88 0 763 1 3 45 0 0.1688 = 155 / 918
## 6 17 0 1 3 9 876 70 0 25 0 0.9301 = 931 / 1,001
## 7 3 22 0 110 2 9 1 913 40 5 0.1738 = 192 / 1,105
## 8 0 15 1 36 1 99 0 0 792 0 0.1610 = 152 / 944
## 9 1 0 0 30 248 81 0 80 450 124 0.8777 = 890 / 1,014
## Totals 795 1085 26 1155 711 2384 73 1014 2677 163 0.4335 = 4,371 / 10,083
##
## Hit Ratio Table: Extract with `h2o.hit_ratio_table(<model>,train = TRUE)`
## =======================================================================
## Top-10 Hit Ratios:
## k hit_ratio
## 1 1 0.566498
## 2 2 0.790439
## 3 3 0.888525
## 4 4 0.931270
## 5 5 0.956065
## 6 6 0.980363
## 7 7 0.989090
## 8 8 0.995041
## 9 9 0.998413
## 10 10 1.000000
##
##
##
##
## H2OMultinomialMetrics: deeplearning
## ** Reported on validation data. **
## ** Metrics reported on full validation frame **
##
## Validation Set Metrics:
## =====================
##
## Extract validation frame with `h2o.getFrame("RTMP_sid_8232_8")`
## MSE: (Extract with `h2o.mse`) 0.4986107
## RMSE: (Extract with `h2o.rmse`) 0.7061237
## Logloss: (Extract with `h2o.logloss`) 1.317135
## Mean Per-Class Error: 0.425529
## AUC: (Extract with `h2o.auc`) NaN
## AUCPR: (Extract with `h2o.aucpr`) NaN
## Confusion Matrix: Extract with `h2o.confusionMatrix(<model>,valid = TRUE)`)
## =========================================================================
## Confusion Matrix: Row labels: Actual class; Column labels: Predicted class
## 0 1 2 3 4 5 6 7 8 9 Error Rate
## 0 775 0 0 13 0 191 0 1 0 0 0.2092 = 205 / 980
## 1 0 1053 0 31 0 6 0 0 45 0 0.0722 = 82 / 1,135
## 2 4 4 18 35 3 68 3 1 895 1 0.9826 = 1,014 / 1,032
## 3 6 1 0 844 0 99 0 8 52 0 0.1644 = 166 / 1,010
## 4 0 0 0 6 470 102 0 6 364 34 0.5214 = 512 / 982
## 5 10 0 0 82 2 740 0 5 53 0 0.1704 = 152 / 892
## 6 30 2 0 7 11 807 87 0 14 0 0.9092 = 871 / 958
## 7 3 23 0 108 1 10 1 839 36 7 0.1839 = 189 / 1,028
## 8 4 7 1 37 0 100 0 4 821 0 0.1571 = 153 / 974
## 9 4 1 0 26 282 64 0 78 438 116 0.8850 = 893 / 1,009
## Totals 836 1091 19 1189 769 2187 91 942 2718 158 0.4237 = 4,237 / 10,000
##
## Hit Ratio Table: Extract with `h2o.hit_ratio_table(<model>,valid = TRUE)`
## =======================================================================
## Top-10 Hit Ratios:
## k hit_ratio
## 1 1 0.576300
## 2 2 0.796000
## 3 3 0.891600
## 4 4 0.934700
## 5 5 0.958200
## 6 6 0.979200
## 7 7 0.989000
## 8 8 0.995800
## 9 9 0.999100
## 10 10 1.000000
El error medio es mucho mayor aquí, alrededor de un tercio. Parece que el error más alto surge de que la modelación confunde el número \(8\) con el número \(1\). También parece confundir el número \(3\) con el número \(5\). Sin embargo, parece que lo hace mejor para identificar los números \(3\) y \(7\).
Se repite el modelo con una red más profunda con más nodos para ver si aumenta la precisión.
y <- "label"
x <- setdiff(names(train), y)
train[,y] <- as.factor(train[,y])
test[,y] <- as.factor(test[,y])
# Entrenar un modelo de aprendizaje profundo y validarlo en conjunto de prueba
model <- h2o.deeplearning(x = x,
y = y,
training_frame = train,
validation_frame = test,
distribution = "multinomial",
activation = "RectifierWithDropout",
hidden = c(50,50,50,50,50),
input_dropout_ratio = 0.2,
l1 = 1e-5,
epochs = 20)
##
|
| | 0%
|
|= | 1%
|
|== | 2%
|
|=== | 4%
|
|=== | 5%
|
|==== | 6%
|
|===== | 7%
|
|====== | 8%
|
|======= | 10%
|
|======== | 11%
|
|======== | 12%
|
|========= | 13%
|
|========== | 15%
|
|=========== | 16%
|
|============ | 17%
|
|============= | 18%
|
|============== | 19%
|
|============== | 21%
|
|=============== | 22%
|
|================ | 23%
|
|================= | 24%
|
|================== | 25%
|
|=================== | 27%
|
|==================== | 28%
|
|==================== | 29%
|
|===================== | 30%
|
|====================== | 32%
|
|======================= | 33%
|
|======================== | 34%
|
|========================= | 35%
|
|========================= | 36%
|
|========================== | 38%
|
|=========================== | 39%
|
|============================ | 40%
|
|============================= | 41%
|
|============================== | 42%
|
|=============================== | 44%
|
|=============================== | 45%
|
|================================ | 46%
|
|================================= | 47%
|
|================================== | 49%
|
|=================================== | 50%
|
|==================================== | 51%
|
|===================================== | 52%
|
|===================================== | 53%
|
|====================================== | 55%
|
|======================================= | 56%
|
|======================================== | 57%
|
|========================================= | 58%
|
|========================================== | 59%
|
|========================================== | 61%
|
|=========================================== | 62%
|
|============================================ | 63%
|
|============================================= | 64%
|
|============================================== | 66%
|
|=============================================== | 67%
|
|================================================ | 68%
|
|================================================ | 69%
|
|================================================= | 70%
|
|================================================== | 72%
|
|=================================================== | 73%
|
|==================================================== | 74%
|
|===================================================== | 75%
|
|====================================================== | 76%
|
|====================================================== | 78%
|
|======================================================= | 79%
|
|======================================================== | 80%
|
|========================================================= | 81%
|
|========================================================== | 83%
|
|=========================================================== | 84%
|
|=========================================================== | 85%
|
|============================================================ | 86%
|
|============================================================= | 87%
|
|============================================================== | 89%
|
|=============================================================== | 90%
|
|================================================================ | 91%
|
|================================================================= | 92%
|
|================================================================= | 93%
|
|================================================================== | 95%
|
|=================================================================== | 96%
|
|==================================================================== | 97%
|
|===================================================================== | 98%
|
|======================================================================| 100%
print(model)
## Model Details:
## ==============
##
## H2OMultinomialModel: deeplearning
## Model ID: DeepLearning_model_R_1626858183250_23
## Status of Neuron Layers: predicting label, 10-class classification, multinomial distribution, CrossEntropy loss, 46,610 weights/biases, 699.8 KB, 1,210,081 training samples, mini-batch size 1
## layer units type dropout l1 l2 mean_rate rate_rms
## 1 1 717 Input 20.00 % NA NA NA NA
## 2 2 50 RectifierDropout 50.00 % 0.000010 0.000000 0.032165 0.084483
## 3 3 50 RectifierDropout 50.00 % 0.000010 0.000000 0.000312 0.000141
## 4 4 50 RectifierDropout 50.00 % 0.000010 0.000000 0.000631 0.000326
## 5 5 50 RectifierDropout 50.00 % 0.000010 0.000000 0.000821 0.000430
## 6 6 50 RectifierDropout 50.00 % 0.000010 0.000000 0.000789 0.000450
## 7 7 10 Softmax NA 0.000010 0.000000 0.004168 0.005216
## momentum mean_weight weight_rms mean_bias bias_rms
## 1 NA NA NA NA NA
## 2 0.000000 0.043230 0.115339 -0.146830 0.194481
## 3 0.000000 -0.050174 0.149822 0.849328 0.153448
## 4 0.000000 -0.033811 0.162735 0.815715 0.231792
## 5 0.000000 -0.034074 0.174709 0.883515 0.210183
## 6 0.000000 -0.064663 0.154984 0.774011 0.247604
## 7 0.000000 -0.479832 0.895738 -3.185287 2.208103
##
##
## H2OMultinomialMetrics: deeplearning
## ** Reported on training data. **
## ** Metrics reported on temporary training frame with 10066 samples **
##
## Training Set Metrics:
## =====================
##
## MSE: (Extract with `h2o.mse`) 0.1548053
## RMSE: (Extract with `h2o.rmse`) 0.393453
## Logloss: (Extract with `h2o.logloss`) 0.5209894
## Mean Per-Class Error: 0.09347684
## AUC: (Extract with `h2o.auc`) NaN
## AUCPR: (Extract with `h2o.aucpr`) NaN
## Confusion Matrix: Extract with `h2o.confusionMatrix(<model>,train = TRUE)`)
## =========================================================================
## Confusion Matrix: Row labels: Actual class; Column labels: Predicted class
## 0 1 2 3 4 5 6 7 8 9 Error Rate
## 0 948 0 27 8 0 3 6 2 21 0 0.0660 = 67 / 1,015
## 1 0 1012 7 1 0 1 12 1 61 1 0.0766 = 84 / 1,096
## 2 1 0 908 27 1 0 27 5 34 1 0.0956 = 96 / 1,004
## 3 1 0 28 971 1 21 2 9 13 4 0.0752 = 79 / 1,050
## 4 0 0 1 2 802 1 3 0 117 23 0.1549 = 147 / 949
## 5 4 1 3 44 0 764 7 1 48 3 0.1269 = 111 / 875
## 6 1 1 4 0 0 9 952 0 32 0 0.0470 = 47 / 999
## 7 1 2 10 13 2 0 0 990 25 13 0.0625 = 66 / 1,056
## 8 3 10 6 18 0 30 4 3 965 1 0.0721 = 75 / 1,040
## 9 2 1 3 19 54 7 0 26 43 827 0.1578 = 155 / 982
## Totals 961 1027 997 1103 860 836 1013 1037 1359 873 0.0921 = 927 / 10,066
##
## Hit Ratio Table: Extract with `h2o.hit_ratio_table(<model>,train = TRUE)`
## =======================================================================
## Top-10 Hit Ratios:
## k hit_ratio
## 1 1 0.907908
## 2 2 0.949334
## 3 3 0.967216
## 4 4 0.976952
## 5 5 0.983509
## 6 6 0.989668
## 7 7 0.993443
## 8 8 0.995728
## 9 9 0.998907
## 10 10 1.000000
##
##
##
##
## H2OMultinomialMetrics: deeplearning
## ** Reported on validation data. **
## ** Metrics reported on full validation frame **
##
## Validation Set Metrics:
## =====================
##
## Extract validation frame with `h2o.getFrame("RTMP_sid_8232_10")`
## MSE: (Extract with `h2o.mse`) 0.1585816
## RMSE: (Extract with `h2o.rmse`) 0.398223
## Logloss: (Extract with `h2o.logloss`) 0.5335397
## Mean Per-Class Error: 0.09983358
## AUC: (Extract with `h2o.auc`) NaN
## AUCPR: (Extract with `h2o.aucpr`) NaN
## Confusion Matrix: Extract with `h2o.confusionMatrix(<model>,valid = TRUE)`)
## =========================================================================
## Confusion Matrix: Row labels: Actual class; Column labels: Predicted class
## 0 1 2 3 4 5 6 7 8 9 Error Rate
## 0 924 0 21 3 0 11 6 3 12 0 0.0571 = 56 / 980
## 1 0 1050 4 1 0 0 8 0 72 0 0.0749 = 85 / 1,135
## 2 3 1 936 20 2 0 26 7 36 1 0.0930 = 96 / 1,032
## 3 0 0 22 933 0 26 2 14 12 1 0.0762 = 77 / 1,010
## 4 0 0 3 4 835 0 9 3 113 15 0.1497 = 147 / 982
## 5 2 0 3 63 0 750 6 5 60 3 0.1592 = 142 / 892
## 6 3 3 4 1 1 9 901 0 36 0 0.0595 = 57 / 958
## 7 0 2 21 14 0 0 0 952 24 15 0.0739 = 76 / 1,028
## 8 2 2 6 20 1 37 4 9 890 3 0.0862 = 84 / 974
## 9 4 0 2 17 70 4 1 26 46 839 0.1685 = 170 / 1,009
## Totals 938 1058 1022 1076 909 837 963 1019 1301 877 0.0990 = 990 / 10,000
##
## Hit Ratio Table: Extract with `h2o.hit_ratio_table(<model>,valid = TRUE)`
## =======================================================================
## Top-10 Hit Ratios:
## k hit_ratio
## 1 1 0.901000
## 2 2 0.947000
## 3 3 0.966500
## 4 4 0.976400
## 5 5 0.983400
## 6 6 0.988800
## 7 7 0.993900
## 8 8 0.996500
## 9 9 0.999200
## 10 10 1.000000
De hecho, ahora la tasa de error se reduce considerablemente. Es útil evaluar si la mejora proviene de más nodos en cada capa o de más capas ocultas.
y <- "label"
x <- setdiff(names(train), y)
train[,y] <- as.factor(train[,y])
test[,y] <- as.factor(test[,y])
# Entrenar un modelo de aprendizaje profundo y validarlo en conjunto de prueba
model <- h2o.deeplearning(x = x,
y = y,
training_frame = train,
validation_frame = test,
distribution = "multinomial",
activation = "RectifierWithDropout",
hidden = c(50,50,50,50,50),
input_dropout_ratio = 0.2,
l1 = 1e-5,
epochs = 20)
##
|
| | 0%
|
| | 1%
|
|= | 1%
|
|= | 2%
|
|== | 2%
|
|== | 3%
|
|=== | 4%
|
|=== | 5%
|
|==== | 5%
|
|==== | 6%
|
|===== | 7%
|
|===== | 8%
|
|====== | 8%
|
|====== | 9%
|
|======= | 10%
|
|======== | 11%
|
|======== | 12%
|
|========= | 13%
|
|========== | 14%
|
|=========== | 15%
|
|=========== | 16%
|
|============ | 17%
|
|============= | 18%
|
|============= | 19%
|
|============== | 20%
|
|=============== | 21%
|
|=============== | 22%
|
|================ | 22%
|
|================ | 23%
|
|================= | 24%
|
|================= | 25%
|
|================== | 25%
|
|================== | 26%
|
|=================== | 27%
|
|=================== | 28%
|
|==================== | 28%
|
|==================== | 29%
|
|===================== | 30%
|
|====================== | 31%
|
|====================== | 32%
|
|======================= | 33%
|
|======================== | 34%
|
|======================== | 35%
|
|========================= | 36%
|
|========================== | 37%
|
|=========================== | 38%
|
|=========================== | 39%
|
|============================ | 40%
|
|============================= | 41%
|
|============================= | 42%
|
|============================== | 42%
|
|============================== | 43%
|
|=============================== | 44%
|
|=============================== | 45%
|
|================================ | 45%
|
|================================ | 46%
|
|================================= | 47%
|
|================================= | 48%
|
|================================== | 48%
|
|================================== | 49%
|
|=================================== | 49%
|
|=================================== | 50%
|
|=================================== | 51%
|
|==================================== | 51%
|
|==================================== | 52%
|
|===================================== | 52%
|
|===================================== | 53%
|
|====================================== | 54%
|
|====================================== | 55%
|
|======================================= | 55%
|
|======================================= | 56%
|
|======================================== | 57%
|
|======================================== | 58%
|
|========================================= | 58%
|
|========================================= | 59%
|
|========================================== | 60%
|
|=========================================== | 61%
|
|=========================================== | 62%
|
|============================================ | 63%
|
|============================================= | 64%
|
|============================================== | 65%
|
|============================================== | 66%
|
|=============================================== | 67%
|
|================================================ | 68%
|
|================================================ | 69%
|
|================================================= | 69%
|
|================================================= | 70%
|
|================================================== | 71%
|
|================================================== | 72%
|
|=================================================== | 72%
|
|=================================================== | 73%
|
|=================================================== | 74%
|
|==================================================== | 74%
|
|==================================================== | 75%
|
|===================================================== | 75%
|
|===================================================== | 76%
|
|====================================================== | 77%
|
|====================================================== | 78%
|
|======================================================= | 78%
|
|======================================================= | 79%
|
|======================================================== | 80%
|
|========================================================= | 81%
|
|========================================================= | 82%
|
|========================================================== | 83%
|
|=========================================================== | 84%
|
|=========================================================== | 85%
|
|============================================================ | 86%
|
|============================================================= | 87%
|
|============================================================== | 88%
|
|============================================================== | 89%
|
|=============================================================== | 90%
|
|================================================================ | 91%
|
|================================================================ | 92%
|
|================================================================= | 92%
|
|================================================================= | 93%
|
|================================================================== | 94%
|
|================================================================== | 95%
|
|=================================================================== | 95%
|
|=================================================================== | 96%
|
|==================================================================== | 97%
|
|==================================================================== | 98%
|
|===================================================================== | 98%
|
|===================================================================== | 99%
|
|======================================================================| 99%
|
|======================================================================| 100%
print(model)
## Model Details:
## ==============
##
## H2OMultinomialModel: deeplearning
## Model ID: DeepLearning_model_R_1626858183250_24
## Status of Neuron Layers: predicting label, 10-class classification, multinomial distribution, CrossEntropy loss, 46,610 weights/biases, 699.8 KB, 1,201,663 training samples, mini-batch size 1
## layer units type dropout l1 l2 mean_rate rate_rms
## 1 1 717 Input 20.00 % NA NA NA NA
## 2 2 50 RectifierDropout 50.00 % 0.000010 0.000000 0.031173 0.079519
## 3 3 50 RectifierDropout 50.00 % 0.000010 0.000000 0.000316 0.000134
## 4 4 50 RectifierDropout 50.00 % 0.000010 0.000000 0.000668 0.000331
## 5 5 50 RectifierDropout 50.00 % 0.000010 0.000000 0.000769 0.000437
## 6 6 50 RectifierDropout 50.00 % 0.000010 0.000000 0.000826 0.000474
## 7 7 10 Softmax NA 0.000010 0.000000 0.007635 0.027884
## momentum mean_weight weight_rms mean_bias bias_rms
## 1 NA NA NA NA NA
## 2 0.000000 0.040066 0.110342 -0.079188 0.219893
## 3 0.000000 -0.051558 0.153816 0.819879 0.200658
## 4 0.000000 -0.034381 0.165686 0.804179 0.200374
## 5 0.000000 -0.041682 0.159906 0.778788 0.254128
## 6 0.000000 -0.067395 0.153947 0.758162 0.263121
## 7 0.000000 -0.517643 0.923015 -2.271810 1.711209
##
##
## H2OMultinomialMetrics: deeplearning
## ** Reported on training data. **
## ** Metrics reported on temporary training frame with 10017 samples **
##
## Training Set Metrics:
## =====================
##
## MSE: (Extract with `h2o.mse`) 0.1283733
## RMSE: (Extract with `h2o.rmse`) 0.3582922
## Logloss: (Extract with `h2o.logloss`) 0.4434208
## Mean Per-Class Error: 0.1100217
## AUC: (Extract with `h2o.auc`) NaN
## AUCPR: (Extract with `h2o.aucpr`) NaN
## Confusion Matrix: Extract with `h2o.confusionMatrix(<model>,train = TRUE)`)
## =========================================================================
## Confusion Matrix: Row labels: Actual class; Column labels: Predicted class
## 0 1 2 3 4 5 6 7 8 9 Error Rate
## 0 878 0 7 1 7 122 14 0 8 0 0.1533 = 159 / 1,037
## 1 0 1070 18 1 2 0 0 1 32 1 0.0489 = 55 / 1,125
## 2 0 3 917 3 15 6 11 3 28 0 0.0700 = 69 / 986
## 3 0 1 31 849 2 18 0 9 110 2 0.1693 = 173 / 1,022
## 4 0 0 6 1 951 1 10 0 2 14 0.0345 = 34 / 985
## 5 0 0 14 105 8 670 6 3 74 3 0.2412 = 213 / 883
## 6 4 0 63 0 29 15 888 0 3 0 0.1138 = 114 / 1,002
## 7 0 7 16 3 8 3 0 992 5 35 0.0720 = 77 / 1,069
## 8 0 7 26 7 6 7 2 7 893 1 0.0659 = 63 / 956
## 9 0 2 1 14 57 8 0 28 15 827 0.1313 = 125 / 952
## Totals 882 1090 1099 984 1085 850 931 1043 1170 883 0.1080 = 1,082 / 10,017
##
## Hit Ratio Table: Extract with `h2o.hit_ratio_table(<model>,train = TRUE)`
## =======================================================================
## Top-10 Hit Ratios:
## k hit_ratio
## 1 1 0.891984
## 2 2 0.952880
## 3 3 0.972247
## 4 4 0.981931
## 5 5 0.988619
## 6 6 0.992313
## 7 7 0.995408
## 8 8 0.997404
## 9 9 0.998602
## 10 10 1.000000
##
##
##
##
## H2OMultinomialMetrics: deeplearning
## ** Reported on validation data. **
## ** Metrics reported on full validation frame **
##
## Validation Set Metrics:
## =====================
##
## Extract validation frame with `h2o.getFrame("RTMP_sid_8232_12")`
## MSE: (Extract with `h2o.mse`) 0.1261532
## RMSE: (Extract with `h2o.rmse`) 0.3551805
## Logloss: (Extract with `h2o.logloss`) 0.44194
## Mean Per-Class Error: 0.1088472
## AUC: (Extract with `h2o.auc`) NaN
## AUCPR: (Extract with `h2o.aucpr`) NaN
## Confusion Matrix: Extract with `h2o.confusionMatrix(<model>,valid = TRUE)`)
## =========================================================================
## Confusion Matrix: Row labels: Actual class; Column labels: Predicted class
## 0 1 2 3 4 5 6 7 8 9 Error Rate
## 0 865 0 0 1 3 89 19 1 2 0 0.1173 = 115 / 980
## 1 0 1089 11 0 0 0 1 1 33 0 0.0405 = 46 / 1,135
## 2 1 1 959 2 12 10 6 7 34 0 0.0707 = 73 / 1,032
## 3 0 1 23 860 1 9 0 12 102 2 0.1485 = 150 / 1,010
## 4 0 0 10 0 939 0 8 3 3 19 0.0438 = 43 / 982
## 5 0 0 12 119 11 673 1 2 69 5 0.2455 = 219 / 892
## 6 8 1 39 0 33 21 852 0 4 0 0.1106 = 106 / 958
## 7 0 11 25 3 4 1 1 945 7 31 0.0807 = 83 / 1,028
## 8 2 6 21 10 16 9 1 9 898 2 0.0780 = 76 / 974
## 9 1 4 5 8 72 12 1 28 23 855 0.1526 = 154 / 1,009
## Totals 877 1113 1105 1003 1091 824 890 1008 1175 914 0.1065 = 1,065 / 10,000
##
## Hit Ratio Table: Extract with `h2o.hit_ratio_table(<model>,valid = TRUE)`
## =======================================================================
## Top-10 Hit Ratios:
## k hit_ratio
## 1 1 0.893500
## 2 2 0.952600
## 3 3 0.971600
## 4 4 0.982800
## 5 5 0.988400
## 6 6 0.993600
## 7 7 0.996200
## 8 8 0.998000
## 9 9 0.999100
## 10 10 1.000000
La tasa de error es ahora extremadamente baja, por lo que la cantidad de nodos por capa oculta parece importar más. Sin embargo, se debe tener en cuenta que esto es más arte que ciencia, y se deben probar varias estrategias de modelación antes de decidirse por una ganadora para cierta aplicación.
TensorFlow
(de Google, denominado en forma abreviada TF
) es un marco de trabajo de redes neuronales profunda de código abierto, basado en un modelo gráfico. Es más que una plataforma de redes neuronales y admite el cálculo numérica basado en gráficos de flujo de datos. Los datos pueden estar representados en estructuras \(n-\)dimensionales como vectores y matrices, o tensores de dimensiones superiores. Debido a que estos objetos matemáticos se combinan en un gráfico de flujo de datos para el cálculo, el apodo de esta biblioteca de software es obvio.
Los cálculos para las redes de aprendizaje profundo involucran cálculos de tensores, que se sabe que se implementan de manera más eficiente en las GPU que en las CPU. Por lo tanto, al igual que otras bibliotecas de aprendizaje profundo, TensorFlow se puede implementar en CPU y GPU. La generalidad y la velocidad del software TensorFlow
, la facilidad de instalación, su documentación y ejemplos, y la capacidad de ejecución en múltiples plataformas han convertido a TensorFlow
en el kit de herramientas de aprendizaje profundo más popular en la actualidad (las opiniones sobre esto pueden, por supuesto, diferir).
En lugar de ejecutar TF
de forma nativa, a menudo es más fácil usarlo a través de un programa de interfaz fácil de usar. Una de las API de alto nivel más populares es Keras
. Aunque originalmente escrito en Python
, Keras
se ha extendido a R
a través de la librería kerasR (Arnold 2017).
Se reelaborarán los ejemplos anteriores para ejemplificar lo fácil que es implementar TF
en R
usando Keras
. Se necesitan dos bibliotecas específicas en R
para ejecutar TF
. Una es tensorflow en sí mismo (Allaire and Tang 2021). La otra es keras (Allaire and Chollet 2021). Entonces, para continuar se cargan estas dos bibliotecas, asumiendo, por supuesto, que ya se han instalado.
library(tensorflow)
library(keras)
install_keras()
##
## Installation complete.
Como antes, se ha leído el conjunto de datos de cáncer de mama. Las distribuciones de los valores de las características se ven en la Figura 5.
BCrec2 <- BCrec %>% select(-Class,-Id) %>% mutate_all(as.numeric)
BCrec4 <- tibble(BCrec2,BCrec %>% select(Class))
BCrec4 %>% pivot_longer(names_to = "feature", values_to = "value", -Class) %>%
ggplot(aes(x = feature, y = value, fill = Class)) +
geom_violin(alpha = 0.5, scale = "width") +
theme_bw()
Figure 5: Distributions of the feature values
La meta es conectar las \(9\) funciones de entrada a la clase de salida correcta utilizando una red neuronal artificial. Para esta tarea, se ha elegido la siguiente arquitectura simple con una capa de entrada con \(9\) neuronas (una para cada característica), una capa oculta con \(9\) neuronas y una capa de salida con \(2\) neuronas (una para cada clase), todas completamente conectadas (Figura 6).
Figure 6: Architecture visualization
La red neuronal artificial tendrá un total de \(110\) parámetros: \(9\) para cada neurona de entrada conectada a la capa oculta, más \(9\) adicionales para la primera neurona de polarización asociada y \(2\) para cada una de las neuronas ocultas conectadas a la capa de salida, más \(3\) adicionales para la segunda neurona de sesgo asociada, es decir, \(9 \times 9 + 9 + 9 \times 2 + 2 = 110\).
Se comienza alterando ligeramente la base de datos del diagnóstico, cambiando el nombre, escalando las características y convirtiendo las etiquetas de los caracteres a variables numéricas.
set.seed(265509)
nn_dat <- BCrec4 %>%
mutate(bare_nuclei = scale(Bare.nuclei),
bl_cromatin = scale(Bl.cromatin),
cell_shape = scale(Cell.shape),
cell_size = scale(Cell.size),
cl_thickness = scale(Cl.thickness),
epith_c_size = scale(Epith.c.size),
marg_adhesion = scale(Marg.adhesion),
mitoses = scale(Mitoses),
normal_nucleoli = scale(Normal.nucleoli),
class_label = as.numeric(Class)-1 ) %>%
select(bare_nuclei, bl_cromatin, cell_shape,
cell_size,cl_thickness,epith_c_size,marg_adhesion,
mitoses,normal_nucleoli, class_label)
nn_dat %>% head()
## # A tibble: 6 x 10
## bare_nuclei[,1] bl_cromatin[,1] cell_shape[,1] cell_size[,1] cl_thickness[,1]
## <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 -0.698 -0.182 -0.741 -0.702 0.198
## 2 1.77 -0.182 0.263 0.277 0.198
## 3 -0.424 -0.182 -0.741 -0.702 -0.511
## 4 0.125 -0.182 1.60 1.58 0.552
## 5 -0.698 -0.182 -0.741 -0.702 -0.157
## 6 1.77 2.27 2.27 2.23 1.26
## # … with 5 more variables: epith_c_size <dbl[,1]>, marg_adhesion <dbl[,1]>,
## # mitoses <dbl[,1]>, normal_nucleoli <dbl[,1]>, class_label <dbl>
Luego, se crean índices para dividir los datos del diagnóstico en un conjunto de entrenamiento y de prueba. Se seja de lado al \(20\%\) de los datos para realizar pruebas.
set.seed(364)
n <- nrow(nn_dat)
n
## [1] 683
BCrec_parts <- nn_dat %>%
initial_split(prop = 0.8)
train <- BCrec_parts %>%
training()
test <- BCrec_parts %>%
testing()
list(train, test) %>%
map_int(nrow)
## [1] 546 137
n_total_samples <- nrow(nn_dat)
n_train_samples <- nrow(train)
n_test_samples <- nrow(test)
Se debe tener en cuenta que las funciones de la librería keras
esperan que los datos estén en una matriz y no en una tibble. Entonces as.matrix()
se agrega al final de cada línea.
x_train <- train %>% select(-class_label) %>% as.matrix()
y_train <- train %>% select(class_label) %>% as.matrix() %>% to_categorical()
x_test <- test %>% select(-class_label) %>% as.matrix()
y_test <- test %>% select(class_label) %>% as.matrix() %>% to_categorical()
dim(y_train)
## [1] 546 2
dim(y_test)
## [1] 137 2
Con los datos en su lugar, ahora se configura la arquitectura de esta red neuronal.
model <- keras_model_sequential()
model %>%
layer_dense(units = 9, activation = 'relu', input_shape = 9) %>%
layer_dense(units = 2, activation = 'sigmoid')
model %>% summary
## Model: "sequential"
## ________________________________________________________________________________
## Layer (type) Output Shape Param #
## ================================================================================
## dense_1 (Dense) (None, 9) 90
## ________________________________________________________________________________
## dense (Dense) (None, 2) 20
## ================================================================================
## Total params: 110
## Trainable params: 110
## Non-trainable params: 0
## ________________________________________________________________________________
A continuación, se debe compilar la arquitectura establecida en el modelo.
model %>% compile(
loss = 'categorical_crossentropy',
optimizer = optimizer_rmsprop(),
metrics = c('accuracy')
)
Por último, se ajusta el modelo y se guarda el progreso del entrenamiento en el objeto history
. La Figura 7 muestra la visualización de este objeto.
history <- model %>% fit(
x = x_train, y = y_train,
epochs = 200,
batch_size = 20,
validation_split = 0.2
)
plot(history) +
ggtitle("Training a neural network based classifier on the breast cancer data set") +
theme_bw()
Figure 7: Visualization of the training progress
El rendimiento final se puede obtener así:
perf <- model %>% evaluate(x_test, y_test)
print(perf)
## loss accuracy
## 0.04042205 0.98540145
Para la siguiente gráfica (Figura 8), los valores predichos y verdaderos deben estar en un vector. Se debe tener en cuenta que los valores verdaderos deben desenlistarse antes de colocarlos en un vector numérico. También se muestra la matriz de confusión construida con gmodels (Warnes et al. 2018), pues es una herramienta que maneja varias herramientas para ajustar modelos.
classes <- BCrec4 %>% pull(Class) %>% unique()
y_pred <- model %>% predict_classes(x_test)
y_true <- test %>% select(class_label) %>% unlist() %>% as.numeric()
tibble(y_true = classes[y_true + 1], y_pred = classes[y_pred + 1],
Correct = ifelse(y_true == y_pred, "Yes", "No") %>% factor) %>%
ggplot(aes(x = y_true, y = y_pred, colour = Correct)) +
geom_jitter() +
theme_bw() +
ggtitle(label = "Classification Performance of Artificial Neural Network",
subtitle = str_c("Accuracy = ",round(perf[2],3)*100,"%")) +
xlab(label = "True diagnosis class") +
ylab(label = "Predicted diagnosis class")
Figure 8: Confusion matrix plolt of predicted vs true values
library(gmodels)
CrossTable(y_pred, y_true,
prop.chisq = FALSE, prop.t = FALSE, prop.r = FALSE,
dnn = c('predicted', 'actual'))
##
##
## Cell Contents
## |-------------------------|
## | N |
## | N / Col Total |
## |-------------------------|
##
##
## Total Observations in Table: 137
##
##
## | actual
## predicted | 0 | 1 | Row Total |
## -------------|-----------|-----------|-----------|
## 0 | 76 | 0 | 76 |
## | 0.974 | 0.000 | |
## -------------|-----------|-----------|-----------|
## 1 | 2 | 59 | 61 |
## | 0.026 | 1.000 | |
## -------------|-----------|-----------|-----------|
## Column Total | 78 | 59 | 137 |
## | 0.569 | 0.431 | |
## -------------|-----------|-----------|-----------|
##
##
Se ha ilustrado lo fácil que es comenzar a construir una red neuronal artificial usando Keras
y TensorFlow
en R
. Con relativa facilidad, se crea un predictor de \(2\) clases con una precisión del \(99\%\). Este fue un ejemplo mínimo básico. La red se puede expandir para crear redes de aprendizaje profundo y también está disponible toda la API de TensorFlow
.
Por último se retoma el ejemplo de reconocer dígitos escritos a mano del conjunto de datos MNIST.
La base de datos MNIST se incluye con Keras y se puede acceder a él mediante la función dataset_mnist()
. Aquí se carga el conjunto de datos y luego se crean variables para prueba y entrenamiento:
mnist <- dataset_mnist()
x_train <- mnist$train$x
y_train <- mnist$train$y
x_test <- mnist$test$x
y_test <- mnist$test$y
Los datos x
son una matriz tridimensional (imágenes, ancho, alto) de valores de escala de grises. Para preparar los datos para el entrenamiento, se convierten las matrices \(3D\) en matrices remodelando el ancho y la altura en una sola dimensión (las imágenes de \(28 \times 28\) se aplanan en \(784\) vectores de longitud). Luego, se convierten los valores de escala de grises de números enteros que oscilan entre \(0\) y \(255\) en valores de punto flotante que oscilan entre \(0\) y \(1\):
# reshape
x_train <- array_reshape(x_train, c(nrow(x_train), 784))
x_test <- array_reshape(x_test, c(nrow(x_test), 784))
# escalar
x_train <- x_train / 255
x_test <- x_test / 255
Se tiene en cuenta que se usa la función array_reshape()
en lugar de la función dim <- ()
para remodelar la matriz. Esto es para que los datos se reinterpreten utilizando la semántica de filas principales (a diferencia de la semántica de columnas principales predeterminada de R
), que a su vez es compatible con la forma en que las bibliotecas numéricas llamadas por Keras
interpretan las dimensiones de la matriz.
Los datos y
son un vector entero con valores que van de \(0\) a \(9\). Para preparar estos datos para el entrenamiento, se codifican los vectores en matrices de clases binarias usando la función to_categorical()
, con la codificación one-hot (se describe la variable dependiente como una matriz).
y_train <- to_categorical(y_train, 10)
y_test <- to_categorical(y_test, 10)
La estructura de datos central de Keras
es un modelo, una forma de organizar capas. El tipo de modelo más simple es el modelo secuencial, una pila lineal de capas.
Se comienza creando un modelo secuencial y luego agregando capas usando el operador pipe:
model <- keras_model_sequential()
model %>%
layer_dense(units = 256, activation = 'relu', input_shape = c(784)) %>%
layer_dropout(rate = 0.4) %>%
layer_dense(units = 128, activation = 'relu') %>%
layer_dropout(rate = 0.3) %>%
layer_dense(units = 10, activation = 'softmax')
El argumento input_shape
de la primera capa especifica la forma de los datos de entrada (un vector numérico de longitud \(784\) que representa una imagen en escala de grises). La capa final genera un vector numérico de longitud 10 (probabilidades para cada dígito) usando una función de activación softmax
.
Utilizando la función de summary()
, se imprimen los detalles del modelo:
summary(model)
## Model: "sequential_1"
## ________________________________________________________________________________
## Layer (type) Output Shape Param #
## ================================================================================
## dense_4 (Dense) (None, 256) 200960
## ________________________________________________________________________________
## dropout_1 (Dropout) (None, 256) 0
## ________________________________________________________________________________
## dense_3 (Dense) (None, 128) 32896
## ________________________________________________________________________________
## dropout (Dropout) (None, 128) 0
## ________________________________________________________________________________
## dense_2 (Dense) (None, 10) 1290
## ================================================================================
## Total params: 235,146
## Trainable params: 235,146
## Non-trainable params: 0
## ________________________________________________________________________________
A continuación, se compila el modelo con la función de pérdida, el optimizador y las métricas adecuadas:
model %>% compile(
loss = 'categorical_crossentropy',
optimizer = optimizer_rmsprop(),
metrics = c('accuracy')
)
Se utiliza la función fit()
para entrenar el modelo durante \(30\) épocas, utilizando lotes de \(128\) imágenes:
history <- model %>% fit(
x_train, y_train,
epochs = 30, batch_size = 128,
validation_split = 0.2
)
El objeto history
devuelto por fit()
incluye métricas de pérdida y precisión, que se muestran en la Figura 9.
plot(history)
Figure 9: Loss and accuracy metrics
Se evalúa el rendimiento del modelo en los datos de prueba:
model %>% evaluate(x_test, y_test)
## loss accuracy
## 0.1005122 0.9820000
Y se generan predicciones sobre nuevos datos:
model %>% predict_classes(x_test)
## [1] 7 2 1 0 4 1 4 9 5 9 0 6 9 0 1 5 9 7 3 4 9 6 6 5 4 0 7 4 0 1 3 1 3 4 7 2
## [37] 7 1 2 1 1 7 4 2 3 5 1 2 4 4 6 3 5 5 6 0 4 1 9 5 7 8 9 3 7 4 6 4 3 0 7 0
## [73] 2 9 1 7 3 2 9 7 7 6 2 7 8 4 7 3 6 1 3 6 9 3 1 4 1 7 6 9 6 0 5 4 9 9 2 1
## [109] 9 4 8 7 3 9 7 4 4 4 9 2 5 4 7 6 7 9 0 5 8 5 6 6 5 7 8 1 0 1 6 4 6 7 3 1
## [145] 7 1 8 2 0 2 9 8 5 5 1 5 6 0 3 4 4 6 5 4 6 5 4 5 1 4 4 7 2 3 2 7 1 8 1 8
## [181] 1 8 5 0 8 9 2 5 0 1 1 1 0 9 0 3 1 6 4 2 3 6 1 1 1 3 9 5 2 9 4 5 9 3 9 0
## [217] 3 6 5 5 7 2 2 7 1 2 8 4 1 7 3 3 8 8 7 9 2 2 4 1 5 9 8 7 2 3 0 6 4 2 4 1
## [253] 9 5 7 7 2 8 2 6 8 5 7 7 9 1 8 1 8 0 3 0 1 9 9 4 1 8 2 1 2 9 7 5 9 2 6 4
## [289] 1 5 8 2 9 2 0 4 0 0 2 8 4 7 1 2 4 0 2 7 4 3 3 0 0 3 1 9 6 5 2 5 9 7 9 3
## [325] 0 4 2 0 7 1 1 2 1 5 3 3 9 7 8 6 5 6 1 3 8 1 0 5 1 3 1 5 5 6 1 8 5 1 7 9
## [361] 4 6 2 2 5 0 6 5 6 3 7 2 0 8 8 5 4 1 1 4 0 3 3 7 6 1 6 2 1 9 2 8 6 1 9 5
## [397] 2 5 4 4 2 8 3 8 2 4 5 0 3 1 7 7 5 7 9 7 1 9 2 1 4 2 9 2 0 4 9 1 4 8 1 8
## [433] 4 5 9 8 8 3 7 6 0 0 3 0 2 0 6 4 9 3 3 3 2 3 9 1 2 6 8 0 5 6 6 6 3 8 8 2
## [469] 7 5 8 9 6 1 8 4 1 2 5 9 1 9 7 5 4 0 8 9 9 1 0 5 2 3 7 0 9 4 0 6 3 9 5 2
## [505] 1 3 1 3 6 5 7 4 2 2 6 3 2 6 5 4 8 9 7 1 3 0 3 8 3 1 9 3 4 4 6 4 2 1 8 2
## [541] 5 4 8 8 4 0 0 2 3 2 7 7 0 8 7 4 4 7 9 6 9 0 9 8 0 4 6 0 6 3 5 4 8 3 3 9
## [577] 3 3 7 7 8 0 2 2 1 7 0 6 5 4 3 8 0 9 6 3 8 0 9 9 6 8 6 8 5 7 8 6 0 2 4 0
## [613] 2 2 3 1 9 7 5 1 0 8 4 6 2 6 7 9 3 2 9 8 2 2 9 2 7 3 5 9 1 8 0 2 0 5 2 1
## [649] 3 7 6 7 1 2 5 8 0 3 7 2 4 0 9 1 8 6 7 7 4 3 4 9 1 9 5 1 7 3 9 7 6 9 1 3
## [685] 3 8 3 3 6 7 2 4 5 8 5 1 1 4 4 3 1 0 7 7 0 7 9 4 4 8 5 5 4 0 8 2 1 0 8 4
## [721] 8 0 4 0 6 1 9 3 2 6 7 2 6 9 3 1 4 6 2 5 9 2 0 6 2 1 7 3 4 1 0 5 4 3 1 1
## [757] 7 4 9 9 4 8 4 0 2 4 5 1 1 6 4 7 1 9 4 2 4 1 5 5 3 8 3 1 4 5 6 8 9 4 1 5
## [793] 3 8 0 3 2 5 1 2 8 3 4 4 0 8 8 3 3 1 2 3 5 9 6 3 2 6 1 3 6 0 7 2 1 7 1 4
## [829] 2 4 2 1 7 9 6 1 1 2 4 8 1 7 7 4 8 0 7 3 1 3 1 0 7 7 0 3 5 5 2 7 6 6 9 2
## [865] 8 3 5 2 2 5 6 0 8 2 9 2 8 8 8 8 7 4 9 3 0 6 6 3 2 1 3 2 2 9 3 0 0 5 7 8
## [901] 3 4 4 6 0 2 9 1 4 7 4 7 3 9 8 8 4 7 1 2 1 2 2 3 2 3 2 3 9 1 7 4 0 3 5 5
## [937] 8 6 3 2 6 7 6 6 3 2 7 9 1 1 7 5 6 4 9 5 1 3 3 4 7 8 9 1 1 0 9 1 4 4 5 4
## [973] 0 6 2 2 3 1 5 1 2 0 3 8 1 2 6 7 1 6 2 3 9 0 1 2 2 0 8 9 9 0 2 5 1 9 7 8
## [1009] 1 0 4 1 7 9 5 4 2 6 8 1 3 7 5 4 4 1 8 1 3 8 1 2 5 8 0 6 2 1 1 2 1 5 3 4
## [1045] 6 9 5 0 9 2 2 4 8 2 1 7 2 4 9 4 4 0 3 9 2 2 3 3 8 3 5 7 3 5 8 1 2 4 4 6
## [1081] 4 9 5 1 0 6 9 5 9 5 9 7 3 8 0 3 7 1 3 6 7 8 5 9 7 9 6 9 6 3 7 4 6 5 3 5
## [1117] 4 7 8 7 8 0 7 6 8 8 7 3 3 1 9 5 2 7 3 5 1 1 2 1 4 7 4 7 5 4 5 4 0 8 3 6
## [1153] 9 6 0 2 7 4 4 4 4 6 6 4 7 9 3 4 5 5 8 7 3 7 2 7 0 2 4 1 1 1 6 9 2 8 7 2
## [1189] 0 1 5 0 9 1 7 0 6 0 8 6 8 1 8 0 3 3 7 2 3 6 2 1 6 1 1 3 7 9 0 8 0 5 4 0
## [1225] 2 8 2 2 9 8 4 0 9 5 8 5 1 2 1 3 1 7 9 5 7 2 0 5 8 8 6 2 5 4 1 9 2 1 5 8
## [1261] 1 0 2 4 4 3 6 8 8 2 4 0 5 0 4 4 7 9 3 4 1 5 9 7 3 5 8 8 0 3 3 3 6 6 0 1
## [1297] 6 0 3 5 4 4 1 2 9 1 4 6 9 9 3 9 8 4 4 3 1 3 1 3 8 7 9 4 8 8 7 9 9 1 4 5
## [1333] 6 0 5 2 2 2 1 5 5 2 4 9 6 2 7 7 2 2 1 1 2 8 3 7 2 4 1 7 1 7 6 7 8 2 7 3
## [1369] 1 7 5 8 2 6 2 2 5 6 6 0 9 2 4 3 3 9 7 6 6 8 0 4 1 3 8 2 9 1 8 0 6 7 2 1
## [1405] 0 5 5 2 0 2 2 0 2 4 9 8 0 9 9 4 6 5 4 9 1 8 3 4 9 9 1 2 2 8 1 9 6 4 0 9
## [1441] 4 8 3 8 6 0 2 5 1 9 6 2 9 4 0 9 6 0 6 2 5 4 2 3 8 4 5 5 0 3 8 5 3 5 8 6
## [1477] 5 7 6 3 3 9 6 1 1 2 9 0 4 3 3 6 9 5 9 3 7 7 7 8 3 9 8 3 0 7 2 7 9 4 5 4
## [1513] 9 3 2 1 4 0 2 3 7 5 9 8 8 5 0 1 1 4 7 3 9 0 0 0 6 6 2 3 7 8 4 7 7 9 2 4
## [1549] 1 6 5 2 4 9 9 1 8 4 0 9 8 4 8 7 7 0 7 8 8 6 0 4 8 8 2 4 7 6 6 6 4 7 1 8
## [1585] 8 2 3 6 3 0 0 3 7 6 9 7 9 9 5 4 3 3 6 1 2 3 7 3 3 6 0 5 3 8 4 3 6 3 5 0
## [1621] 2 0 9 0 7 4 6 9 3 5 1 9 6 1 4 5 4 5 0 5 9 5 2 1 2 9 1 9 9 4 0 8 4 5 2 9
## [1657] 2 1 2 1 7 3 6 8 8 4 9 1 9 8 5 7 5 1 1 8 6 5 2 4 4 7 2 3 5 6 8 8 6 2 3 1
## [1693] 0 5 8 9 2 9 6 7 0 4 8 7 1 7 4 1 0 3 7 2 0 0 9 1 7 8 7 8 4 7 2 0 4 6 0 3
## [1729] 1 1 3 3 9 6 7 4 1 5 3 0 8 7 3 9 6 9 3 5 0 2 7 2 5 1 2 5 8 0 8 8 1 5 0 3
## [1765] 0 3 1 4 0 3 7 2 7 1 8 0 7 0 4 3 1 9 8 7 7 1 4 9 9 3 2 1 7 9 0 2 0 3 3 7
## [1801] 4 9 2 3 3 7 7 0 0 7 5 2 9 8 7 4 4 2 6 6 1 9 6 8 2 9 0 8 3 1 1 6 3 5 1 1
## [1837] 1 3 1 2 3 0 2 0 1 3 5 5 7 4 8 9 6 9 6 8 3 6 6 8 5 1 4 2 4 4 5 1 1 9 0 2
## [1873] 4 9 5 7 1 8 3 5 6 9 8 7 1 1 6 7 6 3 2 2 0 8 9 2 5 1 0 8 1 4 5 7 9 6 9 0
## [1909] 6 1 5 5 8 3 8 2 6 5 0 7 4 6 1 3 4 7 3 2 3 4 2 5 2 7 1 7 2 6 4 1 5 7 8 6
## [1945] 0 1 8 2 5 7 7 6 9 3 5 8 4 2 4 0 8 8 3 4 9 2 7 5 8 6 5 6 0 8 6 7 3 6 4 9
## [1981] 4 6 6 3 0 4 1 0 1 4 6 2 9 1 1 0 6 3 9 5 6 5 6 5 9 4 6 4 3 9 1 3 4 1 9 1
## [2017] 2 1 1 9 3 5 4 0 9 3 6 1 7 5 5 3 3 4 1 5 7 5 8 6 5 1 0 8 2 3 4 6 7 9 8 1
## [2053] 8 9 9 2 8 6 2 7 0 0 6 7 5 8 6 0 9 3 9 1 3 5 4 3 3 5 5 6 3 0 2 3 4 2 3 0
## [2089] 9 9 4 7 2 8 4 7 0 6 2 8 5 2 8 5 7 3 0 8 2 7 2 8 2 5 5 7 6 4 6 8 4 8 2 7
## [2125] 4 5 2 0 3 9 9 6 7 2 5 1 1 1 2 3 6 7 8 7 6 4 8 9 4 8 6 3 8 3 1 0 6 2 2 5
## [2161] 6 9 5 8 1 4 1 7 8 4 6 1 8 4 3 1 2 8 0 8 5 9 1 4 2 0 2 7 0 9 0 2 5 7 6 7
## [2197] 9 4 2 6 2 4 4 8 0 4 4 5 8 0 6 8 9 8 5 6 9 0 4 8 7 1 3 4 6 8 0 9 1 3 3 6
## [2233] 9 8 7 1 0 5 7 1 7 5 2 7 9 1 8 5 2 4 9 4 7 2 2 3 4 9 1 9 2 1 7 9 4 4 1 6
## [2269] 7 2 7 8 8 1 9 7 1 1 7 5 3 3 5 1 3 7 6 1 3 8 7 5 9 0 0 0 2 8 8 2 3 7 1 3
## [2305] 0 3 4 4 3 8 9 2 3 9 7 1 1 7 0 4 9 6 5 9 1 7 0 2 0 2 4 6 7 0 7 1 4 6 4 5
## [2341] 4 9 9 1 7 9 5 3 3 8 2 3 6 2 2 1 1 1 1 1 6 9 8 4 3 7 1 6 4 5 0 4 7 4 2 4
## [2377] 0 7 0 1 9 8 8 6 0 0 4 1 6 8 2 2 3 8 4 8 2 2 1 7 5 4 4 0 4 3 4 7 3 1 0 1
## [2413] 2 5 9 2 1 0 1 8 9 1 4 8 3 8 9 3 6 2 8 3 2 2 1 0 4 2 9 2 4 3 7 9 1 5 2 9
## [2449] 9 0 3 8 5 3 6 0 9 4 6 2 5 0 0 7 4 6 6 8 6 6 8 6 9 1 7 2 5 9 9 0 7 2 7 6
## [2485] 7 0 6 5 4 4 7 2 0 9 9 2 2 9 4 4 2 3 3 2 1 7 0 7 6 4 1 3 8 7 4 5 9 2 5 1
## [2521] 8 7 3 7 1 5 5 0 9 1 4 0 6 3 3 6 0 4 9 7 5 1 6 8 9 5 5 7 9 3 8 3 8 1 5 3
## [2557] 5 0 5 5 3 8 6 7 7 7 3 7 0 5 9 0 2 5 5 3 1 7 7 8 6 5 9 3 8 9 5 3 7 9 1 7
## [2593] 0 0 3 7 2 3 8 1 8 6 2 9 5 7 5 7 8 6 2 5 1 4 8 4 5 8 3 0 6 2 7 3 3 2 1 0
## [2629] 7 3 4 0 3 9 3 2 8 9 0 3 8 0 7 6 5 4 7 3 0 0 8 6 2 5 1 1 0 0 4 4 0 1 2 3
## [2665] 2 7 7 8 5 2 5 7 6 9 1 4 1 6 4 2 4 3 5 4 3 9 5 0 1 5 3 8 9 1 9 7 9 5 5 2
## [2701] 7 4 6 0 1 1 1 0 4 4 7 6 3 0 0 4 3 0 6 1 4 6 1 3 8 1 2 5 6 2 7 3 6 0 1 9
## [2737] 7 6 6 8 9 2 9 5 8 3 1 0 0 7 6 6 2 1 6 9 3 1 8 6 9 0 6 0 0 0 6 3 5 9 3 4
## [2773] 5 5 8 5 3 0 4 0 2 9 6 8 2 3 1 2 1 1 5 6 9 8 0 6 6 5 5 3 8 6 2 1 4 5 4 3
## [2809] 7 8 5 0 9 3 5 1 1 0 4 4 7 0 1 7 0 1 6 1 4 5 6 6 5 7 8 4 4 7 2 5 3 7 0 7
## [2845] 7 9 6 4 2 8 5 7 8 3 9 5 8 9 9 8 6 2 8 9 2 3 6 1 1 8 9 3 4 0 7 9 6 7 1 4
## [2881] 1 3 4 9 3 1 4 7 7 4 7 2 9 3 0 8 8 8 4 0 4 4 1 5 2 8 3 4 9 5 2 8 1 5 3 7
## [2917] 9 4 2 5 6 2 5 9 3 5 9 2 1 9 5 3 0 6 9 8 4 0 4 7 2 9 0 1 0 3 1 6 5 8 1 5
## [2953] 3 5 0 3 5 5 9 2 8 7 0 4 9 1 9 7 7 5 5 2 0 9 1 8 6 2 3 9 6 2 1 9 1 3 5 5
## [2989] 0 3 8 3 3 7 6 8 0 1 4 0 6 9 8 1 2 9 9 5 9 7 3 7 8 0 1 3 0 4 6 1 0 2 5 8
## [3025] 4 4 1 1 5 4 6 6 0 6 9 2 6 2 7 1 7 9 4 0 0 3 8 2 2 3 1 6 0 5 7 7 9 2 6 7
## [3061] 9 7 5 6 8 8 4 6 8 4 1 2 8 2 3 9 4 0 3 7 3 2 3 3 7 3 4 0 6 2 0 8 1 5 3 5
## [3097] 4 1 7 1 5 7 5 7 3 2 2 7 3 7 3 7 8 5 4 5 2 9 6 5 3 6 7 4 1 7 1 5 2 3 6 3
## [3133] 1 4 2 6 7 4 3 8 0 6 2 1 6 5 3 9 1 9 3 2 1 8 4 4 6 5 8 6 9 7 7 8 6 9 7 3
## [3169] 9 4 0 5 4 6 4 1 2 3 0 0 2 6 6 5 7 0 8 6 4 7 9 0 7 3 4 2 1 8 8 5 9 2 7 1
## [3205] 8 8 8 2 7 6 0 1 2 7 1 0 8 3 6 0 5 3 6 2 8 9 0 1 4 2 1 1 4 4 4 4 7 1 6 2
## [3241] 9 9 0 0 1 8 8 4 3 4 2 0 6 1 6 1 2 2 2 1 2 3 7 8 1 0 0 2 1 6 6 0 1 6 2 5
## [3277] 1 7 4 8 2 1 4 3 8 3 9 9 4 9 3 4 7 2 7 5 7 0 4 3 3 2 6 7 6 0 0 6 7 7 0 5
## [3313] 5 8 1 0 7 0 2 8 1 5 0 8 8 0 3 2 7 7 2 6 4 7 5 5 7 2 9 2 8 4 6 8 6 5 0 0
## [3349] 8 7 6 1 7 1 1 2 7 4 0 0 7 7 6 3 8 6 4 2 0 9 4 0 5 7 8 2 7 4 7 1 1 3 6 6
## [3385] 2 9 1 9 4 8 3 6 9 5 9 6 2 4 6 7 7 0 6 6 9 4 8 3 5 3 4 9 0 0 5 2 5 0 7 1
## [3421] 1 1 0 7 6 7 9 6 6 4 1 4 3 1 1 2 2 4 1 0 8 7 6 3 4 0 0 6 3 3 0 9 1 7 1 1
## [3457] 3 1 0 9 9 7 5 4 1 4 8 9 5 3 5 1 9 8 2 3 3 9 9 0 1 0 2 9 3 9 3 3 6 2 9 9
## [3493] 8 3 7 4 0 4 7 8 4 9 8 1 9 7 5 9 2 8 2 2 0 2 2 3 8 4 6 8 4 8 2 4 6 7 9 3
## [3529] 3 9 4 3 1 4 4 7 0 5 9 6 0 4 4 4 4 6 1 2 3 2 6 4 5 9 6 8 5 6 0 5 6 4 1 8
## [3565] 6 5 2 5 4 5 5 4 7 7 0 7 8 2 2 3 7 0 1 8 0 7 1 9 8 7 5 5 9 1 7 5 4 9 1 2
## [3601] 2 1 6 6 7 1 1 4 0 7 4 2 4 0 6 4 7 6 9 5 3 4 6 5 0 1 8 8 2 8 3 5 7 8 0 8
## [3637] 5 7 1 1 0 1 3 7 8 5 0 7 1 1 0 1 1 4 5 2 7 6 2 3 0 2 8 5 9 6 9 7 2 1 3 6
## [3673] 4 1 8 2 4 0 5 1 0 3 2 6 4 4 3 9 6 1 6 5 7 9 2 0 2 6 0 1 4 3 5 2 8 8 0 8
## [3709] 8 9 0 9 6 7 6 3 9 3 4 7 7 7 4 9 0 6 4 4 4 2 7 2 8 1 0 0 7 8 3 3 3 1 3 7
## [3745] 6 1 3 1 6 6 5 2 4 7 5 9 5 8 4 9 9 1 6 5 0 1 3 7 0 3 4 8 2 2 0 2 8 1 5 1
## [3781] 6 8 8 9 1 2 1 3 5 1 0 9 4 4 8 3 2 5 9 7 6 6 2 0 0 0 5 8 3 1 5 2 3 8 5 1
## [3817] 8 2 0 4 9 9 6 2 3 3 5 6 4 8 0 9 2 8 3 6 7 5 7 2 9 4 9 1 2 8 6 0 7 0 9 1
## [3853] 1 5 7 5 9 9 1 9 5 9 2 5 0 4 1 0 8 9 0 8 9 8 9 4 2 5 7 9 8 9 8 0 9 9 6 8
## [3889] 9 9 5 9 8 6 1 0 3 3 5 2 1 6 5 0 2 8 2 5 6 2 3 0 2 2 6 4 3 5 5 1 7 2 1 6
## [3925] 9 1 9 9 5 5 1 6 2 2 8 6 7 1 4 6 0 6 0 5 3 2 2 3 6 8 9 8 5 3 8 5 4 5 2 0
## [3961] 5 6 3 2 8 3 9 9 5 7 9 4 6 7 1 3 1 3 6 6 0 9 0 1 9 9 2 8 8 0 1 6 9 7 5 3
## [3997] 4 7 4 9 9 4 3 6 3 1 1 7 6 9 1 8 4 1 1 9 9 4 3 6 8 1 6 0 4 1 3 7 7 4 9 5
## [4033] 1 0 0 1 1 6 2 1 9 8 4 0 3 6 4 9 0 7 1 6 5 7 5 2 5 1 8 5 4 7 0 6 7 9 2 5
## [4069] 8 1 0 4 5 7 1 8 5 1 9 0 0 6 0 7 3 1 8 3 9 7 0 0 8 9 5 9 8 3 2 7 2 9 7 2
## [4105] 1 1 3 7 5 3 1 9 8 2 2 2 8 8 5 7 3 8 9 8 8 6 8 2 3 9 7 5 6 2 9 2 8 8 1 6
## [4141] 2 8 7 9 1 8 0 1 7 2 0 7 5 1 9 0 2 0 9 8 6 2 3 0 3 8 0 2 1 1 1 1 4 2 9 7
## [4177] 7 5 1 1 2 1 9 9 9 1 0 2 0 2 1 1 4 6 4 1 5 4 9 9 7 1 5 6 2 2 2 8 0 6 9 6
## [4213] 1 9 7 7 1 4 8 5 3 4 3 4 7 7 5 0 7 4 8 8 1 5 3 9 5 9 7 6 9 0 3 6 3 9 8 2
## [4249] 8 1 2 8 6 8 5 5 3 9 4 9 2 5 1 5 1 4 4 1 4 4 3 5 9 1 2 2 3 3 0 2 9 0 0 9
## [4285] 9 6 0 9 3 7 8 4 1 9 9 7 2 7 9 9 5 9 5 1 1 8 3 5 1 9 5 3 5 4 9 5 9 3 1 9
## [4321] 0 9 7 5 4 9 2 0 1 0 5 1 4 9 3 3 6 1 5 2 5 2 2 0 9 2 6 6 0 1 2 0 3 0 2 5
## [4357] 5 7 9 5 3 0 8 9 5 0 3 2 5 4 0 8 8 4 5 8 8 4 5 4 8 5 4 9 2 2 1 2 6 8 8 7
## [4393] 0 3 6 6 4 3 8 8 7 2 2 0 0 9 3 9 9 1 9 8 6 6 4 2 6 9 2 8 5 4 5 7 9 9 9 2
## [4429] 1 8 3 4 0 3 8 7 9 3 4 6 5 6 2 3 9 2 6 0 0 6 1 2 8 7 9 8 2 0 4 7 7 5 0 5
## [4465] 6 4 6 7 4 3 0 7 5 0 7 4 2 0 8 9 9 4 2 4 6 7 8 7 6 9 4 1 3 7 3 0 8 7 7 6
## [4501] 9 3 9 2 2 9 2 1 8 3 2 9 6 8 4 0 1 2 8 4 5 2 7 8 1 1 3 0 3 5 7 0 3 1 9 3
## [4537] 5 3 1 7 7 3 0 8 4 8 2 6 5 2 9 7 3 9 0 9 9 6 4 2 9 7 2 1 1 6 7 4 7 5 9 6
## [4573] 8 2 1 4 4 5 7 6 1 3 2 5 9 9 3 6 1 1 4 6 9 7 2 1 5 1 4 6 3 8 1 1 0 3 1 6
## [4609] 8 4 9 0 7 3 0 2 9 0 6 6 6 3 6 7 7 2 8 6 0 8 3 0 2 9 8 3 2 5 3 8 8 0 0 1
## [4645] 9 5 1 3 9 6 0 1 4 1 7 1 2 3 7 9 7 4 9 9 3 9 2 8 2 7 1 8 0 9 1 0 1 7 7 9
## [4681] 6 9 9 9 2 1 6 1 3 5 7 1 9 7 6 4 5 7 6 6 9 9 6 3 6 2 9 8 1 2 2 5 5 2 3 7
## [4717] 2 1 0 1 0 4 5 2 8 2 8 3 5 1 7 7 1 1 2 9 7 8 4 0 5 0 7 8 8 4 7 7 8 5 8 4
## [4753] 9 8 1 3 8 0 3 1 7 9 5 5 1 6 5 7 4 9 3 5 4 7 1 2 0 8 1 6 0 7 3 4 7 3 9 6
## [4789] 0 8 6 4 8 7 7 9 3 8 6 9 7 2 3 4 0 2 1 0 3 5 5 7 2 4 6 7 2 8 3 0 8 7 8 4
## [4825] 0 8 4 4 5 8 5 6 6 3 0 9 3 7 6 8 9 3 4 9 5 8 9 1 2 8 8 6 8 1 3 7 9 0 1 1
## [4861] 9 7 0 8 1 7 4 5 7 1 2 1 1 3 9 6 2 1 2 6 8 7 6 6 9 3 7 0 5 2 8 0 5 4 3 8
## [4897] 4 6 6 2 7 9 5 1 3 2 4 3 6 1 9 4 4 7 6 5 4 1 9 9 2 7 8 0 1 3 6 1 3 4 1 1
## [4933] 1 5 6 0 7 0 7 2 3 2 5 2 2 9 4 9 8 1 2 1 6 1 2 7 8 0 0 0 8 2 2 9 2 2 3 9
## [4969] 9 2 7 5 1 3 4 9 4 1 8 5 6 2 8 3 1 2 8 4 9 9 3 7 0 7 7 2 3 2 4 0 3 9 9 8
## [5005] 4 1 0 6 0 9 6 8 6 1 1 9 8 9 2 3 5 5 9 4 2 1 9 4 3 9 6 0 4 0 6 0 1 2 3 4
## [5041] 7 8 9 0 1 2 3 4 7 8 9 0 1 2 3 4 5 6 7 8 9 8 3 4 7 8 6 3 4 0 9 7 1 9 3 8
## [5077] 4 7 3 0 9 1 4 5 4 6 2 0 6 2 1 1 1 1 7 2 4 7 5 2 9 4 5 8 4 2 9 7 0 0 7 5
## [5113] 1 1 7 6 6 6 8 2 2 7 7 4 0 2 4 2 1 8 9 6 1 0 5 9 6 9 8 0 3 0 8 3 9 6 3 0
## [5149] 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 5 4 8 7 4 7 7 3 9 8
## [5185] 8 3 1 5 8 2 7 4 2 1 5 4 5 5 8 6 4 4 4 1 8 7 5 5 1 8 9 1 3 6 3 3 2 2 6 9
## [5221] 9 6 5 5 3 3 8 1 6 5 6 8 1 9 7 6 8 3 7 4 7 0 9 0 0 3 7 9 3 0 2 0 1 0 1 0
## [5257] 4 0 1 0 4 7 9 6 2 6 2 2 9 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
## [5293] 2 3 4 5 6 7 8 9 8 0 5 6 6 0 8 0 2 3 7 9 4 7 1 9 1 7 1 4 0 0 4 1 7 5 7 1
## [5329] 3 3 3 6 6 9 7 4 3 0 2 5 2 6 0 8 9 4 3 5 4 8 1 5 9 0 6 4 3 6 3 3 8 1 4 7
## [5365] 5 7 2 2 0 0 1 7 7 9 5 9 8 9 6 8 8 2 3 6 1 2 9 8 9 5 2 6 2 4 8 4 6 5 0 1
## [5401] 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 7 4 2 0 9 0 1 5 8 8 0
## [5437] 2 7 8 4 4 6 1 0 4 5 3 9 4 2 0 5 0 1 3 2 9 8 6 0 1 1 8 0 4 7 7 6 3 6 0 7
## [5473] 3 5 4 2 4 1 8 3 5 6 7 0 6 7 1 2 5 8 1 9 3 8 2 8 7 6 7 1 4 6 2 9 3 0 1 2
## [5509] 3 4 5 6 7 0 1 2 3 4 5 0 1 2 8 9 1 4 0 9 5 0 8 0 7 7 1 1 2 9 3 6 7 2 3 8
## [5545] 1 2 9 8 8 7 1 7 1 1 0 3 4 2 6 4 7 4 2 7 4 9 1 0 6 8 5 5 5 3 5 9 7 4 8 5
## [5581] 9 6 9 3 0 3 8 9 1 8 1 6 0 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2
## [5617] 3 4 5 6 7 8 9 3 5 3 2 9 3 2 1 4 5 5 2 3 2 1 3 9 7 2 8 2 8 9 1 8 8 7 8 1
## [5653] 0 0 7 7 8 7 5 0 6 1 5 7 4 6 1 2 5 0 7 9 9 0 3 8 2 4 8 1 8 6 5 9 0 0 0 3
## [5689] 7 1 6 4 2 6 6 0 4 5 4 1 3 8 6 3 9 9 5 9 3 7 8 5 6 4 7 6 2 2 0 9 4 0 1 2
## [5725] 3 4 5 6 7 8 9 0 1 2 7 5 6 0 1 2 3 4 5 6 8 7 1 3 2 8 0 7 5 9 9 6 0 9 4 1
## [5761] 3 2 1 2 3 8 3 2 6 5 6 8 2 7 4 8 1 8 0 5 3 9 4 1 9 2 1 9 6 7 9 0 4 6 1 7
## [5797] 3 8 7 2 9 6 5 8 3 9 0 5 7 1 6 1 0 9 3 3 4 4 0 6 2 5 4 2 3 4 6 0 0 2 0 1
## [5833] 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7 8 9 8 7 1 3 7 5 2 8 0 7 5
## [5869] 9 9 0 9 1 1 5 8 8 6 3 2 1 8 3 2 6 5 6 0 4 1 0 5 3 1 9 2 1 9 6 0 4 6 1 7
## [5905] 3 8 7 2 9 6 5 8 3 5 7 1 6 1 0 9 6 2 5 4 2 3 4 4 6 0 0 2 0 1 2 3 9 3 6 7
## [5941] 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 8 4 5 6 7 8 9 8 6 5 0 6 8 9 4 1 9 5 9 0 4
## [5977] 8 9 1 4 0 5 5 2 1 5 4 0 7 6 0 1 7 0 6 8 9 5 1 7 9 8 6 0 8 1 7 7 1 3 2 5
## [6013] 1 4 2 0 0 7 8 4 6 4 9 3 8 4 7 2 5 6 3 6 9 6 3 2 2 4 6 9 0 2 5 5 1 5 3 9
## [6049] 7 8 7 2 2 5 7 9 8 2 1 9 1 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
## [6085] 2 3 4 5 6 7 8 9 1 2 6 5 3 0 7 0 4 1 4 3 6 7 2 3 1 2 1 2 9 6 0 1 3 0 2 7
## [6121] 5 7 6 2 9 1 9 0 6 0 6 0 2 0 6 1 5 8 4 3 0 1 5 4 4 8 5 7 5 7 8 3 4 8 8 5
## [6157] 2 9 7 1 3 8 1 0 7 5 3 6 9 4 7 7 9 9 3 4 4 3 8 6 2 0 1 2 3 4 5 6 7 8 9 0
## [6193] 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 8 3 9 5 5 2 6 8 4 9 1 7 1 2 3 5
## [6229] 9 6 9 1 1 1 2 9 5 6 8 1 2 0 7 7 5 8 2 9 8 9 0 4 6 7 1 3 4 5 6 0 3 6 8 7
## [6265] 0 4 2 7 4 7 5 4 3 4 2 8 1 5 1 2 0 2 5 6 4 3 0 0 0 3 3 5 7 0 6 4 8 8 6 3
## [6301] 4 6 9 9 8 2 7 7 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 7
## [6337] 8 2 1 7 2 5 0 8 0 2 7 8 8 3 6 0 2 7 6 6 1 2 8 8 7 7 4 7 7 3 7 4 5 4 3 3
## [6373] 8 4 1 1 9 7 4 3 7 3 3 0 2 5 5 6 6 3 5 2 5 9 9 8 4 1 0 6 0 9 6 8 8 5 6 1
## [6409] 1 9 8 9 2 3 5 5 9 4 2 1 9 2 9 2 0 6 0 4 0 0 1 2 3 4 7 8 9 0 1 2 3 7 8 9
## [6445] 0 1 2 3 4 7 8 9 7 3 0 3 1 8 7 6 4 0 2 6 8 3 2 8 1 2 0 7 1 0 4 4 5 8 0 6
## [6481] 2 3 1 5 1 8 5 9 4 0 7 5 8 8 3 8 9 2 6 2 5 3 1 7 3 9 1 9 9 6 0 3 9 2 8 1
## [6517] 4 3 5 2 9 2 5 8 9 5 0 1 2 4 5 6 0 1 2 3 4 5 6 7 1 2 3 4 5 1 0 4 5 6 6 3
## [6553] 4 4 2 9 1 0 6 4 9 7 2 3 3 9 2 0 9 3 3 7 1 5 6 3 1 7 8 4 0 2 4 0 2 4 7 8
## [6589] 0 7 0 6 9 3 2 8 6 7 5 7 5 1 0 8 1 6 7 2 9 7 9 5 8 6 2 6 2 8 1 7 5 0 1 1
## [6625] 3 4 4 9 1 8 6 8 9 0 1 2 3 4 5 6 7 5 9 0 1 2 3 4 7 8 9 5 1 7 8 9 9 8 9 8
## [6661] 4 1 7 7 3 3 7 6 6 6 1 9 0 1 7 6 3 2 1 7 1 3 9 1 7 6 8 4 1 4 3 6 9 6 1 4
## [6697] 4 7 2 4 4 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 9 0 1 2 3 4 7 8 1 3 5 1 7 7
## [6733] 2 1 4 8 3 4 4 3 9 7 4 1 2 3 5 9 1 6 0 1 0 0 2 9 7 1 1 4 0 4 7 3 6 8 0 3
## [6769] 7 4 0 6 9 2 6 5 8 6 9 0 4 0 6 1 9 2 0 9 5 1 3 7 6 9 3 0 2 2 0 1 2 3 4 5
## [6805] 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 2 1 7 2 5 0 8 0 2 7 8 8
## [6841] 3 0 6 0 2 7 6 4 1 2 8 8 7 7 4 7 7 3 7 4 5 4 3 3 8 4 5 4 1 1 9 7 4 3 7 3
## [6877] 3 0 2 5 5 6 3 1 5 2 5 9 9 8 4 1 0 6 0 9 6 8 8 5 6 1 1 9 8 9 2 3 5 5 9 4
## [6913] 2 1 9 4 9 1 3 9 2 0 6 0 4 0 6 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
## [6949] 1 2 3 4 5 6 7 8 9 3 8 0 7 1 0 7 5 5 6 9 0 1 0 0 8 3 4 3 1 5 0 0 9 5 3 4
## [6985] 9 3 7 6 9 2 4 5 7 2 6 4 9 4 9 4 1 2 2 5 8 1 3 2 9 4 3 8 2 2 1 2 8 6 5 1
## [7021] 6 7 2 1 3 9 3 8 7 5 7 0 7 4 8 8 5 0 6 6 3 7 6 9 9 4 8 4 1 0 6 6 0 1 2 3
## [7057] 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 7 4 0 4 0 1 7 9 5 1
## [7093] 4 2 8 9 4 3 7 8 2 4 4 3 3 6 9 9 5 8 6 7 0 6 8 2 6 3 9 3 2 8 6 1 7 4 8 8
## [7129] 9 0 3 3 9 0 5 2 9 4 1 0 3 7 5 8 7 7 8 2 9 7 1 2 6 4 2 5 2 3 6 6 5 0 0 2
## [7165] 8 1 6 1 0 4 3 1 6 1 9 0 1 4 5 6 7 8 9 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 8 9
## [7201] 8 4 0 0 7 2 4 3 8 6 6 3 2 6 3 3 3 1 4 7 8 0 3 1 9 0 1 9 1 2 7 0 1 3 8 2
## [7237] 9 2 7 6 5 5 9 9 8 2 9 1 3 2 3 4 3 1 9 0 9 3 6 8 7 0 1 0 5 8 2 7 7 0 1 2
## [7273] 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 1 7 4 8 1 5 6 5 7
## [7309] 2 8 6 3 3 8 6 5 4 0 9 1 7 2 9 1 5 1 3 2 2 3 0 6 4 3 7 6 9 0 4 8 1 4 0 6
## [7345] 1 2 6 9 2 2 3 5 5 1 0 7 7 9 6 2 9 4 7 0 2 3 4 0 0 8 8 8 5 1 3 7 4 9 8 8
## [7381] 9 0 9 8 9 0 2 6 5 6 7 4 7 5 4 1 3 5 3 1 2 3 4 5 6 1 2 3 4 6 0 1 2 4 5 6
## [7417] 7 8 1 7 2 4 1 4 1 4 9 6 8 4 5 3 7 8 4 3 3 5 6 7 0 6 1 6 8 7 0 1 5 0 8 5
## [7453] 0 1 5 8 4 2 3 9 7 6 9 1 9 0 6 7 1 2 3 9 2 4 5 5 3 7 5 3 1 8 2 2 3 0 2 9
## [7489] 4 9 7 0 2 7 4 9 9 2 5 9 8 3 8 6 7 0 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7
## [7525] 8 9 0 1 2 3 4 5 6 7 8 9 0 0 7 2 6 5 5 3 7 8 6 6 6 6 4 3 8 8 3 0 1 9 0 5
## [7561] 4 1 9 1 2 7 0 1 3 8 2 9 2 7 4 2 6 5 5 9 9 1 1 5 7 6 8 2 9 4 3 1 9 0 9 3
## [7597] 6 8 7 0 1 0 5 8 2 7 7 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 8 9 0 1 2 3 4 5 6
## [7633] 7 8 9 2 1 2 1 3 9 9 8 5 3 7 0 7 7 5 7 9 9 4 7 0 3 4 1 5 8 1 4 8 4 1 8 6
## [7669] 6 4 6 0 5 5 3 3 5 7 2 5 9 6 9 2 6 2 1 2 0 8 3 8 3 0 8 7 4 9 5 0 9 7 0 0
## [7705] 4 6 0 9 1 6 2 7 6 8 3 5 2 1 8 3 8 6 1 0 2 1 4 0 1 2 3 4 5 6 7 8 9 0 1 2
## [7741] 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 7 6 4 7 6 2 3 4 8 7 8 6 9 8 3 2 2 8 4
## [7777] 8 5 6 5 0 2 0 1 1 2 9 6 8 2 1 0 6 5 2 9 7 5 3 9 2 7 1 8 3 8 1 9 5 5 0 1
## [7813] 1 9 8 2 6 0 4 5 0 3 1 8 6 7 5 9 9 3 0 3 1 4 4 0 4 9 0 1 2 3 5 6 7 8 0 1
## [7849] 2 3 5 6 7 8 9 0 8 2 3 5 6 7 8 9 9 7 0 9 0 1 5 8 8 0 9 3 2 7 8 4 6 1 0 4
## [7885] 9 4 2 0 5 0 1 6 9 3 2 9 1 6 0 8 1 8 7 7 6 3 6 0 7 2 4 1 7 0 6 7 1 2 5 8
## [7921] 1 2 2 8 7 6 8 7 8 6 2 9 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2
## [7957] 3 4 5 6 7 8 9 8 9 5 7 0 3 1 6 8 4 1 5 6 4 2 7 8 1 3 4 3 4 7 2 0 5 0 1 9
## [7993] 2 3 2 3 5 5 7 8 4 9 9 7 1 1 9 0 7 8 3 4 8 6 3 8 0 9 6 2 1 0 1 0 6 2 3 8
## [8029] 9 0 7 2 3 4 5 5 2 8 5 4 6 6 6 7 9 1 8 2 1 5 3 4 7 9 4 0 0 0 1 2 3 4 5 6
## [8065] 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 9 0 1 3 1 5 1 8 4 9 8 4 6 8 0 1
## [8101] 1 9 2 6 6 8 7 4 2 9 7 0 2 1 0 3 6 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8
## [8137] 9 0 1 2 3 4 5 6 7 8 9 8 6 5 9 7 0 2 3 4 3 8 5 1 5 2 3 0 1 2 1 3 2 6 5 3
## [8173] 0 7 2 7 4 6 4 0 5 9 9 8 9 5 3 1 7 4 7 6 5 4 0 0 6 6 2 0 6 3 7 7 4 4 3 9
## [8209] 2 8 9 6 0 9 5 3 8 8 7 1 4 0 4 8 5 2 3 9 0 1 9 1 5 1 7 4 8 6 2 1 6 8 8 0
## [8245] 1 2 3 4 7 8 9 0 1 2 3 4 6 7 8 9 0 1 2 3 4 7 8 9 1 4 5 3 3 0 9 5 4 9 0 8
## [8281] 4 6 7 0 7 7 1 6 9 1 3 6 2 3 8 2 3 8 9 5 8 8 7 1 7 1 1 0 3 4 2 4 4 7 4 2
## [8317] 2 4 2 9 2 7 9 2 1 6 6 5 3 4 8 5 9 6 9 0 6 3 0 8 1 6 0 0 1 2 3 4 5 6 7 0
## [8353] 1 2 3 4 7 8 9 0 1 2 3 4 7 2 5 1 6 4 3 9 9 0 9 7 1 6 4 3 6 2 0 9 8 6 5 7
## [8389] 0 0 1 7 4 3 2 4 1 3 7 6 4 7 7 7 9 8 4 3 6 2 8 3 5 8 0 5 4 7 1 3 1 7 9 6
## [8425] 2 0 9 1 7 3 3 9 1 6 4 3 9 8 2 1 8 6 4 1 5 5 6 5 0 1 2 3 4 5 6 7 8 9 0 1
## [8461] 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 6 9 7 0 2 3 4 3 8 5 1 3 0 1 2 1 3 2
## [8497] 0 7 2 6 4 0 5 9 9 8 9 5 3 1 7 4 7 0 0 6 6 6 3 7 4 2 8 9 8 7 1 9 0 4 8 5
## [8533] 2 3 9 0 1 9 1 5 1 7 6 1 2 1 6 8 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 0
## [8569] 1 2 3 5 6 7 8 1 0 4 5 6 6 3 4 4 2 8 1 0 6 4 9 7 2 9 2 0 9 3 3 9 1 5 2 3
## [8605] 1 6 7 3 7 8 4 0 2 4 0 2 4 7 8 0 7 0 6 9 3 2 4 8 6 0 5 7 5 1 0 8 1 6 7 2
## [8641] 9 7 9 5 6 5 2 6 2 8 1 7 5 5 7 3 5 0 1 1 3 8 4 9 4 5 1 8 6 8 9 0 1 2 3 4
## [8677] 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 3 5 3 2 9 3 2 1 4 5 5
## [8713] 2 3 2 1 3 9 7 2 1 2 8 9 1 8 8 7 8 1 0 0 6 7 7 8 7 5 0 6 1 5 7 4 6 1 2 5
## [8749] 0 7 9 9 0 3 4 4 8 4 1 8 6 5 9 0 0 0 3 7 1 6 4 6 0 4 5 4 1 3 8 6 3 9 9 5
## [8785] 9 3 7 8 5 6 4 7 6 2 2 0 9 4 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
## [8821] 2 3 4 5 6 7 8 9 6 4 2 6 4 7 5 5 4 7 2 9 3 9 3 8 2 0 9 5 6 0 1 0 6 5 3 5
## [8857] 3 8 0 0 3 4 1 5 3 0 8 3 0 6 2 7 8 1 7 1 3 8 5 4 2 0 9 7 6 7 4 1 6 2 6 7
## [8893] 1 9 8 0 6 9 4 9 9 6 2 3 7 1 9 2 2 5 3 7 8 0 1 2 3 4 7 8 9 0 1 2 3 4 7 8
## [8929] 9 0 1 7 8 9 8 9 2 6 1 3 5 4 8 2 6 4 3 4 5 9 2 0 3 9 4 9 7 3 8 7 4 4 9 8
## [8965] 5 8 2 6 6 2 3 1 3 2 7 3 1 9 0 1 1 3 5 0 7 8 1 5 1 4 6 0 0 4 9 1 6 6 9 0
## [9001] 7 6 1 1 0 1 2 3 4 2 2 3 4 5 6 2 0 1 2 2 8 6 3 9 2 1 9 3 9 6 1 7 2 4 4 5
## [9037] 7 0 0 1 6 6 8 2 7 7 2 4 2 1 6 1 0 6 9 8 3 9 6 3 0 1 2 3 4 5 6 7 8 9 0 1
## [9073] 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 1 6 8 9 9 0 1 2 4 4 3 7 4 4 4 0 3 8
## [9109] 7 5 8 2 1 7 5 3 8 5 2 5 1 1 6 2 1 3 8 6 4 2 6 2 5 5 0 2 8 0 6 8 1 7 9 1
## [9145] 9 2 6 7 6 6 8 7 4 9 2 1 3 3 0 5 5 8 0 3 7 9 7 0 2 7 9 1 7 8 0 3 5 3 6 0
## [9181] 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 7 8 9 6 4 2 6 4 7 8 9 2
## [9217] 9 3 9 3 0 0 1 0 4 2 6 3 5 3 0 3 4 1 5 3 0 8 3 0 6 1 7 8 0 9 2 6 7 1 9 6
## [9253] 9 4 9 9 6 7 1 2 5 3 7 8 0 1 2 4 5 6 7 8 9 0 1 3 4 5 6 7 8 0 1 3 4 7 8 9
## [9289] 7 5 5 1 9 9 7 1 0 0 5 9 7 1 7 2 2 3 6 8 3 2 0 0 6 1 7 5 8 6 2 9 4 8 8 7
## [9325] 1 0 8 7 7 5 8 5 3 4 6 1 1 5 5 0 7 2 3 6 4 1 2 4 1 5 4 2 0 4 8 6 1 9 0 2
## [9361] 5 6 9 3 6 3 6 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 5 6 7 8 1
## [9397] 0 9 5 7 5 1 8 6 9 0 4 1 9 3 8 4 4 7 0 1 9 2 8 7 8 2 5 9 6 0 6 5 5 3 3 3
## [9433] 9 8 1 1 0 6 1 0 0 6 2 1 1 3 2 7 7 8 8 7 8 4 6 0 2 0 7 0 3 6 8 7 1 5 9 9
## [9469] 3 7 2 4 9 4 3 6 2 2 5 3 2 5 5 9 4 1 7 2 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
## [9505] 6 7 8 9 0 1 2 3 4 5 6 7 8 9 1 0 1 2 7 5 3 4 4 0 0 6 9 6 6 5 7 2 3 4 4 9
## [9541] 1 4 0 7 9 5 7 2 3 1 4 4 0 9 9 6 1 8 3 3 7 3 9 8 8 4 7 7 6 2 1 9 8 7 8 8
## [9577] 7 2 2 3 9 3 3 5 5 0 7 4 5 6 5 1 4 1 1 2 8 2 6 1 5 0 1 2 3 4 5 6 7 8 9 0
## [9613] 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 8 0 6 0 1 2 3 7 9 4 7 1 9 1 7 1 4 0
## [9649] 0 1 7 5 7 1 3 3 3 1 6 9 7 1 3 0 7 6 0 8 9 7 3 5 4 8 1 5 9 0 6 3 3 8 1 4
## [9685] 7 5 2 0 0 1 7 8 9 6 8 8 2 3 6 1 8 9 5 2 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
## [9721] 6 7 8 9 0 1 2 3 4 6 6 7 8 9 7 4 6 1 4 0 9 9 3 7 8 0 7 5 8 6 3 2 2 0 5 8
## [9757] 6 0 3 8 1 0 3 0 4 7 4 9 0 9 0 7 1 7 1 6 6 0 6 2 8 7 6 4 9 9 5 3 7 4 3 0
## [9793] 4 6 6 1 1 3 2 1 0 0 1 2 3 4 7 8 9 0 1 2 3 4 5 6 7 8 0 1 2 3 4 7 8 9 0 8
## [9829] 3 9 5 5 2 6 8 4 1 7 1 3 3 5 6 9 1 1 1 2 1 2 0 7 7 5 8 2 9 8 6 7 3 4 6 8
## [9865] 7 0 4 2 7 7 5 4 3 4 2 8 1 5 1 0 2 3 3 5 7 0 6 8 6 3 9 9 8 2 7 7 1 0 1 7
## [9901] 8 9 0 1 2 3 4 5 6 7 8 0 1 2 3 4 7 8 9 7 8 6 4 1 9 3 8 4 4 7 0 1 9 2 8 7
## [9937] 8 2 6 0 6 5 3 3 8 9 1 4 0 6 1 0 0 6 2 1 1 7 7 8 4 6 0 7 0 3 6 8 7 1 5 2
## [9973] 4 9 4 3 6 4 1 7 2 6 6 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6
Keras
proporciona un vocabulario para crear modelos de aprendizaje profundo que es simple, elegante e intuitivo. Construir un sistema de respuesta a preguntas, un modelo de clasificación de imágenes, una máquina neuronal de Turing o cualquier otro modelo es igualmente sencillo.
Si se desea una introducción más completa tanto a Keras
como a los conceptos y la práctica del aprendizaje profundo, se recomienda el libro (Chollet and Allaire 2018) de Manning. Este libro es una colaboración entre François Chollet, el creador de Keras
, y J.J. Allaire, quien escribió la interfaz R
para Keras
.
El libro no presupone un conocimiento significativo del aprendizaje automático y el aprendizaje profundo, y abarca desde la teoría básica hasta las aplicaciones prácticas avanzadas, todas utilizando la interfaz R
para Keras
.
Por otro lado, el aprendizaje profundo ya ha logrado resultados notables en muchas disciplinas y una fluidez sobre otras interfaces para TensorFlow
es de suma importancia en la práctica de la ciencia de datos. Ahora está causando sensación en las ciencias en general y en las ciencias de la vida en particular. El texto práctico (Bharath Ramsundar and Pande 2019) enseña cómo utilizar el aprendizaje profundo en genómica, química, biofísica, microscopía, análisis médico y otros campos.