En sesiones previas, vimos la forma de poder extraer, de forma automática, modelos de probabilidad donde partíamos de un paquete de datos de múltiples variables independientes, y con la ayuda de un programa, pudimos extraer modelos cuyas variables resultaban ser significativas. Este trabajo se conoce como Machine Learning, donde se aprende una función f, para manear las variables independientes hacia la variable dependiente.

En esta sesión, incorporaremos otra alternativa para modelar nuestra variables dependiente.

Redes neuronales

Una red neuronal, es una modelo inspirado por el sistema neurolígico. Se compone de un número de elementos de procesamiento altamente interconectados que se conocen como neuronas o nodos.

Es un sistema dinámico adaptable, puesto que cambia su estructura interna mediante el ajuste de valores representados como pesos.

En la práctica, las redes neuronales tienen un campo de aplicación muy grande, pero sobretodo se utiliza para el reconocimiento de patrones (que pueden ser imágenes).

De manera bilógica, una neurona transmite impulsos eléctricos en función de todas nuestras actividades y sentidos.

Neurona Fuente

La representación gráfica de la red neuronal en términos programables sería la siguiente:

Red_neuronal Fuente

Cada nodo tiene un peso dentro de la red.

Red_neuronal_2

Red_neuronal_2

Fuente

Instalamos el paquete/librería

install.packages("neuralnet")

Traemos a nuestro entorno la librerías que vamos a utilizar

library(neuralnet)
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following object is masked from 'package:neuralnet':
## 
##     compute
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(caret)
## Loading required package: lattice
## Loading required package: ggplot2
library(stats) 
options(scipen=999)

Importamos nuestro conjunto de información (german_credit.csv)

datos <- read.csv('german_credit.csv')

Realizamos un summary() en búsqueda de datos nulos y conocer más detalles sobre nuestros datos

summary(datos)
##        X             chk_acct        duration      credit_his   
##  Min.   :   1.0   Min.   :1.000   Min.   : 4.0   Min.   :0.000  
##  1st Qu.: 250.8   1st Qu.:1.000   1st Qu.:12.0   1st Qu.:2.000  
##  Median : 500.5   Median :2.000   Median :18.0   Median :2.000  
##  Mean   : 500.5   Mean   :2.577   Mean   :20.9   Mean   :2.545  
##  3rd Qu.: 750.2   3rd Qu.:4.000   3rd Qu.:24.0   3rd Qu.:4.000  
##  Max.   :1000.0   Max.   :4.000   Max.   :72.0   Max.   :4.000  
##     purpose        saving_acct     present_emp    installment_rate
##  Min.   : 0.000   Min.   :1.000   Min.   :1.000   Min.   :1.000   
##  1st Qu.: 1.000   1st Qu.:1.000   1st Qu.:3.000   1st Qu.:2.000   
##  Median : 2.000   Median :1.000   Median :3.000   Median :3.000   
##  Mean   : 2.828   Mean   :2.105   Mean   :3.384   Mean   :2.973   
##  3rd Qu.: 3.000   3rd Qu.:3.000   3rd Qu.:5.000   3rd Qu.:4.000   
##  Max.   :10.000   Max.   :5.000   Max.   :5.000   Max.   :4.000   
##       sex         other_debtor   present_resid      property    
##  Min.   :1.000   Min.   :1.000   Min.   :1.000   Min.   :1.000  
##  1st Qu.:2.000   1st Qu.:1.000   1st Qu.:2.000   1st Qu.:1.000  
##  Median :3.000   Median :1.000   Median :3.000   Median :2.000  
##  Mean   :2.682   Mean   :1.145   Mean   :2.845   Mean   :2.358  
##  3rd Qu.:3.000   3rd Qu.:1.000   3rd Qu.:4.000   3rd Qu.:3.000  
##  Max.   :4.000   Max.   :3.000   Max.   :4.000   Max.   :4.000  
##       age        other_install      housing        n_credits    
##  Min.   :19.00   Min.   :1.000   Min.   :1.000   Min.   :1.000  
##  1st Qu.:27.00   1st Qu.:3.000   1st Qu.:2.000   1st Qu.:1.000  
##  Median :33.00   Median :3.000   Median :2.000   Median :1.000  
##  Mean   :35.55   Mean   :2.675   Mean   :1.929   Mean   :1.407  
##  3rd Qu.:42.00   3rd Qu.:3.000   3rd Qu.:2.000   3rd Qu.:2.000  
##  Max.   :75.00   Max.   :3.000   Max.   :3.000   Max.   :4.000  
##       job           n_people       telephone        foreign         default   
##  Min.   :1.000   Min.   :1.000   Min.   :1.000   Min.   :1.000   Min.   :1.0  
##  1st Qu.:3.000   1st Qu.:1.000   1st Qu.:1.000   1st Qu.:1.000   1st Qu.:1.0  
##  Median :3.000   Median :1.000   Median :1.000   Median :1.000   Median :1.0  
##  Mean   :2.904   Mean   :1.155   Mean   :1.404   Mean   :1.037   Mean   :1.3  
##  3rd Qu.:3.000   3rd Qu.:1.000   3rd Qu.:2.000   3rd Qu.:1.000   3rd Qu.:2.0  
##  Max.   :4.000   Max.   :2.000   Max.   :2.000   Max.   :2.000   Max.   :2.0  
##    amountLog    
##  Min.   :5.521  
##  1st Qu.:7.219  
##  Median :7.749  
##  Mean   :7.789  
##  3rd Qu.:8.287  
##  Max.   :9.821

Observamos que a diferencia de lo que vimos la sesión pasada, la variable amount no aparece, en cambio tenemos amountLog

Observaciones:

Tenemos la columna X que es un índice que no vamos a necesitar La columna default tiene valores entre 1 y 2, requerimos que sean entre 1 y 0

datos[,1] <- NULL 
datos['default'] <- datos['default'] - 1 
summary(datos)
##     chk_acct        duration      credit_his       purpose      
##  Min.   :1.000   Min.   : 4.0   Min.   :0.000   Min.   : 0.000  
##  1st Qu.:1.000   1st Qu.:12.0   1st Qu.:2.000   1st Qu.: 1.000  
##  Median :2.000   Median :18.0   Median :2.000   Median : 2.000  
##  Mean   :2.577   Mean   :20.9   Mean   :2.545   Mean   : 2.828  
##  3rd Qu.:4.000   3rd Qu.:24.0   3rd Qu.:4.000   3rd Qu.: 3.000  
##  Max.   :4.000   Max.   :72.0   Max.   :4.000   Max.   :10.000  
##   saving_acct     present_emp    installment_rate      sex       
##  Min.   :1.000   Min.   :1.000   Min.   :1.000    Min.   :1.000  
##  1st Qu.:1.000   1st Qu.:3.000   1st Qu.:2.000    1st Qu.:2.000  
##  Median :1.000   Median :3.000   Median :3.000    Median :3.000  
##  Mean   :2.105   Mean   :3.384   Mean   :2.973    Mean   :2.682  
##  3rd Qu.:3.000   3rd Qu.:5.000   3rd Qu.:4.000    3rd Qu.:3.000  
##  Max.   :5.000   Max.   :5.000   Max.   :4.000    Max.   :4.000  
##   other_debtor   present_resid      property          age       
##  Min.   :1.000   Min.   :1.000   Min.   :1.000   Min.   :19.00  
##  1st Qu.:1.000   1st Qu.:2.000   1st Qu.:1.000   1st Qu.:27.00  
##  Median :1.000   Median :3.000   Median :2.000   Median :33.00  
##  Mean   :1.145   Mean   :2.845   Mean   :2.358   Mean   :35.55  
##  3rd Qu.:1.000   3rd Qu.:4.000   3rd Qu.:3.000   3rd Qu.:42.00  
##  Max.   :3.000   Max.   :4.000   Max.   :4.000   Max.   :75.00  
##  other_install      housing        n_credits          job       
##  Min.   :1.000   Min.   :1.000   Min.   :1.000   Min.   :1.000  
##  1st Qu.:3.000   1st Qu.:2.000   1st Qu.:1.000   1st Qu.:3.000  
##  Median :3.000   Median :2.000   Median :1.000   Median :3.000  
##  Mean   :2.675   Mean   :1.929   Mean   :1.407   Mean   :2.904  
##  3rd Qu.:3.000   3rd Qu.:2.000   3rd Qu.:2.000   3rd Qu.:3.000  
##  Max.   :3.000   Max.   :3.000   Max.   :4.000   Max.   :4.000  
##     n_people       telephone        foreign         default      amountLog    
##  Min.   :1.000   Min.   :1.000   Min.   :1.000   Min.   :0.0   Min.   :5.521  
##  1st Qu.:1.000   1st Qu.:1.000   1st Qu.:1.000   1st Qu.:0.0   1st Qu.:7.219  
##  Median :1.000   Median :1.000   Median :1.000   Median :0.0   Median :7.749  
##  Mean   :1.155   Mean   :1.404   Mean   :1.037   Mean   :0.3   Mean   :7.789  
##  3rd Qu.:1.000   3rd Qu.:2.000   3rd Qu.:1.000   3rd Qu.:1.0   3rd Qu.:8.287  
##  Max.   :2.000   Max.   :2.000   Max.   :2.000   Max.   :1.0   Max.   :9.821

Hacemos una partición de nuestros datos, de entrenamiento y prueba

set.seed(1234) 

# p = 0.8 toma el 80% de la muestra aleatoriamente, y dejamos el resto para la prueba 
train <- createDataPartition(y = datos$default, p = 0.8, list = FALSE, times = 1) 
datos_train <- datos[train, ]
datos_test <- datos[-train, ] 

La variable que queremos modelar default es una variable cuyos valores son cualitativos, 1 ó 0.
Esto nos dice que el tipo de modelo que debemos parametrizar es un modelo de probabilidad.

Funciones de activación

las funciones de activación son aquellas expresiones que nos permiten definir el valor de salida de la neurona.

  • Función de Identidad: Operador lineal, mapea los valores de entrada hacia la salida.
  • Binary Step: Define el valor de salida verdadero o falso (0 ó 1) a los valores de Y (que no tiene valores 0 ó 1)
  • Sigmoidea: Logística e Hiperbólica.
  • Binaria sigmoidea: Ideal cuando nuestra variable dependiente es 0 ó 1
  • Sigmoidea bipolar: Cuando los valores de la variable dependiente oscilan entre -1 y 1
  • ReLu: (Rectified Linear Unit) Mapea valores negatuivos a 0, y deja el valor original de los positivos.
  • Ramp: Similar a ReLu

Esto implica que la función de activación que usaremos es la función binaria Sigmoidea, que es ideal cuando la variable dependiente es binaria con valores 0 y 1.

Funciones de activación

Funciones de activación

Construimos nuestro clasificador de Red Neuronal

nn = neuralnet(default ~ ., data=datos_train, hidden=c(4,2), act.fct = 'logistic', linear.output = FALSE)

Graficamos nuestra red

plot(nn)

Evaluamos nuestra red con datos de prueba train y creamos la matriz de confusión, predicciones vs datos en entrenamiento

predicciones_train <- neuralnet::compute(nn, datos_train)
predicciones_nn_train <- ifelse(predicciones_train$net.result>0.5,1,0) 

matriz_conf_nn <- table(datos_train$default, predicciones_nn_train, dnn = c("observaciones", "predicciones"))
matriz_conf_nn
##              predicciones
## observaciones   0   1
##             0 532  27
##             1 142  99
exactitud <- (matriz_conf_nn[1] + matriz_conf_nn[4] ) / sum(matriz_conf_nn[1:4])
exactitud 
## [1] 0.78875

Probamos con datos de prueba test y creamos la matriz de confusión, predicciones vs datos de prueba

predicciones_test <- neuralnet::compute(nn, datos_test)
predicciones_nn_test <- ifelse(predicciones_test$net.result>0.5,1,0) 

matriz_conf_nn_test <- table(datos_test$default, predicciones_nn_test, dnn = c("observaciones", "predicciones"))
matriz_conf_nn_test
##              predicciones
## observaciones   0   1
##             0 130  11
##             1  44  15
exactitud <- (matriz_conf_nn_test[1] + matriz_conf_nn_test[4] ) / sum(matriz_conf_nn_test[1:4])
exactitud
## [1] 0.725

Creamos la matriz de confusión, predicciones vs datos de prueba

Interacción con proveedores de servicio para trading algorítmico

BITSO API-BITSO

Existen diversos proveedores de información que como vimos en sesiones pasadas, hacen pública su información a través de APIs. Además, también hay proveedores de servicios para realizar operaciones de compra y venta de monedas virtuales en blockchain, tal es el caso de Bitso.

Bitso dispone de un API, donde desarrolladores externos pueden crear programas que interactúen con la plataforma Bitso para realizar diversas operaciones.

Para lo anterior, es necesario crear una cuenta personal, una vez creada, se require configurar un API desde la página de Bitso, la cual nos va a proveer de dos claves que nos servirán para acceder a nuestra cuenta.

Descargamos librerías que nos permitirán acceder a los recurso de Bitso. Atención con la fuente de descarga.

## https://github.com/nicholasbucher/RBitso
library(devtools)
## Loading required package: usethis
## La librería es una colaboración pública 
## Siempre busquen documentarse antes de descargar e instalar un software 
install_github("nicholasbucher/RBitso")   
## Skipping install of 'RBitso' from a github remote, the SHA1 (cdbfb6b3) has not changed since last install.
##   Use `force = TRUE` to force installation

Cargamos la librería RBitso que descargamos en el paso anterior.

library(RBitso)

Ingresamos los identificadores para acceder a la API de la cuenta personal mediante dos variables.
Nota: Para que la librería funcione adecuadamente, las variables deben tener los nombres ky y scrt
(No compartan los valores, sobretodo si su cuenta está fondeada)

ky <- ""
scrt <- ""  

Habiendo ingresado las llaves, podemos usar diversas funciones para acceder a los recursos de nuestra cuenta en Bitso. Por ejemplo:

balance() 

Podemos extraer los precios actuales de negociación de Bitcon en pesos. Las claves de cotización, o tickers, son nombres estándar de Bitso.

ticker('eth_mxn')

Tambieén podemos consultar que libros (o tickers), hay disponibles.

available_books()

Pudiendo accerder a los recursos de la plataforma de negociación, podemos crear nostros programas para que de forma automática nuestro programa opere por nosotros. Esto se conoce como trading algorítmico.

limit <- 1150000
monto <- 100000

while(TRUE){
  
  Sys.sleep(2)
  precio <- ticker('btc_mxn')$ask[1]
  
  if(precio>limit){
    print(paste("Precio Actual = ", precio))
    
  }else{
    # Envía la orden de compra 
    print("Envía la orden de compra")
    place_order("btc_mxn","buy","limit",monto,"0.001")
    break
  }
  
}