sábado, 20 de febrero de 2021

AWS in a nutshell 10: Despliegue de una Instancia EC2

10.1 Despliegue desde la GUI


Amazon EC2 (Elastic Compute Cloud)  proporciona una amplia selección de tipos de instancias optimizados para adaptarse a diferentes casos de uso. La abrimos desde la consola de AWS → EC2 → (panel lateral izquierdo ) Instances

Despliegue de una Instancia EC2



Se puede hacer también a través de comandos CLI y PowerShell tomando de la consola el número ID de la instancia deseada.

10.2 Administración de instancias de Windows EC2

Podemos administrar de forma remota instancias EC2 basadas en Windows mediante el Protocolo de escritorio remoto o RDP. Nuestra instancia puede tener una dirección IP pública, por lo que se puede conectar directamente a través de RDP, lo que podría presentar un riesgo de seguridad. O puede tener un cuadro de salto a través del cual se conecta para, en última instancia, administrar de forma remota nuestras instancias de Windows en AWS.

Administración de instancias de Windows EC2 en AWS


Lo mismo si elegimos Linux

10.3 Tamaño de la instancia EC2

El tipo de instancia EC2, también llamado a veces tamaño de instancia, determina la potencia subyacente en términos de CPU virtuales y la cantidad de RAM. Estas cosas controlan la cantidad de recursos disponibles para ejecutar una carga de trabajo dentro de una instancia EC2. Podemos configurarlo al iniciar la instancia, o una vez creada esta. Cuando configuremos nuestra instancia es importante asegurarse de esté detenida. 

Tamaño de la instancia EC2 de AWS


10.4 Scripts de lanzamiento de EC2

Cuando lanzamos una nueva instancia EC2, hay ocasiones en las que es posible que deseemos que ciertos comandos se ejecuten automáticamente cuando se inicie. Por ejemplo al instalar ciertos paquetes o aplicar ciertas actualizaciones. Para hacerlo podemos utilizar un script de lanzamiento de EC2 que podemos colocar dentro de la sección de datos del usuario cuando lanzamos una instancia de EC2. 

10.5 Reservas de instancias programadas de EC2

Por conveniencia y ahorro de costos, podemos utilizar las reservas de instancias EC2 programadas. Una reserva significa que nos estamos comprometiendo, por ejemplo, por un período de un año, pero también podemos programar instancias EC2 para que se ejecuten en determinados momentos. Diariamente o semanalmente, por ejemplo para el procesamiento por lotes de algún tipo.

Consola → EC2 → (panel lateral izquierdo ) Scheduled Instances → Purchase Scheduled Instances (botón)

10.6 AMI personalizadas

na imagen de máquina de Amazon, o AMI,  define el volumen de arranque raíz siguiendo el sistema operativo y el tipo de sistema operativo. Aunque hay muchas AMI entre las que podemos elegir, también podemos crear nuestra propia AMI personalizada.

sábado, 13 de febrero de 2021

Instalar TensorFlow en un entorno virtual de Windows (Corrige warning is not on PATH)

Hace un tiempo publiqué cómo crear un  entorno Virtual para Machine Learning e instalar TensorFlow sobre él.

Pero cuando lo intenté en otro equipo, falló la actualización de pip. Aquí reproduzco un camino alternativo por si la primera opción falla, igual que me sucedió a mi.

Siguiendo las instrucciones iniciales, para actualizar pip a la última versión tecleamos en el editor de Anaconda  

Python –m pip install –user –U pip

Pero nos devuelve un warning, si lo ignoramos y continuamos, TensorFlow no se instala correctamente.

Instalar TensorFlow en un entorno virtual de Windows

Nos devuelve un WARNING diciendo: ‘The scripts pip.exe, pip3.7.exe and pip3.exe are installed in ‘C:\Users\[mi usuario]\AppData\Roaming\Python\Python37\Scripts’ wich is not on PATH’

Para solucionar este warning tenemos que copiar en el portapapeles la dirección indicada 

"C:\Users\[mi usuario]\AppData\Roaming\Python\Python37\Scripts" 

Vamos al explorador de Windows y pulsamos sobre ‘Este equipo’ con el botón derecho del ratón, nos abre un diálogo y elegimos propiedades y configuración avanzada del sistema.

 

The scripts pip.exe, pip3.7.exe and pip3.exe are installed in ‘C:\Users\[mi usuario]\AppData\Roaming\Python\Python37\Scripts

También podemos acceder desde Panel de control -> Sistema y seguridad -> sistema

Configuración avanzada de sistema

Y pulsamos sobre el botón 'Variables de entorno'.

Se nos abre una pantalla con las variables de entorno, en la caja inferior de variables de sistema pulsamos sobre nueva y en la caja de Nombre de variable, pegamos la ruta copiada anteriormente en el portapapeles. Y en el valor de la variable ponemos punto y coma “;”aceptamos y continuamos con el proceso de instalar TensorFlow.

 

Variables de entorno del sistema

 

Variables de entorno

Actualizar pip

Creamos el Nuevo entorno virtual

                Creamos el Nuevo entorno virtual

Volvemos al entorno con cd..

Antes de traer Tensorflow actualizamos 

Instalar TensorFlow en un entorno virtual de Windows

python.exe -m pip install --upgrade pip

y finalmente instalamos TensorFlow

python -m pip install -U tensorflow

Ya podemos ejecutar un cuaderno Jupyter desde nuestro entorno virtual (tecleamos Jupyter en inicio de windows) para probar si se ha instalado correctamente, nos debe devolver la versión de TensorFlow al escribir

import tensorflow as tf

from tensorflow import keras

tf.__version__

keras.__version__

Comprobar instalación Tensorflow



 



sábado, 6 de febrero de 2021

AWS in a nutshell 9: Estrategias de desarrollo

 9.1 Framework bien diseñado WA de AWS 

Un Framework bien diseñado de AWS permite medir cargas de trabajo de software, la arquitectura de nuestras cargas de trabajo, y se encuadra en las buenas prácticas de AWS. La idea es que buscamos una mejora constante. Esto significa analizar la excelencia operativa, la optimización de costos, la confiabilidad, la eficiencia del desempeño y, por supuesto, la seguridad. Las herramientas de AWS bien diseñada, o WA, está disponible directamente en la Consola de administración de AWS para medir las cargas de trabajo de aplicaciones existentes y luego documentarlas. El primer pilar de un marco bien diseñado es la excelencia operativa.

Framework bien diseñado WA de AWS


9.2 Aplicaciones web de varios niveles

Una aplicación web de varios niveles es aquella que consta esencialmente de varias capas para cada parte principal de una aplicación. Como ejemplo, si tenemos un dispositivo cliente que se conecta a una aplicación web. Esa conexión podría establecerse con un equilibrador de carga que se encuentra entre el cliente y la aplicación. Lo que seguiría después, es que el balanceador de carga enrute las solicitudes del cliente a un servidor backend activo o receptivo que admita la interfaz de la aplicación. Eso se llamaría el nivel de presentación.

9.3 Integración e implementación continuas

Actualmente la mayoría de las organizaciones tienen algún tipo de presencia en la web, y ahí es donde la integración y entrega continuas, o CI y CD, realmente pueden ayudar, aunque no está vinculado específicamente a una presencia web o una aplicación web para el caso. En realidad, se trata de DevOps, lo que realmente significa que estamos combinando el desarrollo de soluciones de software y el lado operativo, que incluirá la implementación y el parcheo a lo largo del tiempo. Por lo tanto, combina desarrollo de software, operación de software y mantenimiento de software.

9.4 Soluciones AWS CI / CD 

Para los desarrolladores, una parte importante de los servicios web de Amazon es saber cuándo utilizar los servicios disponibles para desarrolladores, para eso están las soluciones AWS CI / CD, CI y CD, lo que significa Integración continua e Implementación continua. El principal beneficio de las soluciones CI / CD es un tiempo de comercialización más rápido, por así decirlo, para las soluciones de software, y eso siempre es importante. Tener una solución implementada más temprano que tarde siempre es beneficioso para una organización. La primera solución es AWS CodePipeline, luego tenemos AWS CodeCommit,  AWS CodeBuild. y finalmente AWS CodeDeploy. 

9.5 API de AWS 

Los desarrolladores de software estarán familiarizados con las API o interfaces de programación de aplicaciones. Las API tienen un ciclo de vida específico. El ciclo de vida de la API comienza cuando el desarrollador crea o define una API. Por ejemplo, en Amazon Web Services, un equipo en algún momento tuvo que crear la API de S3 para permitir el acceso programático al entorno de S3. La siguiente fase del ciclo de vida de la API es implementar la solución, lo que generalmente significa ponerla a disposición en un servidor.

API de AWS

9.6 Microservicios y desacoplamiento 

El microservicio no es una oferta de servicios de AWS. En cambio, es más un enfoque o estrategia de desarrollo de software. Con microservicios, estamos hablando de desarrollo de software modular. Entonces, en lugar de crear una aplicación gigante, los equipos de desarrollo pueden trabajar juntos para crear funciones específicas de tareas o API, o incluso contenedores aislados que contienen componentes de software específicos. Con un entorno de microservicio, cada módulo o microservicio puede comunicarse con otros a través de la red. También podemos habilitar el acoplamiento suelto. Así es realmente cómo se construye el código.

9.7 Servicio de notificación simple 

El servicio de notificación simple, o SNS, en Amazon Web Services proporciona una forma de publicar notificaciones o mensajes. También proporciona una forma para que otros recursos se suscriban a los mensajes que se publican. La forma en que esto funciona con SNS es que permite el desacoplamiento de software, esto significa que se permite el uso de microservicios para suscribirse a mensajes que podrían ser publicados por otros componentes de software. La parte de desacoplamiento significa que los componentes de software, no tienen que estar disponibles en la red al mismo tiempo y no tienen que estar ejecutándose al mismo tiempo necesariamente para intercambiar esos mensajes.

Para acceder a ellos desde la Consola de AWS escribimos 

SNS → Escribimos nombre de topic y botón Next

Servicio de notificación simple AWS

9.8 Servicio de cola simple  

En Amazon Web Services, Simple Queue Service, o SQS, se utiliza como mecanismo para microservicios. Ahora no tiene por qué ser así, pero los microservicios se benefician de esto cuando el censo de los microservicios que son software modular o componentes de código, podemos pensar en ellos como fragmentos de código enfocados, que juntos muchos microservicios pueden formar una sola aplicación.

Consola → SQS -> get started now 

Servicio de cola simple AWS


sábado, 30 de enero de 2021

Construyendo una red neuronal de regresión utilizando la API Sequential de Keras

Vamos a utilizar la API Sequential de Keras para crear una red neuronal, secuencial, entrenarla y evaluarla. Podemos utilizar esta red neuronal de regresión para hacer predicciones. Para poder trabajar tendremos que importar las librerías de tensorflow, numpy y keras.

import tensorflow as tf

import numpy as np

from tensorflow import keras

Antes de nada para tener un dataset de ejemplo sobre el que trabajar vamos a descargar un dataset de Scikit-Learn llamado fetch_california_housing() con datos numéricos de inmuebles de California.

from sklearn.datasets import fetch_california_housing

from sklearn.model_selection import train_test_split

from sklearn.preprocessing import StandardScaler

 

housing = fetch_california_housing()

 

X_train_full, X_test, y_train_full, y_test = train_test_split(housing.data, housing.target, random_state=42)

X_train, X_valid, y_train, y_valid = train_test_split(X_train_full, y_train_full, random_state=42)

 

scaler = StandardScaler()

X_train = scaler.fit_transform(X_train)

X_valid = scaler.transform(X_valid)

X_test = scaler.transform(X_test)

 

np.random.seed(42)

tf.random.set_seed(42)

Hacer predicciones con regresión es bastante similar a hacerlo con clasificación, una de las diferencias,  es el hecho de que la capa de salida es una única neurona (si sólo deseamos predecir un único valor), otra que  utilizamos la función de activación relu, y finalmente que la función de pérdida es el error cuadrático medio. Para este caso, como el dataset tiene bastante ruido, utilizaremos una capa oculta para evitar el sobreentrenamiento.

A continuación la creación de la red neuronal con la API de Keras.

model = keras.models.Sequential([

    keras.layers.Dense(30, activation="relu", input_shape=X_train.shape[1:]),

    keras.layers.Dense(1)

])

model.compile(loss="mean_squared_error", optimizer=keras.optimizers.SGD(lr=1e-3))

history = model.fit(X_train, y_train, epochs=20, validation_data=(X_valid, y_valid))

mse_test = model.evaluate(X_test, y_test)

X_new = X_test[:3]

y_pred = model.predict(X_new)

Como podemos ver, la API Sequential es bastante fácil de utilizar, pero si queremos crear redes neuronales con topologías más complejas que la secuencial, podemos utilizar la API Functional.

Construyendo redes neuronales complejas utilizando la API Functional de Keras

En este caso construiremos una red neuronal con capas ocultas y un atajo de este estilo.

Construyendo una red neuronal de regresión utilizando la API Sequential de Keras

El código con la API de keras  será como este.

entrada = keras.layers.Input(shape=X_train.shape[1:])

oculta1 = keras.layers.Dense(30, activation="relu")(entrada)

oculta2 = keras.layers.Dense(30, activation="relu")(oculta1)

concat = keras.layers.concatenate([entrada, oculta2])

salida = keras.layers.Dense(1)(concat)

model = keras.models.Model(inputs=[entrada], outputs=[salida])

Podemos ver un esquema de la red neuronal creada

model.summary()

 

esquema de la red neuronal creada  model.summary

Veamos lo que significan las líneas de código

En primer lugar necesitamos crear un objeto entrada, lo creamos especificando el tipo de modelo que queremos, incluyendo su forma y su tipo.

Después creamos una capa oculta densa con 30 neuronas utilizando la activación ReLU y le pasamos su entrada como si fuera una función, en nuestro caso (entrada).

Creamos una segunda capa oculta y la usamos de nuevo como si fuera una función, pasandole la salida de la primera capa oculta.

Después creamos la capa concatenada y una vez más la usamos como si fuera una función, concatenando la entrada y la salida de la segunda capa oculta en los parámetros de la función.

Creamos la capa de salida con una única neurona y sin función de activación y la usamos como una función pasandole como parámetro la salida de la capa de concatenación.

Finalmente creamos el modelo Keras, especificando cuales son sus entradas y sus salidas.

Una vez creado el modelo procedemos como siempre, compilándolo,  evaluándolo y utilizándolo para hacer predicciones.

model.compile(loss="mean_squared_error", optimizer=keras.optimizers.SGD(lr=1e-3))

history = model.fit(X_train, y_train, epochs=20,

                    validation_data=(X_valid, y_valid))

mse_test = model.evaluate(X_test, y_test)

y_pred = model.predict(X_new)

Pero ¿Que sucede si lo que queremos es enviar un subset de datos por el atajo y el otro por el camino habitual? Tal y como se muestra en el esquema.

Red neuronal Keras con dos entradas

entrada_A = keras.layers.Input(shape=[5], name="atajo")

entrada_B = keras.layers.Input(shape=[6], name="profunda")

oculta1 = keras.layers.Dense(30, activation="relu")(entrada_B)

oculta2 = keras.layers.Dense(30, activation="relu")(oculta1)

concat = keras.layers.concatenate([entrada_A, oculta2])

salida = keras.layers.Dense(1, name="salida")(concat)

model = keras.models.Model(inputs=[entrada_A, entrada_B], outputs=[salida])

El código es muy similar al anterior, sólo  que ahora en las entradas hemos añadido entrada_A y entrada_B ahora vamos a compilarlo, pero en vez de pasarle una sola matriz de entrada X_train le pasaremos dos matrices, X_train_A y X_train_B, igual deberemos hacer con X_valid para la evaluación y X_text para la predcción.


model.compile(loss="mse", optimizer=keras.optimizers.SGD(lr=1e-3))

 

X_train_A, X_train_B = X_train[:, :5], X_train[:, 2:]

X_valid_A, X_valid_B = X_valid[:, :5], X_valid[:, 2:]

X_test_A, X_test_B = X_test[:, :5], X_test[:, 2:]

X_new_A, X_new_B = X_test_A[:3], X_test_B[:3]

 

history = model.fit((X_train_A, X_train_B), y_train, epochs=20,

                    validation_data=((X_valid_A, X_valid_B), y_valid))

mse_test = model.evaluate((X_test_A, X_test_B), y_test)

y_pred = model.predict((X_new_A, X_new_B))

 


sábado, 23 de enero de 2021

Clasificador de imágenes con una red neuronal Keras

Ya hemos comentado aquí lo que es una red neuronal, ahora vamos a descargar el dataset MNIST  de prendas de ropa que contiene 60.000 imágenes de prendas de vestir en escala de grises de 28x28 pixels. El dataset contiene 10 categorías o clases de prendas de vestir. Previamente tendremos instalado en nuestro equipo un entorno virtual de Anaconda con Tensorflow instalado (enlace), o podemos optar también por ejecutar las instrucciones en la nube con Colaboratory.

Hecho esto importamos Tensorflow y Keras 

import tensorflow as tf

from tensorflow import keras

Cargamos el dataset de Moda de MNIST

fashion_mnist = keras.datasets.fashion_mnist

(X_train_full, y_train_full), (X_test, y_test) = fashion_mnist.load_data()

Si hacemos

X_train_full.shape

Nos devuelve  (60000, 28, 28) lo que significa que contiene 60.000 imágenes de 28 por 28 pixels.

Dividimos el dataset de entrenamiento completo en un dataset de validación y otro de entrenamiento (más pequeño). También escalamos las intensidades de píxeles para dejarlas dentro del rango 0-1, como sus valores van de 0 a 255 las dividimos entre 255, esto hace que pasen a ser valores flotantes.

X_valid, X_train = X_train_full[:5000] / 255, X_train_full[5000:] / 255

y_valid, y_train = y_train_full[:5000], y_train_full[5000:]

X_test = X_test / 255

Vamos a mostrar una imagen del conjunto

plt.imshow(X_train[23], cmap="binary")

plt.axis('off')

plt.show()

En este caso hemos tomado al azar el número 23 que ha resultado ser una bota.

class_names = ["Camiseta""Pantalones""Jersey""Vestido""Abrigo","Sandalia""Camisa""Deportivas""Bolso""Bota"]

Por ejemplo elegimos la etiqueta de nuestra imagen 23.

class_names[y_train[23]]

Clasificador de imágenes con una red neuronal Keras

En nuestro caso está clasificada como deportivas.

El dataset de validación contiene 5000 imágenes y el dataset de prueba contiene 10000 imágenes:

X_valid.shape

X_test.shape

Crear un modelo usando la API Secuencial

Ahora vamos a construir una red neuronal  con dos capas ocultas

model = keras.models.Sequential()

model.add(keras.layers.Flatten(input_shape=[2828]))

model.add(keras.layers.Dense(300, activation="relu"))

model.add(keras.layers.Dense(100, activation="relu"))

model.add(keras.layers.Dense(10, activation="softmax"))

La primera fila crea el modelo secuencial, la segunda línea crea una capa de entrada aplanada (Flatten), su cometido es convertir cada imagen de 28x28 pixels en un array de una dimensión y 784 bits de tamaño, no tiene parámetros simplemente realiza un preprocesamiento.

La siguiente fila, crea una capa densa de 300 neuronas ( o perceptrones)  y utilizará la función ReLU como función de activación. Cada capa densa gestiona su propia matriz de pesos y contiene todas las conexiones con la capa de entrada, también gestiona los sesgos de cada neurona (Bias). 

La siguiente línea añade una segunda capa de 100 neuronas. Finalmente añadimos una capa de salida de 10 neuronas, una por clase. Y utiliza softmax como función de activación pues las 10 clases son exclusivas.

En vez de añadir las capas una por una, podemos pasar una lista de las capas al crear el modelo secuencial.

model = keras.models.Sequential([

    keras.layers.Flatten(input_shape=[2828]),

    keras.layers.Dense(300, activation="relu"),

    keras.layers.Dense(100, activation="relu"),

    keras.layers.Dense(10, activation="softmax")

])

Si queremos saber las capas que tiene nuestro modelo podemos hacer 

model.layers

También podemos ver un pequeño resumen de nuestra red poniendo

model.summary()

Y para ver un esquema 

keras.utils.plot_model(model, "mnist_modelo_prendas_ropa.png", show_shapes=True)

Esquema de una red neuronal keras

Para obtener el nombre de la primera capa oculta

hidden1 = model.layers[1]

hidden1.name

Esta devuelve true si la capa es oculta

model.get_layer(hidden1.name) is hidden1

Todos los parámetros de una capa pueden ser accedidos utilizando los métodos get_weights() y set_weghts() si la capa es densa, incluye los pesos de las conexiones y los términos de sesgo (bias).

weights, biases = hidden1.get_weights()

weights

weights.shape

biases

biases.shape

Compilando el modelo

Después de crear nuestro modelo necesitamos compilarlo, para ello llamamos al método compile 

model.compile(loss="sparse_categorical_crossentropy",

              optimizer="sgd",

              metrics=["accuracy"])

Para especificar la función de pérdida y el optimizador a utilizar. Opcionalmente podemos especificar una lista de métricas extra para computar durante el entrenamiento y evaluación.

hemos utilizado sparse_categorical_crossentropy porque tenemos etiquetas escasas (una por instancia) y las clases son exclusivas. Respecto al optimizador sgd significa que vamos a entrenar el modelo utilizando Descenso de gradiente estocástico simple (Stochastic Gradient Descent). Finalmente debido a que es un clasificador, es útil medir su exactitud "accuracy" durante su entrenamiento y evaluación.

Entrenando y evaluando el modelo

Ahora el modelo está preparado para ser entrenado, para ello llamamos al método fit().

history = model.fit(X_train, y_train, epochs=30,

                    validation_data=(X_valid, y_valid))

Para entrenar el modelo, le pasamos las características de entrada X_train y las clases objetivo y_train así como el número de épocas a entrenar, también le pasamos el set de validación aunque esto último es opcional. 

Keras mide la perdida y otras métricas del modelo al final de cada época, lo cual es muy útil para ver cómo se va entrenando el modelo.

Entrenar un modelo

Para ver los diferentes parámetros del entrenamiento

history.params

print(history.epoch)

history.history.keys()

Si creamos un diccionario con estos valores, podemos visualizar las gráficas del entrenamiento.

import pandas as pd

pd.DataFrame(history.history).plot(figsize=(85))

plt.grid(True)

plt.gca().set_ylim(01)

save_fig("curvas_de_aprendizaje_keras")

plt.show()


Visualizar entrenamiento de un modelo keras

Una vez estamos satisfechos con la exactitud del modelo podemos evaluar el set para estimar el error antes de desplegarlo en producción. Podemos hacerlo fácilmente con el método evaluate().

model.evaluate(X_test, y_test)

313/313 [==============================] - 0s 2ms/step - loss: 0.3364 - accuracy: 0.8812

[0.33643999695777893, 0.8812000155448914]

Utilizando el modelo para hacer predicciones

A continuación utilizaremos el método predict() para hacer predicciones sobre nuevas instancias. Como no tenemos nuevas instancias reales, vamos a utilizar las cuatro primeras instancias del dataset

X_new = X_test[:4]

y_proba = model.predict(X_new)

y_proba.round(2)

array([[0.  , 0.  , 0.  , 0.  , 0.  , 0.  , 0.  , 0.01, 0.  , 0.99],

       [0.  , 0.  , 1.  , 0.  , 0.  , 0.  , 0.  , 0.  , 0.  , 0.  ],

       [0.  , 1.  , 0.  , 0.  , 0.  , 0.  , 0.  , 0.  , 0.  , 0.  ],

       [0.  , 1.  , 0.  , 0.  , 0.  , 0.  , 0.  , 0.  , 0.  , 0.  ]],

      dtype=float32)

Para cada instancia estima una probabilidad por clase entre la 0 y la 9, para la primera instancia ha estimado una probabilidad de 0,99 a la clase 9 que es una bota, y 0,01 para la clase 7 que es deportivas. Lo mismo para el resto de instancias.

Si queremos obtener sólo un valor para la clase de mayor probabilidad, en vez del método predict() utilizaremos np.argmax().

y_pred =np.argmax(model.predict(X_new), axis=-1)

y_pred

array([9, 2, 1, 1])

para ver el significado de cada clase hacemos

np.array(class_names)[y_pred]

array(['Bota', 'Jersey', 'Pantalones', 'Pantalones'], dtype='<U10')

y para ver las imágenes

plt.figure(figsize=(7.22.4))

for index, image in enumerate(X_new):

    plt.subplot(14, index + 1)

    plt.imshow(image, cmap="binary", interpolation="nearest")

    plt.axis('off')

    plt.title(class_names[y_test[index]], fontsize=12)

plt.subplots_adjust(wspace=0.2, hspace=0.5)

save_fig('imagenes_predichas', tight_layout=False)

plt.show()

Mostrar imágenes de un dataset con keras