Introducción a Keras Sequential y API Funcional#

Introducción a TensorFlow#

La mejor introducción a esta biblioteca fundamental de inteligencia artificial es entrando a la documentación oficial

Introducción a Keras#

Keras no es más que una API funcionando sobre algún motor tensorial (Por ejemplo, TensorFlow).

Igual que antes, no hay nada mejor que ir a los sitios oficiales y chequear por sí mismxs la documentación oficial:

diosito2

¿Por qué elegir Keras?#

Preguntémosle a dios Google:

dios_trends

Importando Librerías Necesarias#

Como siempre, lo primero que debemos hacer es importar las librerías necesarias:

# Librería para manejo de tensores
import tensorflow as tf
# API para AI sobre motor de tensores
from tensorflow import keras
# Manejo de arreglos
import numpy as np
# Dibujitos
import matplotlib.pyplot as plt

Simulando Datos #

En esta ocasión y por ser la introducción, mostraremos que el proceso de optimización visto en clase (usando JAX), es equivalente a construir una red neuronal artificial.

Para esto, simulemos unos datos de prueba:

# Genera datos espaciados uniformemente
x=np.linspace(-10,10,50)
# Modelo generado a partir de las entradas
y=2*x**2+3*x+5*np.random.normal(0,4,size=len(x))

Observemos algo de los datos simulados:

print(x)
[-10.          -9.59183673  -9.18367347  -8.7755102   -8.36734694
  -7.95918367  -7.55102041  -7.14285714  -6.73469388  -6.32653061
  -5.91836735  -5.51020408  -5.10204082  -4.69387755  -4.28571429
  -3.87755102  -3.46938776  -3.06122449  -2.65306122  -2.24489796
  -1.83673469  -1.42857143  -1.02040816  -0.6122449   -0.20408163
   0.20408163   0.6122449    1.02040816   1.42857143   1.83673469
   2.24489796   2.65306122   3.06122449   3.46938776   3.87755102
   4.28571429   4.69387755   5.10204082   5.51020408   5.91836735
   6.32653061   6.73469388   7.14285714   7.55102041   7.95918367
   8.36734694   8.7755102    9.18367347   9.59183673  10.        ]
print(y)
[217.99355623 142.68741022 146.31621191 128.13479406 111.73941384
  89.47685489 105.11836081  81.19732541  41.91156847  66.78121834
  30.2499299   32.93817221  66.38013768  11.53944667  39.74005336
  43.18997134  13.49564781  -2.55456125  12.85486119   8.49065364
  10.54997947  -3.52320593 -23.10728138   5.28466635   5.13328338
 -30.04973645   5.07860833  -9.28112974  30.58987377  -8.71957095
  10.0410125   38.08053443  48.66118723  40.10339338  67.65755535
  51.50627849  57.20230928  85.52521727  64.79352386 123.02358686
  80.40731023 103.25935165 127.73747174  99.3556638  158.00346775
 159.85390715 173.74514933 175.63960935 165.48174042 199.00324966]

Visualizando Datos#

En lo posible, trate de visualizar datos para tener una intuición sobre lo que está pasando. Es claro que no siempre es posible hacerlo, pero existen, por ejemplo, técnicas de reducción de dimensión para dar una idea vaga de lo que está pasando.

# Generar Lienzo
plt.figure(figsize=(15,8))
#Titulo del lienzo
plt.title("Visualización de Datos",fontsize=15)
#Dibujar datos
plt.plot(x,y,'o')
# Leyenda de los datos
plt.legend(["Datos"],fontsize=15)
# Nombrar Ejes
plt.xlabel("$Tiempo$",fontsize=15)
plt.ylabel("$Valor$",fontsize=15)

# Poner cuadrícula
plt.grid()
# Mostrar imagen
plt.show()
../../_images/Hello_World_ML_18_0.png

Construyendo Red Neuronal (Diseño)#

Para construir nuestra primera red Neuronal, recuerde el siguiente dibujo:

Perceptron

Vemos que el dibujo opera de izquierda a derecha (\(\rightarrow\)), por lo que tiene sentido llamarlo Modelo Secuencial.

En este caso, usaremos una neurona (units) y la dimensión de entrada es unidimensional (input_shape)

model = keras.Sequential(
    keras.layers.Dense(units=1,input_shape=(1,))
    )

Compilando Red Neuronal (Forma de Optimizar)#

Ahora que tenemos nuestra maqueta de las ecuaciones del modelo, elegimos una función de pérdida adecuada a nuestro problema y un optimizador para minimizar dicha pérdida:

model.compile(optimizer='sgd', loss='mean_squared_error')

Resumen de la Red Neuronal#

El modelo creado y compilado tiene muchos otros métodos interesantes.

Por ejemplo, podemos ver el resumen de lo que tiene la red.

model.summary()
Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 dense (Dense)               (None, 1)                 2         
                                                                 
=================================================================
Total params: 2
Trainable params: 2
Non-trainable params: 0
_________________________________________________________________

También es posible visualizar los modelos en forma de grafo, lo cual es muy útil para tener control global de la arquitectura del modelo:

from tensorflow.keras.utils import plot_model
plot_model(model,show_shapes=True)
You must install pydot (`pip install pydot`) and install graphviz (see instructions at https://graphviz.gitlab.io/download/) for plot_model/model_to_dot to work.

Entrenando Red Neuronal (Fancy para «Ajustar los datos»)#

model.fit(x, y, epochs=10,verbose=1)
Epoch 1/10
1/2 [==============>...............] - ETA: 0s - loss: 6596.0742

2/2 [==============================] - 1s 8ms/step - loss: 8620.6582
Epoch 2/10
1/2 [==============>...............] - ETA: 0s - loss: 8898.5801

2/2 [==============================] - 0s 8ms/step - loss: 8100.7305
Epoch 3/10
1/2 [==============>...............] - ETA: 0s - loss: 7838.4111

2/2 [==============================] - 0s 0s/step - loss: 8003.3955
Epoch 4/10
1/2 [==============>...............] - ETA: 0s - loss: 9316.4707

2/2 [==============================] - 0s 0s/step - loss: 7479.1870
Epoch 5/10
1/2 [==============>...............] - ETA: 0s - loss: 7585.7280

2/2 [==============================] - 0s 8ms/step - loss: 7672.4448
Epoch 6/10
1/2 [==============>...............] - ETA: 0s - loss: 5066.2114

2/2 [==============================] - 0s 8ms/step - loss: 7128.1436
Epoch 7/10
1/2 [==============>...............] - ETA: 0s - loss: 5780.6123

2/2 [==============================] - 0s 8ms/step - loss: 7198.5161
Epoch 8/10
1/2 [==============>...............] - ETA: 0s - loss: 5357.8721

2/2 [==============================] - 0s 0s/step - loss: 6663.5493
Epoch 9/10
1/2 [==============>...............] - ETA: 0s - loss: 7064.5449

2/2 [==============================] - 0s 8ms/step - loss: 6941.7188
Epoch 10/10
1/2 [==============>...............] - ETA: 0s - loss: 5028.7676

2/2 [==============================] - 0s 8ms/step - loss: 6354.8145
<keras.callbacks.History at 0x19f58a4fbb0>

Visualizar Resultados de la Red #

#Obtener Pesos de la Red
w=model.get_weights();
print(w)
#Imprimir resultados
print("\nObjeto Pesos:",w)
print('\nNumber of Weights -> '+ str(len(w)))
print('\nw = ' + str(w[0][0]) +'(Weight)')
print('b = ' + str(w[1])+'("Weight"->Bias)')
[array([[-0.24988794]], dtype=float32), array([23.104277], dtype=float32)]

Objeto Pesos: [array([[-0.24988794]], dtype=float32), array([23.104277], dtype=float32)]

Number of Weights -> 2

w = [-0.24988794](Weight)
b = [23.104277]("Weight"->Bias)

Predecir valores dentro de los datos (Ver Regresión)#

predecir=model.predict(x)
#print(predecir)
#np.vstack((predecir.reshape(-1,),y)).T
1/2 [==============>...............] - ETA: 0s

2/2 [==============================] - 0s 8ms/step

Visualizar Resultados#

plt.figure(figsize=(15,8))
plt.plot(x,predecir,'r-',label='Model: y={:.2f}*x+{:.2f}'.format(w[0].item(),w[1].item()))
plt.plot(x,y,'o', label='Data')
plt.title('Plotting Model vs Data')
plt.legend(loc=0)
plt.show()
../../_images/Hello_World_ML_38_0.png

Mejorando Red Neuronal#

model2 = tf.keras.Sequential([
    keras.layers.Dense(units=5,input_shape=(1,),activation='softplus'),
    keras.layers.Dense(units=10,activation='softplus'),
    keras.layers.Dense(units=20,activation='softplus'),
    keras.layers.Dense(units=1),
    ])
model2.compile(optimizer='adam', loss='mean_squared_error')
model2.summary()
Model: "sequential_1"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 dense_1 (Dense)             (None, 5)                 10        
                                                                 
 dense_2 (Dense)             (None, 10)                60        
                                                                 
 dense_3 (Dense)             (None, 20)                220       
                                                                 
 dense_4 (Dense)             (None, 1)                 21        
                                                                 
=================================================================
Total params: 311
Trainable params: 311
Non-trainable params: 0
_________________________________________________________________
history=model2.fit(x, y, epochs=1000,verbose=0)
#Obtener Pesos de la Red
w2=model2.get_weights();
#Imprimir resultados
#print("\nObjeto Pesos:",w2)
#print('\nNumber of Weights -> '+ str(len(w2)))
#print('\nw = ' + str(w[0][0]) +'(Weight)')
#print('b = ' + str(w[1])+'("Weight"->Bias)')
x_test=np.linspace(x[0],x[-1],300)
predecir=model2.predict(x_test)
 1/10 [==>...........................] - ETA: 0s

10/10 [==============================] - 0s 2ms/step
plt.figure(figsize=(15,8))
plt.plot(x_test,predecir,label='Model')
plt.plot(x,y,'o', label='Data')
plt.title('Plotting Model vs Data')
plt.legend(loc=0)
plt.show()
../../_images/Hello_World_ML_44_0.png
plt.figure(figsize=(15,8))
plt.plot(history.history['loss'],'r-',label='Loss')
plt.title('Plotting Model vs Data')
plt.legend(loc=0)
plt.show()
../../_images/Hello_World_ML_45_0.png

Datos más retadores#

trend=0.1
time=np.arange(0,100,0.1)
y=trend*time+np.sin(time)+np.random.normal(scale=0.5,size=len(time))
plt.figure(figsize=(15,8))
plt.title("Visualización de Datos",fontsize=15)
plt.plot(time,y,'-')
plt.legend(["Datos"],fontsize=15)
plt.xlabel("$x$",fontsize=15)
plt.ylabel("$y$",fontsize=15)
plt.grid()
plt.show()
../../_images/Hello_World_ML_48_0.png
model3 = tf.keras.Sequential([
    keras.layers.Dense(units=10,input_shape=(1,),activation='elu'),
    keras.layers.Dense(units=20,activation='elu'),
    keras.layers.Dense(units=30,activation='elu'),
    keras.layers.Dense(units=40,activation='elu'),
    keras.layers.Dense(units=50,activation='elu'),
    keras.layers.Dense(units=60,activation='elu'),
    keras.layers.Dense(units=70,activation='elu'),
    keras.layers.Dense(units=1)
    ])

model3.compile(optimizer='adam', loss='mean_squared_error')
model3.summary()
Model: "sequential_2"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 dense_5 (Dense)             (None, 10)                20        
                                                                 
 dense_6 (Dense)             (None, 20)                220       
                                                                 
 dense_7 (Dense)             (None, 30)                630       
                                                                 
 dense_8 (Dense)             (None, 40)                1240      
                                                                 
 dense_9 (Dense)             (None, 50)                2050      
                                                                 
 dense_10 (Dense)            (None, 60)                3060      
                                                                 
 dense_11 (Dense)            (None, 70)                4270      
                                                                 
 dense_12 (Dense)            (None, 1)                 71        
                                                                 
=================================================================
Total params: 11,561
Trainable params: 11,561
Non-trainable params: 0
_________________________________________________________________
history=model3.fit(time, y, epochs=10000,verbose=0)
#Obtener Pesos de la Red
w3=model3.get_weights();
#Imprimir resultados
#print("\nObjeto Pesos:",w2)
#print('\nNumber of Weights -> '+ str(len(w2)))
#print('\nw = ' + str(w[0][0]) +'(Weight)')
#print('b = ' + str(w[1])+'("Weight"->Bias)')
x_test=np.linspace(time[0],time[-1],3000)
predecir=model3.predict(x_test)
plt.figure(figsize=(15,8))
plt.plot(time,y,'-', label='Data')
plt.plot(x_test,predecir,'r',label='Model')
plt.title('Plotting Model vs Data')
plt.legend(loc=0)
plt.show()
../../_images/Hello_World_ML_53_0.png
plt.figure(figsize=(15,8))
plt.plot(history.history['loss'],'r-',label='Model')
plt.title('Plotting Model vs Data')
plt.legend(loc=0)
plt.show()
../../_images/Hello_World_ML_54_0.png

API Funcional#

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
from tensorflow import keras
from tensorflow.keras.layers import Activation, Input,Dense
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam
trend=0.1
time=np.arange(0,100,0.1)
y=trend*time+np.sin(time)+np.random.normal(scale=0.5,size=len(time))
inputs=Input(shape=(1,))
output=inputs
capas=10
dim=10
output=Activation('elu')(output)

for capa in range(capas):
    output=Dense(dim)(output)
    output=Activation('elu')(output)
    dim+=10
output=Dense(1)(output)

model=Model(inputs,output)
model.compile(loss='mse',optimizer='adam')
model.summary()
Model: "functional_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         [(None, 1)]               0         
_________________________________________________________________
activation (Activation)      (None, 1)                 0         
_________________________________________________________________
dense_13 (Dense)             (None, 10)                20        
_________________________________________________________________
activation_1 (Activation)    (None, 10)                0         
_________________________________________________________________
dense_14 (Dense)             (None, 20)                220       
_________________________________________________________________
activation_2 (Activation)    (None, 20)                0         
_________________________________________________________________
dense_15 (Dense)             (None, 30)                630       
_________________________________________________________________
activation_3 (Activation)    (None, 30)                0         
_________________________________________________________________
dense_16 (Dense)             (None, 40)                1240      
_________________________________________________________________
activation_4 (Activation)    (None, 40)                0         
_________________________________________________________________
dense_17 (Dense)             (None, 50)                2050      
_________________________________________________________________
activation_5 (Activation)    (None, 50)                0         
_________________________________________________________________
dense_18 (Dense)             (None, 60)                3060      
_________________________________________________________________
activation_6 (Activation)    (None, 60)                0         
_________________________________________________________________
dense_19 (Dense)             (None, 70)                4270      
_________________________________________________________________
activation_7 (Activation)    (None, 70)                0         
_________________________________________________________________
dense_20 (Dense)             (None, 80)                5680      
_________________________________________________________________
activation_8 (Activation)    (None, 80)                0         
_________________________________________________________________
dense_21 (Dense)             (None, 90)                7290      
_________________________________________________________________
activation_9 (Activation)    (None, 90)                0         
_________________________________________________________________
dense_22 (Dense)             (None, 100)               9100      
_________________________________________________________________
activation_10 (Activation)   (None, 100)               0         
_________________________________________________________________
dense_23 (Dense)             (None, 1)                 101       
=================================================================
Total params: 33,661
Trainable params: 33,661
Non-trainable params: 0
_________________________________________________________________
history=model.fit(time,y,epochs=500,verbose=0)
x_test=np.linspace(time[0],time[-1],1000)
predecir=model.predict(x_test)
plt.figure(figsize=(15,8))
plt.plot(time[0:300],y[0:300],'-', label='Data')
plt.plot(x_test[0:300],predecir[0:300],'r',label='Model')
plt.title('Plotting Model vs Data')
plt.legend(loc=0)
plt.show()
../../_images/Hello_World_ML_61_0.png
plt.figure(figsize=(15,8))
plt.plot(history.history['loss'],'r-',label='Model')
plt.title('Plotting Model vs Data')
plt.legend(loc=0)
plt.show()
../../_images/Hello_World_ML_62_0.png