#-----------------------------------------------------------------------------------------------#
getwd() # ¿dónde estoy?
library (reticulado) # cargar reticulado
os <- reticulate::import("os") # una pequeña prueba funcional
os$listdir(".") # si todo va bien: directorio local


#------------------------------------------------- -----------------------------------------------#
# instalar paquetes de python (¡solo lo hacemos una vez!)
# esto es útil cuando estos paquetes están ausentes, evita
# elegir el entorno de instalación incorrecto

py_install('matplotlib')
py_install('pandas')

py_install('graphviz')
py_install('pydot')
py_install('pydotplus')

#------------------------------------------------- -----------------------------------------------#
library (reticulate)
py_config() # la configuración local de python
miniconda_update() # para estar en la última versión
conda_list() # posible configuración de conda
# nos permite comprobar el entorno
#conda que vamos a usar
# aquí r-reticulate

# Para obtener ayuda, busque "conda-tools" en la ayuda

# Versión anterior eliminada
envname <- "r-reticulate" # especifica el entorno correcto
conda_remove(envname = envname,
             paquetes="tensorflow",
             conda="auto")

# nueva versión instalada con PIP!
envname <- "r-reticulate"
conda_install(envname = envname,
              packages = "tensorflow", 
              pip = TRUE)

#-----------------------------------------------------------------------------------------------#

install.packages("tensorflow")    # el paquete R
library(tensorflow)
# install_tensorflow()            # Eventual reinstalación si hay un problema

install.packages("keras") 
install.packages("tfdatasets") 
install.packages("tfestimators") 
install.packages("tfruns") 

#------SI TODO ESTÁ INSTALADO EMPEZAR AQUÍ ------------------------------------------------------#

library(tensorflow)
library(keras)
library(tfdatasets)

library(reticulate)
# py_install("scipy") # si no está instalado
scipy  <- import("scipy")
kutils <- import("tensorflow.keras.utils") # observe cómo importar desde tf!

is_keras_disponible() # ¿keras está bien en el lado de python?
# CPU, GPU... disponible para procesos
tf$config$experimental$list_physical_devices()

hola<- tf$constant('Mi primer tensor')
hola # la definición del tensor
tf$print(hola) 

#-----------------------------------------------------------------------------------------------#

zeros <- tf$Variable(tf$zeros(shape(2L,5L,3L)))
print(zeros)

zeros <-  k_zeros(shape = c(2, 5, 3))
print(zeros)

array(0.0 , c(5,3,2))

#-----------------------------------------------------------------------------------------------#

s_      <-  c(2, 5, 3)
zero    <-  k_zeros(shape = s_)
un      <-  zero + 1

deux    <-  un + un
pi_     <-  un * pi
deux$eval
pi_$eval

k_exp(deux)   # exponencial
k_sin(pi_)    # sino
k_abs(-1*un)  # valor absoluto

h_round <- function(x, l=2) {
  p <- 10**l
  k_round(x*p)/p   # nuestra función útil k_round, el redondeo keras
} 

h_round(pi_,4)
h_round(k_sin(pi_))
h_round(k_cos(pi_))

x <- k_variable(zero)


x[1:2,2:4,1:2]

#-----------------------------------------------------------------------------------------------#

x <- k_variable(zero)
k_count_params(x)
# recuperar las dimensiones 
numero_de_matrices   <- k_count_params(x[,1,1]) ; numero_de_matrices  
numero_de_lineas     <- k_count_params(x[1,,1]) ; numero_de_lineas  
numero_de_columnas   <- k_count_params(x[1,1,]) ; numero_de_columnas 

x <- k_variable(zero)                        # inicialización del tensor x

k_update(x,3*un - k_sin(x)**2 - k_cos(x)**2) # actualización del tensor x
k_update(x[1,1,1], 100)

#-----------------------------------------------------------------------------------------------#

f_update__3 <- function(x,c,i=1,j=1,k=1,iii= NA,
                        jjj= NA,
                        kkk= NA,
                        max= NA) {
  c <- as.vector(c)
  if (is.na(iii))  iii  <- k_count_params(x[,1,1])
  if (is.na(jjj))  jjj  <- k_count_params(x[1,,1])
  if (is.na(kkk))  kkk  <- k_count_params(x[1,1,])
  if (is.na(max))  max  <- sum(c)
  l <- 1
  for (ii in i:iii) {
    for (jj in j:jjj) {
      for (kk in k:kkk) {
        if (l <= max) k_update(x[ii,jj,kk], c[l] )
        l <- l + 1}
    }
  }
  x
}


#-----------------------------------------------------------------------------------------------#

x <- k_variable(zero)

f_update__3(x,c(1:30))

x <- k_variable(zero)

f_update__3(x,c(1:30),1,1,1,1,1,1)  # actualización de la celda 1,1,1

x <- k_variable(zero)

f_update__3(x,c(1:30),max = 5)      # actualización de las 5 priemras celdas

x <- k_variable(zero)

f_update__3(x,c(1:30),1,3,1,1,3,3)

x <- k_variable(zero)

f_update__3(x,c(1:30),1,3,1,2,3,3)

x <- k_variable(zero)

f_update__3(x,c(1:30),1,3,1,2,3,3, max = 5)

x <- k_variable(zero)

f_update__3(x,c(1:30),1,1,1,2,2,2)

m <- matrix(c(1:15)*10, ncol = 3)
m

x <- k_variable(zero)

f_update__3(x,m, max = 15)

x <- k_variable(zero)

f_update__3(x,m*10,2,1,1, max = 15)

k_sum(un) # esperamos obtener la suma de todas las celdas: 30

k_sum(un,1) # compacto sobre las dimensiones de nuestras matrices_3lineas_5columnas
k_sum(un,2) # compacta cada matriz en una linea
k_sum(un,3) # compacta cada matriz en una transposición de columna

k_sum(un,c(1,2)) # compacto k_sum(un,2) en una linea
k_sum(un,c(2,3)) # compacto k_sum(un,2) en una linea
k_sum(un,c(1,3)) # compacto k_sum(un,3) en una línea

#------------------------------------------------- -----------------------------------------------#

library(caret) # manejar muchos tipos de plantillas
library(lessR) # siempre menos código R ...
library(DataExplorer) # para alguna funcionalidad

summary(iris)
introduce(iris)

# remotos::install_github("bokeh/rbokeh") # ¡instalar una vez!

library(rbokeh) # Librería de gráficos de Python (interactiva)
# lista de herramientas interactivas
tools <- c("pan", "wheel_zoom", "box_zoom", "box_select", "reset")
# malla 4 veces 4 de datos por gráfico para gráficos
nms <- expand.grid(names(iris)[1:4], 
                   rev(names(iris)[1:4]), 
                   stringsAsFactors = FALSE)
# lista des 4 veces 4 = 16 gráficos
splom_list <- vector("list", 16)
# bucle de formación de los 16 gráficos
for(ii in seq_len(nrow(nms))) {
  splom_list[[ii]] <- figure(width = 200, height = 200, tools = tools,
                             xlab = nms$Var1[ii], ylab = nms$Var2[ii]) %>%
    ly_points(nms$Var1[ii], nms$Var2[ii], data = iris,
              color = Species, glyph = Species, size = 6, legend = FALSE, 
              hover = list(Sepal.Length, 
                           Sepal.Width, 
                           Petal.Length, 
                           Petal.Width,
                           Species))
}
# ensamblado de los 16 gráficos en 4 veces 4
grid_plot(splom_list, ncol = 4, same_axes = FALSE, link_data = FALSE)

#-----------------------------------------------------------------------------------------------#
set.seed(666)             # inicialización del generador de números aleatorios
# permite la reproducibilidad

# creando una partición del 80% de las claves
# organizado en variable de respuesta
partition <- createDataPartition(iris$Species, p = .8, 
                                 list = FALSE, 
                                 times = 1)


irisTrain <- iris[ partition,]  # extracción de observaciones sobre estas claves
irisRest <- iris[ -partition,] # extraer la parte restante

# dividimos el 20% nuevamente, de la misma manera
sub_partition <- createDataPartition(irisRest$Species, p = .6, 
                                      list = FALSE, 
                                      times = 1)

irisTest  <- irisRest[sub_partition,]  # parte test 60% * 20 % --> 12%
irisVal   <- irisRest[-sub_partition,] # parte validación 40% * 20 % --> 8%


rbind(iris[1:4, ],irisTrain[1:4, ])

fitControl <- trainControl( ##10-folds
  method  = "repeatedcv",
  number  = 10,
  repeats = 10)

# rf,C5.0,ranger,kernelpls,gbm,glmnet,svmLinear3, avNNet,nnet,rbfDDA,regLogistic ...

names(getModelInfo())

algo     <- "rf"

set.seed(666)
t_before <- Sys.time()
model_   <- train(Species ~ ., data = irisTrain, 
                  method = algo, 
                  trControl = fitControl,
                  verbose = FALSE)
t_after <- Sys.time()
duree   <- t_after - t_before 
cat("tiempo de ejecución:",round(duree,2)," segundos \n")
# model_ # eliminar el #  al inicio de linea para tener información del módulo


irisTest.Predictions    <- predict(model_, irisTest)
d                       <- data.frame(irisTest$Species,irisTest.Predictions)


#-----------------------------------------------------------------------------------------------#

mi_accuracy <- function(d, algo =""){
  intervalo <- d[,1] == d[,2]
  numero_exitos <- sum(intervalo)
  efectivo         <- nrow(d)
  accuracy         <- numero_exitos/efectivo * 100
  cat              <- algo != ""
  if  (cat) cat("Accuracy del modelo ",algo," : ", round(accuracy,2),"\n" )
  if (!cat) accuracy 
}


#-----------------------------------------------------------------------------------------------#

mi_accuracy(d,algo)

Plot(irisTest.Species, irisTest.Predictions)


#-----------------------------------------------------------------------------------------------#
# TF2 KERAS
#-----------------------------------------------------------------------------------------------#


iris_  <- dummify(iris, select = "Species") # lessR ¡es muy simple!
iris__ <- data.frame(iris_,iris$Species) # reintroducir factores


# partición en 3 bloques con todas las columnas posibles!
# partición DEBE estar en Species

# nos acostumbramos a usar seed de keras que actúa
# en R, keras y TF2
# no ignore las opciones que preservan la gpu y paralelización


set_random_seed(666, disable_gpu = TRUE)
partition <- createDataPartition(iris__$iris.Species, p = .8, 
                                 list = FALSE, 
                                 times = 1)


irisTrain__ <- iris__[ partition,]
irisRest__  <- iris__[ -partition,]

sub_partition <- createDataPartition(irisRest__ $iris.Species, p = .6, 
                                      list = FALSE, 
                                      times = 1)

irisTest__  <- irisRest__[sub_partition,]
irisVal__   <- irisRest__[-sub_partition,]

# Creación de las particiones para modelizar y pedecir
irisTrain     <- irisTrain__
irisTest      <- irisTest__
irisVal       <- irisVal__

irisTrain$Species     <- NULL
irisTest$Species      <- NULL
irisVal$Species       <- NULL

#-----------------------------------------------------------------------------------------------#

# Preprocesamiento en cada partición de datos
# elaboración de los parámetros en el conjunto de entrenamiento
preProc_param <- preProcess(irisTrain[,1:4], método = c("center", "scale"))
# aplicar preprocesamiento con estos parámetros
# cuidado, todos los datos deben ser procesados
# incluyendo los que serán inferidos!
irisTrain     <- predict(preProc_param, irisTrain)
irisTest      <- predict(preProc_param, irisTest)
irisVal       <- predict(preProc_param, irisVal)


#-----------------------------------------------------------------------------------------------#

# dÃ©división y conversión en matrices
X_train      <- as.matrix(irisTrain[ ,1:4])
X_test       <- as.matrix(irisTest[ ,1:4])
X_val        <- as.matrix(irisVal[ ,1:4])

y_train      <- as.matrix(irisTrain[ ,5:7])
y_test       <- as.matrix(irisTest[ ,5:7])
y_val        <- as.matrix(irisVal[ ,5:7])

#-----------------------------------------------------------------------------------------------#

set_random_seed(666, disable_gpu = FALSE) # dependiendo de si tienes o no una GPU y
# que queremos reproducibilidad total

# Posicionamiento secuencial de capas de neuronas

model <- keras_model_sequential() 
model %>% 
  layer_dense(units = 8, 
              input_shape = c(4), # aquí tensor = matriz 4 col
              kernel_initializer = "glorot_uniform") %>%  
  layer_activation('relu') %>% 
  layer_alpha_dropout(rate = 0.1, seed = 0 ) %>%
  layer_dense(units = 14,
              kernel_initializer = "glorot_uniform") %>% 
  layer_activation('relu') %>% 
  layer_dense(units = 3,
              kernel_initializer = "glorot_uniform") %>%  
  layer_activation('softmax')

summary(model) 



# compilacióin - modelo: parámetros típicos para la inferencia de categorías
model %>% compile(
  optimizer = optimizer_rmsprop(lr = 0.01),
  loss      = "categorical_crossentropy",
  metrics   = list("categorical_accuracy"))


set_random_seed(666, disable_gpu = FALSE)
t_before <- Sys.time()

model %>% 
  fit(
    x = X_train , y = y_train,
    epochs = 69,
    validation_split = 0.01,
    verbose = 2
  )


# mostrar la duración del entrenamiento
t_despues <- Sys.time()
duracion <- t_despues - t_antes
cat("tiempo de ejecución:",round(duracion,2),"segundos\n")


# Aplicación del modelo sobre nuestros datos de prueba
# producir un pronóstico de probabilidad de tres columnas
y_predictions_tests <- round(predict(modelo, X_test),2)
y_predicciones_pruebas[5:13,]


# una función para traducir las probabilidades de las 3 columnas
# decidir lo que significan (setosa, versicolor, virginica)
# usar la sintaxis dplyr
decode_  <- function(d_){
  require(dplyr)
  d__    <- mutate(d_,               # 1/3 = 1/(número de clases)
                   ok1 = if_else(X1 >= 1/3, TRUE, FALSE),
                   ok2 = if_else(X2 >= 1/3, TRUE, FALSE),
                   ok3 = if_else(X3 >= 1/3, TRUE, FALSE))
  d___  <- transmute(d__, 
                     Species = if_else(ok1,
                                       "setosa",
                                       if_else(ok2,
                                               "versicolor",
                                               "virginica"
                                       )))}

# una función que ejecuta la predicción Y decodifica el resultado
predict_   <- function(X_in,model){
  d_ <- data.frame(predict(model, X_in))
  decode_(d_)}


# solo falta mostrar los resultadosuna función que ejecuta la predicción Y decodifica el resultados
irisTest.Predictions    <- predict_(X_test, model)
d                       <- data.frame(irisTest__$iris.Species,irisTest.Predictions)


mi_accuracy(d)
Plot(irisTest__.iris.Species, Species)

#-----------------------------------------------------------------------------------------------#








