Deep Learning | Aprende Machine Learning https://ftp.aprendemachinelearning.com en Español Tue, 22 Oct 2024 20:43:33 +0000 en-US hourly 1 https://wordpress.org/?v=6.6.2 https://ftp.aprendemachinelearning.com/wp-content/uploads/2017/11/cropped-icon_red_neuronal-1-32x32.png Deep Learning | Aprende Machine Learning https://ftp.aprendemachinelearning.com 32 32 134671790 ¿Cómo funcionan los Transformers? en Español https://ftp.aprendemachinelearning.com/como-funcionan-los-transformers-espanol-nlp-gpt-bert/ https://ftp.aprendemachinelearning.com/como-funcionan-los-transformers-espanol-nlp-gpt-bert/#comments Tue, 08 Nov 2022 08:54:00 +0000 https://www.aprendemachinelearning.com/?p=7771 El Machine Learning cambió para siempre con la llegada en 2017 de un paper llamado Attention is all you need en donde se presentaba una nueva arquitectura para NLP: Los Transformers

The post ¿Cómo funcionan los Transformers? en Español first appeared on Aprende Machine Learning.

]]>
Imagen creada por el Autor utilizando el modelo de text-to-img StableDiffusion

Los Transformers aparecieron como una novedosa arquitectura de Deep Learning para NLP en un paper de 2017 “Attention is all you need” que presentaba unos ingeniosos métodos para poder realizar traducción de un idioma a otro superando a las redes seq-2-seq LSTM de aquel entonces. Pero lo que no sabíamos es que este “nuevo modelo” podría ser utilizado en más campos como el de Visión Artificial, Redes Generativas, Aprendizaje por Refuerzo, Time Series y en todos ellos batir todos los records! Su impacto es tan grande que se han transformado en la nueva piedra angular del Machine Learning.

En este artículo repasaremos las piezas fundamentales que componen al Transformer y cómo una a una colaboran para conseguir tan buenos resultados. Los Transformers y su mecanismo de atención posibilitaron la aparición de los grandes modelos generadores de texto GPT2, GPT3 y BERT que ahora podían ser entrenados aprovechando el paralelismo que se alcanza mediante el uso de GPUs.

Agenda

  • ¿Qué son los transformers?
  • Arquitectura
    • General
    • Embeddings
    • Positional Encoding
    • Encoder
      • Mecanismo de Atención
      • Add & Normalisation Layer
      • Feedforward Network
    • Decoder
    • Salida del Modelo
  • Aplicaciones de los Transformers
    • BERT
    • GPT-2
    • GPT-3
  • Resumen

¿Qué son los transformers en Machine Learning?

En el paper original de 2017 “Attention is all you need” aparece el diagrama con la novedosa arquitectura del Transformer, que todos deberíamos tatuarnos en un brazo. Esta arquitectura surge como una solución a problemas de aprendizaje supervisado en Procesamiento del Lenguaje Natural, obteniendo grandes ventajas frente a los modelos utilizados en ese entonces. El transformer permitía realizar la traducción de un idioma a otro con la gran ventaja de poder entrenar al modelo en paralelo; lo que aumentaba drásticamente la velocidad y reducción del coste; y utilizando como potenciador el mecanismo de atención, que hasta ese momento no había sido explotado del todo. Veremos que en su arquitectura utiliza diversas piezas ya existentes pero que no estaban combinadas de esta manera. Además el nombre de “Todo lo que necesitas es Atención” es a la vez un tributo a los Beatles y una “bofetada” a los modelos NLP centrados en Redes Recurrentes que en ese entonces estaban intentando combinarlos con atención. De esta sutil forma les estaban diciendo… “tiren esas redes recurrentes a la basura”, porque el mecanismo de atención NO es un complemento… es EL protagonista!

All you need is Love Attention

The Beatles

Con el tiempo, esta arquitectura resultó ser flexible y se pudo utilizar para tareas más allá del NLP, además de para la generación de texto, clasificación, resumen de contenidos también pudo traspasar esa frontera y ser aplicado en Visión Artificial, Generación de Audio, Predicción de Series Temporales y Aprendizaje por Refuerzo.

La Arquitectura Encoder-Decoder del Transformer

Veamos primero la gran foto de los Transformers.

Visión General

Estás viendo el dibujo que deberías de llevar en tu próxima camiseta:

La Arquitectura de los Transformers

La primera impresión puede ser algo intimidante, pero vayamos poco a poco. Si pensamos en el modelo como una caja negra, sería simplemente:

Entrada -> Transformer -> Salida

Vemos que con una entrada de texto “Hola” obtenemos la salida “Hello”.

Si hacemos un poco de zoom en esa caja, veremos dos componentes principales: Encoders y Decoders.

La entrada pasará por una serie de Encoders que se encadenan uno tras otro y luego envían su salida a otra serie de Decoders hasta emitir la Salida final. En el paper original, se utilizan 6 encoders y 6 decoders. Notaremos un recuadro llamado “Target” donde estamos pasando el Output Deseado al modelo para entrenar; pero obviamente que no lo pasaremos al momento de la inferencia; al menos no completo (más adelante en el artículo).

Observamos ahora con mayor detalle cómo está compuesto un Encoder y un Decoder y veremos que son bastante parecidos por dentro.

En su interior tanto Encoder como decoder cuentan con un componente de Atención (o dos) y una red neuronal “normal” como salidas.

Para comenzar a evaluar con mayor detalle las partes del Transformer, primero deberemos generar un Embedding de la entrada y luego entrar al Encoder. Así que veamos eso primero.

Embeddings

El uso de embeddings existía en NLP desde antes de los Transformers, puede que estés familiarizado con modelos como el word-2-vec y puede que ya hayas visto las proyecciones creadas con miles de palabras donde los embeddings logran agrupar palabras de manera automática en un espacio multidimensional. Entonces conceptos como “hombre y mujer”, distanciado de “perro y gato” veremos nombres de países juntos y profesiones ó deportes también agrupados en ese espacio. Primero convertimos las palabras a tokens, es decir a un valor numérico asociado, porque recordemos que las redes neuronales únicamente pueden procesar números y no cadenas de texto.

Ejemplo de Word Embeddings y una proyección en 3D.

Entonces convertimos una palabra a un número, ese número a un vector de embeddings de 512 dimensiones (podría ser de otro valor, pero el propuesto en el paper fue este).

Entonces:

  1. Palabra -> Token(*)
  2. Token -> Vector n-dimensional

(*) NOTA: una palabra podría convertirse en más de un token

La parte novedosa que introduce el paper de los transformers, es el “Positional Encoding” a esos embeddings…

Positional Encoding

Una vez que tenemos los embeddings, estaremos todos de acuerdo que el orden en que pasemos las palabras al modelo, será importante. De hecho podríamos alterar totalmente el significado de una oración si mezclamos el orden de sus palabras o hasta podría carecer totalmente de significado.

La casa es verde != verde casa la es

Entonces necesitamos pasar al modelo los tokens pudiendo especificar de alguna manera su posición.

Aquí, de paso comentaremos dos novedades de los Transformers: la solución a este posicionamiento pero también esto permite el poder enviar en simultáneo TODOS los tokens al modelo, algo que anteriormente no se podía hacer, por lo que se pasaba “palabra por palabra” una después de la otra, resultando en una menor velocidad.

Para resolver el posicionamiento, se agrega una valor secuencial al embedding que se asume que la red podrá interpretar. Si aparece el token “perro” como segunda palabra ó como décima, mantendrá en esencia el mismo vector (calculado anteriormente en el embedding) pero con un ligero valor adicional que lo distinguirá y que será el que le de la pista a la red neuronal de interpretar su posición en la oración.

En el paper se propone una función sinusoidal sobre el vector de 512 dimensiones del embedding. Entonces ese vector de embeddings del token “perro” será distinto si la palabra aparece primera, segunda, tercera.

Y ahora sí, podemos dar entrada al Encoder de los Transformers.

Encoder

El Encoder está compuesto por la capa de “Self attention” y esta conectada a una red feed forward. Entre las entradas y salidas se aplica la Skip Connection (ó ResNet) y un Norm Layer.

El mecanismo de Atención, es una de las implementaciones novedosas que propone el paper. Veremos que logra procesar en paralelo, manteniendo la ventaja de entreno mediante GPU.

El Encoder tiene como objetivo procesar la secuencia de los tokens de entrada y ser a su vez la entrada del mecanismo de atención del Decoder. No olvides que realmente se encadenan varios Encoders con varios Decoders (no se utilizan sólo uno en la práctica).

El -dichoso- mecanismo de Atención

Primero que nada, ¿Para qué queremos un mecanismo de Atención? El mecanismo de atención nos ayuda a crear y dar fuerza a las relaciones entre palabras en una oración. Si tenemos el siguiente enunciado:

El perro estaba en el salón, durmiendo tranquilo.

Nosotros comprendemos fácilmente que la palabra “tranquilo” se refiere al perro y no al “salón”. Pero a la red neuronal que comienza “en blanco”, sin saber nada de las estructuras del lenguaje (español, pero podría ser cualquier idioma), y que además ve la misma frase como valores numéricos:

5 186 233 7 5 1433 567 721

NOTA: no olvides que cada token, por ej. el nº5 corresponde a un embedding de n-dimensiones de 512 valores. Por simplificar usamos el 5 como reemplazo de “El”, por no escribir sus 512 componentes.

¿Cómo podrá entender que ese último token “721” está afectando a la segunda palabra “186”?
Por eso surgen los mecanismos de atención; para lograr dar más -o menos- importancia a una palabra en relación a las otras de la oración.

La solución que presentan los Transformers en cuanto a la atención, es la construcción de un “Diccionario Blando” (Soft Dictionary). ¿Qué es esto de un diccionario blando?
En programación, es probable que conozcas el uso de diccionarios de tipo “clave-valor” un típico “hashmap” en donde ante una entrada, obtengo un valor dict[“perro”]=0.78.
Para el “diccionario de atenciones” podría ser que si pedimos la atención de “tranquilo vs perro” de la oración, nos devuelva un 1 indicando mucha atención, pero si le pedimos “tranquilo vs salón” nos devuelva un -1.

Pero… eso no es todo. Nuestro Diccionario es “Suave/Blando”, esto quiere decir que no se va a saber “de memoria” el resultado de una clave. Si alteramos un poco la oración, el diccionario tradicional fallaría:

El perro estaba durmiendo en un salón tranquilo.

Ahora la clave de atención para “tranquilo vs salón” deberá pasar de -1 a ser cercana a 1.

Para poder calcular la atención, se utilizan 3 matrices llamadas “Query-Key-Value” que van a operar siguiendo una fórmula que nos devuelve un “score” o puntaje de atención.

  • En la matriz Q de Query tendremos los tokens (su embedding) que estamos evaluando.
  • En la matriz K de Key tendremos los tokens nuevamente, como claves del diccionario.
  • En la matriz V de Value tendremos todos los tokens (su embedding) “de salida”.

El resultado de la atención será aplicar la siguiente fórmula:

Si nos olvidamos del Softmax y el “multihead” (se definirá a continuación), podemos simplificar la fórmula diciendo que:
La atención será multiplicación matricial Q por la transpuesta de K; a eso le llamamos “factor”; y ese factor multiplicado por V.

¿Y eso qué significa? ¿Por qué estamos operando de esa manera? Si recuerdas, tanto Q como K son los valores de los Embeddings, es decir, cada token es un vector n-dimensional. Al hacer el producto vectorial obtenemos matemáticamente la “Similitud” entre los vectores. Entonces si el embedding estuviera funcionando bien, la similitud entre “nieve” y “blanco” deberían estar más cercanas que “nieve” y “negro”. Entonces cuando dos palabras sean similares, tendremos un valor positivo y mayor que si son opuestos, donde obtendríamos un valor negativo (dirección contraria). Este factor se multiplica por la matriz de Valor conformando el Score final de atención para cada relación entre pares de <<palabras>> que estamos evaluando.

Como estamos trabajando con matrices, seguimos aprovechando la capacidad de calcular todo a la vez y poder hacerlo acelerado por GPU.

Más de una atención: Multi-Head Attention

…hay más en el paper, porque el tipo de atención que vamos a calcular se llama “Multi-head Attention“. ¿Qué son esas “Multi-cabezas”??? Lo que se hace es que en vez de calcular la atención de todos los tokens de la oración una vez con las 512 dimensiones (provenientes del embedding), subdividiremos esos valores en grupos y de cada uno, calcular su atención. En el paper proponen “8 heads” con lo que entonces calcularemos “8 atenciones de a 64 valores del embeddings” por cada token! Esto a mi modo de entender es algo bastante arbitrario pero por arte de “magia matemática” funciona… Luego de calcular esas 8 cabezas, (esas 8 atenciones) haremos un promedio de los valores de cada atención entre tokens.

Si volvemos al ejemplo para la clave de “tranquilo vs perro” calcularemos 8 atenciones y al promediarlas deberíamos obtener un valor cercano a 1 (para la 1er oración).

Cuando terminemos de entrenar el modelo Transformer completo, podríamos intentar analizar y entender esas matrices de atención creadas y tratar de comprenderlas. Algunos estudios muestran que la “multi-atención” logra representar relaciones como la de “artículo-sustantivo” ó “adjetivo-sustantivo”, “verbo sustantivo” lo cual me sigue pareciendo algo increíble.

3 tipos de atención: Propia, Cruzada y Enmascarada

Prometo que esto ya es lo último que nos queda comprender sobre los mecanismos de atención… A todo lo anterior, hay que sumar que tenemos 3 tipos distintos de atención

  1. Self Attention
  2. Cross Attention
  3. Masked Attention

Su comportamiento es igual que al descripto anteriormente pero con alguna particularidad:

Self Attention se refiere que crearemos los valores y las matrices de Q-K-V a partir de las propias entradas de los tokens de entrada.

En la Atención Cruzada, vemos cómo utilizamos como entradas en el Decoder los valores obtenidos en el Encoder. Esto es lo que hará que con sólo el valor (Value) del Output pueda modelar la salida de atención buscada, esto es importante porque al final es lo que condicionará mayormente la “traducción” que está haciendo internamente el Decoder!

Y la llamada “Masked attention” se refiere a que enmascaramos parte triangular superior de la matriz de atención al calcularla para no caer en “data-leakage”, es decir, para no “adelantar información futura” que el Output no podría tener en su momento. Esto puede resultar confuso, intentaré aclararlo un poco más. En el Encoder, cuando tenemos los valores de entrada y hacemos “self-attention” dijimos que calculamos la atención de “todos contra todos” porque todos los tokens de entrada son conocidos desde el principio. Si recordamos la frase anterior:

El perro estaba en el salón, durmiendo tranquilo.

Aquí podemos calcular tanto la atención para la clave “perro-tranquilo” y también la de “tranquilo-perro”

Sin embargo -si suponemos que estamos traduciendo al inglés- en el output tendremos

“The dog was in the living room, sleeping peacefully”

PERO hay un detalle; para poder generar el output al momento de la inferencia, generaremos de a una palabra por vez, entonces iremos produciendo el siguiente output:

T1 – The
T2 – The dog
T3 – The dog was
T4 – The dog was in …

Esto quiere decir que vamos generando los tokens de a uno a la vez por lo que al principio no podríamos conocer la relación entre “dog-peacefully” pues esta relación aún no existe!

Entonces diferenciemos esto:

-> Al momento de entrenar el modelo pasamos el output deseado COMPLETO a las matrices de QKV de “Masked Attention” para entrenar en paralelo; al estar enmascarado, es como si estuviésemos simulando la secuencia “The, The dog, The dog was…”

-> Al momento de inferencia REALMENTE tendremos uno a uno los tokens como una secuencia temporal, realmente, iremos agregando de a una palabra del output a la cadena de salida a la vez.

Al enmascarar la matriz Q*K en su diagonal superior, prevenimos obtener valores “futuros” en la relación de atención entre sus tokens.

Short residual skip Connections y Layer Normalization

Al utilizar Skip Connections permitimos mantener el valor de origen del input a través de las deep neural networks evitando que sus pesos se desvanezcan con el paso del tiempo. Esta técnica fue utilizada en las famosas ResNets para clasificación de imágenes y se convirtieron en bloques de construcción para redes profundas. También es sumamente importante la Normalización en RRNN. Previene que el rango de valores entre capas cambie “demasiado bruscamente” logrando hacer que el modelo entrene más rápido y con mayor capacidad de generalización.

Feed Forward Network

La salida final del Encoder la dará una Red Neuronal “normal”, también llamada MLP ó capa densa. Se agregarán dos capas con Dropout y una función de activación no lineal.

Decoder

Ahora que conocemos los componentes del Encoder, podemos ver que con esos mismos bloques podemos crear el Decoder.

Al momento de entrenar, estaremos pasando el Input “hola amigos” y Output “hello friends” (su traducción) al mismo tiempo al modelo.

Tradicionalmente, usamos la salida únicamente para “validar” el modelo y ajustar los pesos de la red neuronal (durante el backpropagation). Sin embargo en el Transformer estamos usando la salida “hello friends” como parte del aprendizaje que realiza el modelo.

Entonces, el output “hello friends” es también la “entrada” del decoder hacia embeddings, posicionamiento y finalmente ingreso a la Masked Self Attention que comentamos antes (para los valores de Q,K,V).

De aquí, y pasando por la Skip Connection y Normalización (en la gráfica “Add & Norm) entramos al segundo mecanismo de Atención Cruzada que contiene para las matrices Query y Key” la salida del Encoder y como Value la salida de la Masked Attention.

Nuevamente Suma y Normalización, entrada a la Feed Forward del Decoder.

RECORDAR: “N encoder y N decoders”

No olvidemos que si bien estamos viendo en mayor detalle “un encoder” y “un decoder”, la arquitectura completa del Transformer implica la creación de (en el paper original) 6 encoders encadenados que enlazan con otros 6 decoders.

Salida final del Modelo

La salida final del modelo pasa por una última capa Lineal y aplicar Softmax. El Softmax, por si no lo recuerdas nos dará un valor de entre 0 y 1 para cada una de las posibles palabras (tokens) de salida. Entonces si nuestro “lenguaje” total es de 50.000 posibles tokens (incluyendo signos de puntuación, admiración, interrogación), encontraremos a uno de ellos con valor más alto, que será la predicción.

Si yo te dijera “en casa de herrero cuchillo de …” y vos tuvieras que predecir la próxima palabra, de entre todas las posibles en el castellano seguramente elegirías “palo” con probabilidad 0,999. Ahí acabas de aplicar Softmax intuitivamente en tu cabeza, y descartaste al resto de 49.999 palabras restantes.

Repaso de la arquitectura

Repasemos los puntos fuertes de la arquitectura de los Transformers:

  • La arquitectura de Transformers utiliza Encoders y Decoders
  • El Transformer permite entrenar en paralelo y aprovechar el GPU
  • Utiliza un mecanismo de atención que cruza en memoria “todos contra todos los tokens” y obtiene un score. Los modelos anteriores como LSTM no podían memorizar textos largos ni correr en paralelo.
  • El mecanismo de atención puede ser de Self Attention en el Encoder, Cross Attention ó Masked Attention en el Decoder. Su funcionamiento es igual en todos los casos, pero cambian los vectores que utilizamos como entradas para Q,K,V.
  • Se utiliza El Input pero también la Salida (el Output del dataset) para entrenar al modelo.

Aplicaciones de los Transformers

Los Transformers se convirtieron en el modelo “de facto” para todo tipo de tareas de NLP, incluyendo Traducción de idiomas (como vimos), clasificación de texto, resumen de textos y Question-Answering. Sólo basta con modificar los datasets que utilizamos para entrenar al modelo y la “salida final del modelo”, manteniendo al resto de arquitectura.

A raíz de poder entrenar mediante GPU, reducción de tiempo y dinero, surgieron varios modelos para NLP que fueron entrenados con datasets cada vez más grandes, con la creencia de que cuantas más palabras, más acertado sería el modelo, llevándolos al límite. Ahora, parece que hemos alcanzado un tope de acuracy, en el cual no vale la pena seguir extendiendo el vocabulario.

Vemos 3 de estos grandes modelos de NLP y sus características

BERT – 2018

BERT (Bidirectional Encoder Representations from Transformers) aparece en 2018, desarrollado por Google y utiliza sólo la parte del Encoder de los Transformers. Este modelo fue entrenado con todos los artículos de la Wikipedia en Inglés que contiene más de 2500 millones de palabras. Esto permitió generar un modelo “pro-entrenado” en inglés muy poderoso que podía ser utilizado para múltiples tareas de NLP. Además, al ser Open Source, permitió la colaboración y extensión por parte de la comunidad científica. El poder utilizar un modelo pre-entrenado tan grande, preciso y potente, permite justamente “reutilizar” ese conocimiento sin necesidad de tener que entrenar nuevamente un modelo de NLP, con el coste y tiempo (e impacto medioambiental) que puede conllevar.

Además BERT contenía algunas novedades, por ejemplo, en vez de utilizar un “Embeddings único y estático”, implementó un mecanismo en donde la misma palabra (token) podría devolver un vector distinto (de “embeddings”) de acuerdo al contexto de la oración de esa palabra.

Cuando salió BERT, batió muchos de los records existentes en datasets como SQuAD, GLUE y MultiNLI.

GPT-2 – 2019

GPT es un modelo de generación de texto creado por Open AI en 2019 y que contiene 1500 millones de parámetros en la configuración de su red neuronal profunda.

Al ser entrenado para generar “siguiente palabra”, pasa a convertirse en un problema de tipo “no supervisado”. Su re-entreno fue realizado usando BooksCorpus, un dataset que contiene más de 7,000 libros de ficción no publicados de diversos géneros.

Este modelo generó polémica en su momento debido a que empezaba a crear textos similares a lo que podía escribir una persona, con lo cual antes de ser lanzado, se temió por su mal uso para generar contenido falso en internet. Había sido anunciado en febrero y recién fue accesible al público, de manera parcial en Agosto. Los modelos de tipo GPT utilizan únicamente la parte de “Decoder” del Transformer.

Ejercicio Práctico: Crea tu propio chatbot con GPT-2 en Español!

GPT-3 – 2020

Lanzado en 2020, la red de GPT-3 tiene 175.000 millones de parámetros. Entrenado con textos de internet que contienen más de 500.000 millones de tokens.

En GPT-3, la generación de textos por la IA puede alcanzar un nivel literario que pasa inadvertido por los humanos, el modelo es capaz de mantener la coherencia en textos largos y debido a su gran conocimiento del mundo, crear un contexto y párrafos muy reales.

Otra de las novedades que trajo GPT3 es que lograba realizar tareas “inesperadas” de manera correcta, sin haber sido entrenado para ello. Por ejemplo, puede realizar Question-Answer, crear diálogos ó hasta escribir código en Python, Java o traducir idiomas. A este tipo de aprendizaje “no buscado” le llamamos “One Shot Learning”.

El Codigo de GPT-3 aún no ha sido liberado, hasta la fecha.

Más allá del NLP

Al comportarse tan bien para tareas de NLP, se comenzó a utilizar esta arquitectura adaptada para Clasificación de imágenes en Computer Vision y también logró superar en muchos casos a las Redes Convolucionales! A este nuevo modelo se le conoce como Vision Transformer o “Vit”.

También podemos utilizar Transformers para pronóstico de Series Temporales (Time Series). Este caso de uso tiene mucha lógica si lo pensamos, porque al final es muy parecido a “predecir la próxima palabra”, pero en su lugar “predecir la próxima venta”, ó stock…

Los Transformers están siendo utilizados en modelos generativos de música o como parte de los modelos de difusión text-to-image como Dall-E2 y Stable Diffusion.

Por último, los Transformers también están siendo utilizados en Aprendizaje por Refuerzo, donde también tienen sentido, pues la fórmula principal de este tipo de problemas también contiene una variable temporal/secuencial.

Y en todos estos campos, recién está empezando la revolución! No digo que será el Transformer quien reemplace al resto de Arquitecturas y modelos de Machine Learning existentes, pero está siendo un buen motivo para cuestionarlos, replantearlos y mejorar!

Resumen

Los Transformers aparecieron en un paper de 2017 implementando un eficiente mecanismo de atención como punto clave para resolver problemas de traducción en el campo del Procesamiento del Lenguaje Natural. Como bien sabemos, el lenguaje escrito conlleva implícitamente un orden temporal, secuencial que hasta aquel entonces era una de las barreras para no poder crear modelos extensos, pues impedía el aprovechamiento de GPU. La nueva arquitectura rompía esa barrera utilizando unos sencillos trucos: utilizar todos los token al mismo tiempo (en vez de uno en uno) y enmascarar la multiplicación matricial para impedir el data leakage en el caso del decoder.

Además, resolvió el Posicionamiento de los token y aprovechó técnicas ya existentes como el uso de Skip Connections y Normalization Layers.

Todo ello posibilitó la creación de los grandes modelos actuales, BERT, GPT y la aparición de muchísimos modelos disponibles “pre-entrenados” que pueden ser descargados y reutilizados para fine-tuning por cualquier persona.

Como si esto fuera poco, los Transformers tienen la flexibilidad suficiente para traspasar el área de NLP y contribuir al resto de áreas del Machine Learning obteniendo resultados impresionantes.

Habrá que agradecer a Ashish VaswaniNoam ShazeerNiki ParmarJakob UszkoreitLlion JonesAidan N. GomezLukasz KaiserIllia Polosukhin por su obra maestra.

Material Extra

Enlaces a más info sobre Transformers!

Suscripción al Blog

Recibe los próximos artículos sobre Machine Learning, estrategias, teoría y código Python en tu casilla de correo!

NOTA: algunos usuarios reportaron que el email de confirmación y/o posteriores a la suscripción entraron en su carpeta de SPAM. Te sugiero que revises y recomiendo que agregues nuestro remitente info @ aprendemachinelearning.com a tus contactos para evitar problemas. Gracias!

El libro del Blog

Si te gustan los contenidos del blog y quieres darme tu apoyo, puedes comprar el libro en papel, ó en digital (también lo puede descargar gratis!).

The post ¿Cómo funcionan los Transformers? en Español first appeared on Aprende Machine Learning.

]]>
https://ftp.aprendemachinelearning.com/como-funcionan-los-transformers-espanol-nlp-gpt-bert/feed/ 1 7771
Detección de Objetos con Python https://ftp.aprendemachinelearning.com/deteccion-de-objetos-con-python-yolo-keras-tutorial/ https://ftp.aprendemachinelearning.com/deteccion-de-objetos-con-python-yolo-keras-tutorial/#comments Wed, 24 Jun 2020 09:16:50 +0000 https://www.aprendemachinelearning.com/?p=7262 Crea tu propia red neuronal convolucional para detección de objetos lego con este simpático tutorial paso a paso

The post Detección de Objetos con Python first appeared on Aprende Machine Learning.

]]>
En este artículo podrás ver de manera práctica cómo crear tu propio detector de objetos que podrás utilizar con imagenes estáticas, video o cámara. Avanzaremos paso a paso en una Jupyter Notebook con el código completo usando redes neuronales profundas con Keras sobre Tensorflow.

Antes de empezar te recomiendo que leas mis artículos anteriores sobre Visión Artificial, que te ayudarán con las bases teóricas sobre las que nos apoyamos en este ejercicio:

Agenda

Tenemos mucho por delante! Antes que nada debo aclarar que próximamente un nuevo artículo explicará toda la teoría que hoy aplicaremos, pero mientras llega… pasemos a la acción!

  • ¿En qué consiste la Detección Yolo?
    • Algunos parámetros de la red
    • El proyecto propuesto
  • Lo que tienes que instalar (y todo el material)
  • Crear un dataset: Imágenes y Anotaciones
    • Recomendaciones para la imágenes
    • Anotarlo todo
    • El lego dataset
  • El código Python
    • Leer el dataset
    • Train y Validación
    • Data Augmentation
    • Crear la red YOLO
    • Crear la red de Detección
    • Generar las Anclas
    • Entrenar
    • Revisar los Resultados
    • Probar la red!
  • Conclusiones
  • Material Adicional

¿En qué consiste la detección YOLO?

Vamos a hacer un detector de objetos en imágenes utilizando YOLO, un tipo de técnica muy novedosa (2016), acrónimo de “You Only Look Once” y que es la más rápida del momento, permitiendo su uso en video en tiempo real.

Esta técnica utiliza un tipo de red Neuronal Convolucional llamada Darknet para la clasificacion de imágenes y le añade la parte de la detección, es decir un “cuadradito” con las posiciones x e y, alto y ancho del objeto encontrado.

La dificultad de esta tarea es enorme: poder localizar las áreas de las imágenes, que para una red neuronal es tan sólo una matriz de pixeles de colores, posicionar múltiples objetos y clasificarlos. YOLO lo hace todo “de una sola pasada” a su red convolucional. En resultados sobre el famoso COCO Dataset clasifica y detecta 80 clases de objetos distintos y etiquetar y posicionar hasta 1000 objetos (en 1 imagen!)

NOTA PARA los Haters del ML (si es que los hay): Este código se basa en varios trozos de código de diversos repos de Github y estaré usando una arquitectura de YOLOv2 aunque sé que es mejor la versión 3 (y de hecho está por salir Yolo v4)… pero recuerden que este artículo es con fines didácticos. No me odies y sé comprensivo, toma tu pastilla todas las noches, gracias.

Aunque ahondaré en la Teoría en un próximo artículo, aquí comentaré varios parámetros que manejaremos con esta red y que debemos configurar.

(Algunos) Parámetros de la red

  • Tamaño de imagen que procesa la red: este será fijo, pues encaja con el resto de la red y es de 416 pixeles. Todas las imágenes que le pasemos serán redimensionadas antes de entrar en la red.
  • Cantidad de cajas por imagen: Estás serán la cantidad de objetos máximos que queremos detectar.
  • etiquetas: estas serán las de los objetos que queramos detectar. En este ejemplo sólo detectaremos 1 tipo de objeto, pero podrían ser múltiples.
  • epochs: la cantidad de iteraciones sobre TODO el dataset que realizará la red neuronal para entrenar. (Recuerda, que a muchas épocas tardará más tiempo y también el riesgo de overfitting)
  • train_times: este valor se refiera a la cantidad de veces de entrenar una MISMA imagen. Esto sirve sobre todo en datasets pequeños, además que haremos algo de data augmentation sobre las imágenes cada vez.
  • saved_weights_name: una vez entrenada la red, guardaremos sus pesos en este archivo y lo usaremos para hacer las predicciones.

El proyecto Propuesto: Detectar personajes de Lego

Será porque soy padre, ó será porque soy Ingeniero… al momento de pensar en un objeto para detectar se me ocurrió: Legos! ¿Quien no tiene legos en su casa?… Por supuesto que puedes crear tu propio dataset de imagenes y anotaciones xml para detectar el ó los objetos que tu quieras.

Lo que tienes que instalar

Primero que nada te recomiendo que crees un nuevo Environment de Python 3.6.+ e instales estas versiones de librerías que usaremos.

En consola escribe:

python -m venv detectaEnv

Y luego lo ACTIVAS para usarlo en windows con:

detectaEnv\Scripts\activate.bat

ó en Linux / Mac con:

source detectaEnv/bin/activate

y luego instala los paquetes:

pip install tensorflow==1.13.2
pip install keras==2.0.8
pip install imgaug==0.2.5
pip install opencv-python
pip install h5py
pip install tqdm
pip install imutils

Aclaraciones: usamos una versión antigua de Tensorflow. Si tienes GPU en tu máquina, puedes usar la versión apropiada de Tensorflow (y CUDA) para aprovecharlo.

Si vas a crear tu propio dataset -como se explica a continuación-, deberás instalar LabelImg, que requiere:

pip install PyQt5
pip install lxml
pip install labelImg

Si no, puedes usar el dataset de legos que provee el blog y saltarte la parte de crear el dataset.

Otros archivos que deberás descargar:

Crea un dataset: Imágenes y Anotaciones

Vale, pues es hora de crear un repositorio de miles de imágenes para alimentar tu red de detección.

En principio te recomendaría que tengas al menos unas 1000 imágenes de cada clase que quieras detectar. Y de cada imagen deberás tener un archivo xml con un formato específico -que en breve comentaré- con la clase y la posición de cada objeto. Al detectar imágenes podemos tener más de un objeto, entonces puedes tener imágenes que tienen a más de un objeto.

Recomendaciones para las imágenes:

Algunas recomendaciones para la captura de imágenes: si vas a utilizar la cámara de tu móvil, puede que convenga que hagas fotos con “pocos megapixeles”, pues si haces una imagen de 4K de 5 Megas, luego la red neuronal la reducirá a 416 pixeles de ancho, por lo que tendrás un coste adicional de ese preprocesado en tiempo, memoria y CPU.

Intenta tener fotos del/los objetos con distintas condiciones de luz, es decir, no tengas imágenes de gatitos “siempre al sol”. Mejor serán imágenes de interior, al aire libre, con poca luz, etc.

Intenta tener imágenes “torcidas”(rotadas), parciales y de distintos tamaños del objeto. Si sólo tienes imágenes en donde tu objeto supongamos que “mide 100 pixeles” mal-acostumbrarás la red y sólo detectará en imágenes cuando sea de esas dimensiones (peligro de overfitting).

Variaciones del mismo objeto: Si tu objeto es un gato, intenta clasificar gatos de distintos colores, razas y en distintas posiciones, para que la red convolucional pueda generalizar el conocimiento.

Anotarlo todo

Muy bien, ya tienes tus imágenes hechas y guardadas en un directorio.

Ahora deberás crear un archivo XML donde anotarás cada objeto, sus posiciones x,y su alto y ancho.

El xml será de este tipo:

Y lo puedes hacer a mano… ó puedes usar un editor como labelImg.

Si lo instalaste mediante Pip, puedes ejecutarlo simplemente poniendo en línea de comandos del environment labelImg. Se abrirá el editor visual y podrás:

  • Seleccionar un directorio como fuente de imágenes.
  • Seleccionar un directorio donde guardará los xml.

En el editor deberás crear una caja (bounding-box) sobre cada objeto que quieras detectar en la imagen y escribir su nombre (clase). Cuando terminas le das a Guardar y Siguiente!

El lego dataset

Puedes utilizar el Lego-Dataset de imágenes y anotaciones (170MB) que creé para este artículo y consta de 300 imágenes. Son fotos tomadas con móvil de diversos personajes lego. Realmente son 100 fotos y 200 variaciones en zoom y recortes. Y sus correspondientes 300 archivos de anotaciones xml.

Dicho esto, recuerda que siempre es mejor más y más imágenes para entrenar.

El código Python

Usaremos Keras sobre Tensorflow para crear la red!, manos a la obra.

En el artículo copiaré los trozos de código más importantes, siempre puedes descargar la notebook Jupyter con el código completo desde Github.

Leer el Dataset

Primer paso, será el de leer las anotaciones xml que tenemos creadas en un directorio e ir iterando los objetos para contabilizar las etiquetas.

NOTA: en este ejemplo, declaro la variable labels con 1 sóla clase “lego”, pero si quieres identificar más podrías poner [“perro”,”gato”] ó lo que sea que contenga tu dataset.

xml_dir = "annotation/lego/"
img_dir = "images/lego/"
labels = ["lego"]
tamanio = 416
mejores_pesos = "red_lego.h5"

def leer_annotations(ann_dir, img_dir, labels=[]):
    all_imgs = []
    seen_labels = {}
    
    for ann in sorted(os.listdir(ann_dir)):
        img = {'object':[]}

        tree = ET.parse(ann_dir + ann)
        
        for elem in tree.iter():
            if 'filename' in elem.tag:
                img['filename'] = img_dir + elem.text
            if 'width' in elem.tag:
                img['width'] = int(elem.text)
            if 'height' in elem.tag:
                img['height'] = int(elem.text)
            if 'object' in elem.tag or 'part' in elem.tag:
                obj = {}
                
                for attr in list(elem):
                    if 'name' in attr.tag:
                        obj['name'] = attr.text

                        if obj['name'] in seen_labels:
                            seen_labels[obj['name']] += 1
                        else:
                            seen_labels[obj['name']] = 1
                        
                        if len(labels) > 0 and obj['name'] not in labels:
                            break
                        else:
                            img['object'] += [obj]
                            
                    if 'bndbox' in attr.tag:
                        for dim in list(attr):
                            if 'xmin' in dim.tag:
                                obj['xmin'] = int(round(float(dim.text)))
                            if 'ymin' in dim.tag:
                                obj['ymin'] = int(round(float(dim.text)))
                            if 'xmax' in dim.tag:
                                obj['xmax'] = int(round(float(dim.text)))
                            if 'ymax' in dim.tag:
                                obj['ymax'] = int(round(float(dim.text)))

        if len(img['object']) > 0:
            all_imgs += [img]
                        
    return all_imgs, seen_labels

train_imgs, train_labels = leer_annotations(xml_dir, img_dir, labels)
print('imagenes',len(train_imgs), 'labels',len(train_labels))

Train y Validación

Separaremos un 20% de las imágenes y anotaciones para testear el modelo. En este caso se utilizará el set de Validación al final de cada época para evaluar métricas, pero nunca se usará para entrenar.

¿Porque usar Train, test y validación?

train_valid_split = int(0.8*len(train_imgs))
np.random.shuffle(train_imgs)
valid_imgs = train_imgs[train_valid_split:]
train_imgs = train_imgs[:train_valid_split]
print('train:',len(train_imgs), 'validate:',len(valid_imgs))

Data Augmentation

El Data Augmentation sirve para agregar pequeñas alteraciones ó cambios a las imágenes de entradas aumentando virtualmente nuestro dataset de imágenes y mejorando la capacidad de la red para detectar objetos. Para hacerlo nos apoyamos sobre una librería llamada imgaug que nos brinda muchas funcionalidades como agregar desenfoque, agregar brillo, ó ruido aleatoriamente a las imágenes. Además podemos usar OpenCV para voltear la imagen horizontalmente y luego recolocar la “bounding box”.

### FRAGMENTO del código

iaa.OneOf([
    iaa.GaussianBlur((0, 3.0)), # blur images
    iaa.AverageBlur(k=(2, 7)), # blur image using local means with kernel
    iaa.MedianBlur(k=(3, 11)), # blur image using local medians with kernel
    ]),
    iaa.Sharpen(alpha=(0, 1.0), lightness=(0.75, 1.5)), # sharpen images
    iaa.AdditiveGaussianNoise(loc=0, scale=(0.0, 0.05*255), per_channel=0.5), # add gaussian noise to images
    iaa.OneOf([
        iaa.Dropout((0.01, 0.1), per_channel=0.5), # randomly remove up to 10% of the pixels
        ]),
    iaa.Add((-10, 10), per_channel=0.5), # change brightness of images
    iaa.Multiply((0.5, 1.5), per_channel=0.5), # change brightness of images
    iaa.ContrastNormalization((0.5, 2.0), per_channel=0.5), # improve or worsen the contrast

Crear la Red de Clasificación

La red CNN es conocida como Darknet y está compuesta por 22 capas convolucionales que básicamente aplican BatchNormalizarion, MaxPooling y activación por LeakyRelu para la extracción de características, es decir, los patrones que encontrará en las imágenes (en sus pixeles) para poder diferenciar entre los objetos que queremos clasificar.

Va alternando entre aumentar y disminuir la cantidad de filtros y kernel de 3×3 y 1×1 de la red convolucional.

#### FRAGMENTO de código, solo algunas capas de ejemplo

# Layer 1
x = Conv2D(32, (3,3), strides=(1,1), padding='same', name='conv_1', use_bias=False)(input_image)
x = BatchNormalization(name='norm_1')(x)
x = LeakyReLU(alpha=0.1)(x)
x = MaxPooling2D(pool_size=(2, 2))(x)

# Layer 2
x = Conv2D(64, (3,3), strides=(1,1), padding='same', name='conv_2', use_bias=False)(x)
x = BatchNormalization(name='norm_2')(x)
x = LeakyReLU(alpha=0.1)(x)
x = MaxPooling2D(pool_size=(2, 2))(x)

# Layer 3
x = Conv2D(128, (3,3), strides=(1,1), padding='same', name='conv_3', use_bias=False)(x)
x = BatchNormalization(name='norm_3')(x)
x = LeakyReLU(alpha=0.1)(x)

No olvides descargar y copiar en el mismo directorio donde ejecutes la notebook los pesos de la red Darknet, pues en este paso se cargaran para incializar la red.

Crear la Red de Detección

Esta red, utilizará la anterior (clasificación) y utilizará las features obtenidas en sus capas convolucionales de salida para hacer la detección de los objetos, es decir las posiciones x e y, alto y ancho. Para ello se valdrá de unas Anclas, en nuestro caso serán 5. Las Anclas son unas “ventanas”, o unas bounding boxes de distintos tamaños, pequeños, mediano grande, rectangulares o cuadrados que servirán para hacer “propuestas de detección”.

### Fragmento de código

        input_image     = Input(shape=(self.input_size, self.input_size, 3))
        self.true_boxes = Input(shape=(1, 1, 1, max_box_per_image , 4))  

        self.feature_extractor = FullYoloFeature(self.input_size)

        print(self.feature_extractor.get_output_shape())    
        self.grid_h, self.grid_w = self.feature_extractor.get_output_shape()        
        features = self.feature_extractor.extract(input_image)            

        # make the object detection layer
        output = Conv2D(self.nb_box * (4 + 1 + self.nb_class), 
                        (1,1), strides=(1,1), 
                        padding='same', 
                        name='DetectionLayer', 
                        kernel_initializer='lecun_normal')(features)
        output = Reshape((self.grid_h, self.grid_w, self.nb_box, 4 + 1 + self.nb_class))(output)
        output = Lambda(lambda args: args[0])([output, self.true_boxes])

        self.model = Model([input_image, self.true_boxes], output)

En total, la red YOLO crea una grilla de 13×13 y en cada una realizará 5 predicciones, lo que da un total de 845 posibles detecciones para cada clase que queremos detectar. Si tenemos 10 clases esto serían 8450 predicciones, cada una con la clase y sus posiciones x,y ancho y alto. Lo más impresionante de esta red YOLO es que lo hace todo de 1 sólo pasada! increíble!

Para refinar el modelo y que detecte los objetos que hay realmente, utilizará dos funciones con las cuales descartará áreas vacías y se quedará sólo con las mejores propuestas. Las funciones son:

  • IOU: Intersection Over Union, que nos da un porcentaje de acierto del área de predicción contra la “cajita” real que queremos predecir.
  • Non Maximum suppression: nos permite quedarnos de entre nuestras 5 anclas, con la que mejor se ajusta al resultado. Esto es porque podemos tener muchas áreas diferentes propuestas que se superponen. De entre todas, nos quedamos con la mejor y eliminamos al resto.

Entonces, pensemos que si en nuestra red de detección de 1 sóla clase detectamos 1 lego, esto quiere decir que la red descarto a las 844 restantes propuestas.

Prometo más teoría y explicaciones en un próximo artículo 🙂

NOTA: por más que para explicar lo haya separado en 2 redes (red YOLO y red de detección), realmente es 1 sóla red convolucional, pues están conectadas y al momento de entrenar, los pesos se ajustan “como siempre” con el backpropagation.

Generar las Anclas

Como antes mencioné, la red utiliza 5 anclas para cada una de las celdas de 13×13 para realizar las propuestas de predicción. Pero… ¿qué tamaño tienen que tener esas anclas? Podríamos pensar en 5 tamaños distintos, algunos pequeños, otros más grandes y que se adapten a las clases que queremos detectar. Por ejemplo, el ancla para detectar siluetas de personas serán rectangulares en vertical.

Según los objetos que quieras detectar, ejecutaremos un pequeño script que utiliza k-means y determina los mejores 5 clusters (de dimensiones) que se adapten a tu dataset.

Entrenar la Red Neuronal!

Basta de bla bla… y a entrenar la red. Como dato informativo, en mi ordenador Macbook de 4 núcleos y 8GB de RAM, tardó 7 horas en entrenar las 300 imágenes del dataset de lego con 7 épocas y 5 veces cada imagen con data augmentation, (en total se procesan 1500 imágenes en cada epoch).

yolo = YOLO(input_size          = tamanio, 
            labels              = labels, 
            max_box_per_image   = 5,
            anchors             = anchors)

Al finalizar verás que se ha creado un archivo nuevo llamado “red_lego.h5” que contiene los pesos de tu nueva red convolucional creada.

Revisar los Resultados

Los resultados vienen dados por una métrica llamada mAP y que viene a ser un equivalente a un F1-Score pero para imágenes, teniendo en cuenta los falsos positivos y negativos. Ten en cuenta que si bien la ventaja de YOLO es la detección en tiempo real, su contra es que es “un poco” peor en accuracy que otras redes -que son lentas-, lo podemos notar al ver que las “cajitas” no se ajustan del todo con el objeto detectado ó puede llegar a confundir la clase que clasificó. Con el Lego Dataset he logrado un bonito 63 de mAP… no está mal. Recordemos que este valor de mAP se obtiene al final de la última Epoch sobre el dataset de Validación (que no se usa para entrenar) y en mi caso eran -apenas- 65 imágenes.

Probar la Red

Para finalizar, podemos probar la red con imágenes nuevas, distintas que no ha visto nunca, veamos cómo se comporta la red!

Crearemos unas funciones de ayuda para dibujar el rectángulo sobre la imagen original y guardar la imagen nueva:

def draw_boxes(image, boxes, labels):
    image_h, image_w, _ = image.shape

    for box in boxes:
        xmin = int(box.xmin*image_w)
        ymin = int(box.ymin*image_h)
        xmax = int(box.xmax*image_w)
        ymax = int(box.ymax*image_h)

        cv2.rectangle(image, (xmin,ymin), (xmax,ymax), (0,255,0), 3)
        cv2.putText(image, 
                    labels[box.get_label()] + ' ' + str(box.get_score()), 
                    (xmin, ymin - 13), 
                    cv2.FONT_HERSHEY_SIMPLEX, 
                    1e-3 * image_h, 
                    (0,255,0), 2)
        
    return image

Utilizaremos el archivo de pesos creado al entrenar, para recrear la red (esto nos permite poder hacer predicciones sin necesidad de reentrenar cada vez).

mejores_pesos = "red_lego.h5"
image_path = "images/test/lego_girl.png"

mi_yolo = YOLO(input_size          = tamanio, 
            labels              = labels, 
            max_box_per_image   = 5,
            anchors             = anchors)

mi_yolo.load_weights(mejores_pesos)

image = cv2.imread(image_path)
boxes = mi_yolo.predict(image)
image = draw_boxes(image, boxes, labels)

print('Detectados', len(boxes))

cv2.imwrite(image_path[:-4] + '_detected' + image_path[-4:], image)

Como salida tendremos una nueva imagen llamada “lego_girl_detected.png” con la detección realizada.

Esta imagen me fue prestada por @Shundeez_official, muchas gracias! Les recomiendo ver su cuenta de Instagram que es genial!

Imágenes pero también Video y Cámara!

Puedes modificar levemente la manera de realizar predicciones para utilizar un video mp4 ó tu cámara web.

Para aplicarlo a un video:

from tqdm import *

video_path = 'lego_movie.mp4'
video_out = video_path[:-4] + '_detected' + video_path[-4:]
video_reader = cv2.VideoCapture(video_path)

nb_frames = int(video_reader.get(cv2.CAP_PROP_FRAME_COUNT))
frame_h = int(video_reader.get(cv2.CAP_PROP_FRAME_HEIGHT))
frame_w = int(video_reader.get(cv2.CAP_PROP_FRAME_WIDTH))

video_writer = cv2.VideoWriter(video_out,
                       cv2.VideoWriter_fourcc(*'MPEG'), 
                       50.0, 
                       (frame_w, frame_h))

for i in tqdm(range(nb_frames)):
    _, image = video_reader.read()
    
    boxes = yolo.predict(image)
    image = draw_boxes(image, boxes, labels)

    video_writer.write(np.uint8(image))

video_reader.release()
video_writer.release()

Luego de procesar el video, nos dejará una versión nueva del archivo mp4 con la detección que realizó cuadro a cuadro.

Y para usar tu cámara: (presiona ‘q’ para salir)

win_name = 'Lego detection'
cv2.namedWindow(win_name)

video_reader = cv2.VideoCapture(0)

while True:
    _, image = video_reader.read()
    
    boxes = yolo.predict(image)
    image = draw_boxes(image, boxes, labels)

    cv2.imshow(win_name, image)

    key = cv2.waitKey(1) & 0xFF
    if key == ord('q'):
        break

cv2.destroyAllWindows()
video_reader.release()

Conclusiones y…

Esta fue la parte práctica de una de las tareas más interesantes dentro de la Visión Artificial, que es la de lograr hacer detección de objetos. Piensen todo el abanico de posibilidades que ofrece poder hacer esto! Podríamos con una cámara contabilizar la cantidad de coches y saber si hay una congestión de tráfico, podemos contabilizar cuantas personas entran en un comercio, si alguien toma un producto de una estantería y mil cosas más! Ni hablar en robótica, donde podemos hacer que el robot vea y pueda coger objetos, ó incluso los coches de Tesla con Autopilot… Tiene un gran potencial!

Además en este artículo quería ofrecer el código que te permita entrenar tus propios detectores, para los casos de negocio que a ti te importan.

En el próximo artículo comento sobre la Teoría que hoy pusimos en práctica sobre Detección de Objetos.

1 millón de Gracias!

Este artículo es muy especial para mi, por varias cosas: una es que el Blog ha conseguido la marca de 1.000.000 de visitas en estos 2 años y medio de vida y estoy muy contento de seguir escribiendo -a pesar de muchas adversidades de la vida-. Gracias por las visitas, por leerme, por los comentarios alentadores y el apoyo!

Libro en proceso

Con este artículo y por el hito conseguido me animo a lanzar un primer borrador de lo que será “El libro del blog” y que algún día completaré y publicaré Ya publicado, en papel y digital!!.

Los invito a todos a comprarlo si pueden colaborar con este proyecto y también está la opción de conseguirlo gratis, porque sé que hay muchos lectores que son estudiantes y puede que no tengan medios ó recursos para pagar y no por eso quiero dejar de compartirlo.

Todos los que lo adquieran ahora, podrán seguir obteniendo todas las actualizaciones que iré haciendo con el tiempo y descargar el material extra.

Suscripción al Blog

Recibe los próximos artículos sobre Machine Learning, estrategias, teoría y código Python en tu casilla de correo!

NOTA: algunos usuarios reportaron que el email de confirmación y/o posteriores a la suscripción entraron en su carpeta de SPAM. Te sugiero que revises y recomiendo que agregues nuestro remitente a tus contactos para evitar problemas. Gracias!

Todo el Material

Recuerda todo lo que tienes que descargar:

Y enlaces a otros artículos de interés:

The post Detección de Objetos con Python first appeared on Aprende Machine Learning.

]]>
https://ftp.aprendemachinelearning.com/deteccion-de-objetos-con-python-yolo-keras-tutorial/feed/ 76 7262
Pronóstico de Ventas con Redes Neuronales – Parte 2 https://ftp.aprendemachinelearning.com/pronostico-de-ventas-redes-neuronales-python-embeddings/ https://ftp.aprendemachinelearning.com/pronostico-de-ventas-redes-neuronales-python-embeddings/#comments Thu, 14 Mar 2019 09:00:00 +0000 https://www.aprendemachinelearning.com/?p=6692 Mejora del modelo de Series Temporales con Múltiples Variables y Embeddings Este artículo es la continuación del post anterior “Pronóstico de Series Temporales con Redes Neuronales en Python” en donde vimos cómo a partir de un archivo de entrada con las unidades vendidas por una empresa durante años anteriores, podíamos estimar las ventas de la […]

The post Pronóstico de Ventas con Redes Neuronales – Parte 2 first appeared on Aprende Machine Learning.

]]>
Mejora del modelo de Series Temporales con Múltiples Variables y Embeddings

Este artículo es la continuación del post anterior “Pronóstico de Series Temporales con Redes Neuronales en Python” en donde vimos cómo a partir de un archivo de entrada con las unidades vendidas por una empresa durante años anteriores, podíamos estimar las ventas de la próxima semana. Continuaremos a partir de ese modelo -por lo que te recomiendo leer antes de continuar- y haremos propuestas para mejorar la predicción.

Breve Repaso de lo que hicimos

En el modelo del capitulo anterior creamos una Red Neuronal MLP (Multilayered Perceptron) feedforward de pocas capas, y el mayor trabajo que hicimos fue en los datos de entrada. Puesto que sólo tenemos un archivo csv con 2 columnas: fecha y unidades vendidas lo que hicimos fue transformar esa entrada en un “problema de aprendizaje supervisado“. Para ello, creamos un “nuevo archivo” de entrada con 7 columnas en donde poníamos la cantidad de unidades vendidas en los 7 días anteriores y de salida la cantidad de unidades vendidas en “la fecha actual”. De esa manera alimentamos la red y ésta fue capaz de realizar pronósticos aceptables. Sólo utilizamos la columna de unidades. Pero no utilizamos la columna de fecha. ¿Podría ser la columna de fecha un dato importante? ¿podría mejorar nuestra predicción de ventas?

Mejoras al modelo de Series Temporales

Esto es lo que haremos hoy: propongo 2 nuevos modelos con Redes Neuronales Feedforward para intentar mejorar los pronósticos de ventas:

  • Un primer modelo tomando la fecha como nueva variable de entrada valiosa y que aporta datos.
  • Un segundo modelo también usando la fecha como variable adicional, pero utilizándola con Embeddings… y a ver si mejora el pronóstico.

Por lo tanto explicaremos lo qué son los embeddings utilizados en variables categóricas (se utiliza mucho en problemas de Procesamiento del Lenguaje Natural NLP para modelar).

Para estos modelos propuestos haremos la transformación a “problema de aprendizaje supervisado”. Para ello usaremos la misma función series_to_supervised() de la web machinelearningmastery como en el artículo anterior.

Primer Mejora: Serie Temporal de múltilples Variables

Puede que el “ejemplo clásico” para comprender lo que son las Series Temporales de Múltiples Variables sea el pronóstico del tiempo, en donde tenemos varias “columnas de entrada” con la temperatura, la presión atmosférica, humedad. Con esas tres variables tendremos una mejor predicción de “la temperatura de mañana” que si tan sólo usásemos una sola feature.

Usar Fecha como variable de entrada

Como solamente tenemos un dato de entrada (las unidades vendidas en el día), intentaremos enriquecer a la red con más entradas. Para ello, usaremos la fecha. ¿Pero cómo? Bueno, aprovecharemos que podemos saber cada día que hubo ventas si fue un lunes, martes… por ejemplo algunos comercios venden más los viernes y sábados. También, como vimos que en cuanto a estacionalidad, en verano (europeo) subían las ventas, la red neuronal debería percatarse de eso y “mejorar su puntería” entendiendo que eso ocurre en los meses 7 y 8 (¿lo hará..?). No agregaré los años, pues sólo tenemos 2017 y 2018 (muy pocos), pero si tu cuentas con un dataset con muchos años, sería bueno agregar como entrada también los años.

En Limpio: Usaremos el día como variable categórica con valores de 0 a 6 indicando día de semana y usaremos el número de mes como otra variable categórica. La “intuición” es que la red <<entenderá>> las estacionalidades dadas entre semana y mensuales.

Segunda mejora: Embeddings en variables categóricas

Bien, para el segundo modelo, utilizaremos embeddings en las variables categóricas, es decir, en la columna de día y de mes. Los valores de día van del 0 al 6 representando los días de la semana. Pero no quiere decir que el día 6 “vale” más que el día 0. Son identificadores. No tendría sentido decir que jueves es mayor que domingo. Sin embargo la red neuronal esto no lo sabe y podría interpretar erróneamente esos valores (categóricos)… Con los meses lo mismo; van del 1 al 12 pero no quiere decir que “diciembre valga más que agosto”. Y de hecho, sabemos en la práctica para este ejercicio, que realmente en julio y agosto, es cuando más aumentan las ventas. Para intentar resolver esta problemática, es que aparecen los Embeddings.

¿Qué son los Embeddings? ¿por qué? ¿para qué?

La traducción al español de “Embed” es Incrustar… y esto a simple vista no nos ayuda mucho. Google lo traduce en uno de sus tutoriales como “incorporaciones“. Los embeddings son una manera de dar valoración útil- a datos categóricos. Para ello asignaremos una profundidad a cada “identificador”, es decir un vector con valores continuos inicialmente aleatorios. Esos valores se ajustarán con backpropagation al igual que nuestra red neuronal. Y finalmente nuestros datos categóricos quedan enriquecidos y dejan de ser “lunes” para ser unos vectores con valores que “significan algo”. ¿Qué significan? para simplificar e intentar entenderlo podemos decir que esos vectores “acercan identificadores similares entre sí y distancia a los opuestos”. Un ejemplo: cuando se utiliza en Natural Language Processing (NLP) con un gran número de palabras, los Embeddings logran hacer que palabras sobre sentimientos positivos -“alegría”,”felicidad”- queden cercanas pero distanciadas de las que significan sentimientos negativos “odio”,”tristeza”.

Hay un caso también muy usado llamado: Filtrado colaborativo en el cual se crea un motor de recomendaciones de películas. En ese ejemplo, se sitúan en un espacio vectorial las películas infantiles en extremo y las de adultos en otro. A su vez, otra coordenada indica si la película es “más comercial/taquillera” ó más “artística”.

En este caso “simplificado” los Embeddings se pueden ver como vectores de coordenadas (x,y) que acercan películas similares en 2 dimensiones y a su vez quedan distanciadas de Identificadores opuestos.

Sobre la dimensionalidad de los Embeddings

Es bueno usar muchas dimensiones (profundidad) para modelar nuestras variables categóricas. Pero ojo!, si tiene demasiadas, puede ocurrir overfitting. Entonces habrá que hacer prueba y error. Hay una regla que dice que hay que usar “una cuarta parte” del tamaño de la variable categórica: si tenemos 100 identificadores, usaremos como profundidad 25. En el curso de Fast.ai recomiendan un máximo de 50 ó “la cantidad de elementos categóricos más uno, dividido dos” (si es menor a 50). Pero siempre dependerá del caso.

Conclusión de Embeddings

Al asignarle vectores con valor numérico continuo a entradas categóricas , estos terminan funcionando como “una mini red neuronal” dentro de la red principal. Aprenden con backpropagation. Y resuelven como valores continuos esos identificadores discretos, acentuando su valor intrínseco.

Una ventaja de usar Embeddings es que se pueden reutilizar. Una vez entrenados podemos guardarlos para utilizarlos en otra red. Gracias a esto es que encontramos archivos de Embeddings con millones de palabras “ya entrenadas” por Google, listos para descargar y usar.

¿Y el código fuente de los modelos? Quiero Python! Exijo mi Jupyter Notebook!

Dejaré enlace a los códigos, pues me quiero centrar un más en las comparaciones y conclusiones de cada modelo, y no tanto en su implementación (cualquier duda, me escriben comentarios!). Aquí los enlaces de las 3 notebooks puedes abrirlas en pestañas nuevas

Los Resultados de los 3 modelos: Comparemos

Para intentar que las comparaciones sean lo más “justas” posibles, utilizaremos en las 3 redes neuronales las mismas funciones de activación (tanh), misma optimización (Adam) y métricas loss y score (mean_absolute_error y mean_squared_error). Además en todos los casos ejecutaremos 40 EPOCHS.

Por comodidad llamaremos a los 3 modelos:

  1. Serie Temporal de 1 variable = ST1
  2. Serie Temporal de Multiples Variables = STMV
  3. Serie Temporal con Embeddings = STE

Comparemos las Métricas

Vemos los valores finales de las métricas tras las 40 EPOCHS

Modelolossval_lossMSEval_MSE
1)ST10.16820.14020.05550.0353
2)STMV0.15830.14280.05100.0429
3)STE0.10860.09540.02270.0199

El modelo ST1 y STMV quedan prácticamente iguales. Es decir que tras agregar las variables de fecha no pareciera haber mejoría en las métricas. Sin embargo el modelo con embeddings sí que logra una mejora algo más evidente: el validation_loss pasa de 0.14 a 0.09 y el validation_MSE de 0.04 a 0.02.

Comparemos Gráficas de Pérdida (loss)

En las tres gráficas vemos que la métrica de loss en los sets de entrenamiento y validación descienden y se mantiene estables. Bueno, en la del segundo modelo STMV la curva de validación es algo errática. Las curvas del modelo 1 y 2 se mantienen sobre el 0.15 mientras que la del 3er modelo desciende algo más en torno del 0.10

Modelo 1) ST1: En azul el Entrenamiento y naranja el set de Validación.
Modelo 2) STMV: En azul el Entrenamiento y naranja el set de Validación.
Modelo 3) STE: En azul el Entrenamiento y naranja el set de Validación.

Comparemos las Gráficas de Accuracy

Utilizamos la métrica de MSE, y vemos que nuevamente el modelo 1 y 2 se comportan similar y se sitúan sobre el 0.06 y el modelo 3 con Embeddings desciende hasta el 0.02 (indicando una mejora) .

Comparamos los pronósticos y sus aciertos

Vamos a hacer una comparación visual, de los pronósticos realizados sobre el set de validación y marcar los aciertos. En azul, los puntos reales y en naranja las predicciones.

Modelo 1) ST1: con aciertos, pero pronóstico conservador
Modelo 2) STMV: Bastante similar al modelo 1 pero con algo mayor de amplitud.
Modelo 3) STE: Los Embeddings proveen mayor flexibilidad a la curva de pronóstico y aciertos.

Podemos ver que la primera red es “más conservadora”, manteniéndoselo en “la media” de 200, sin picos bruscos. El segundo modelo tiene algo más de amplitud en sus predicciones y la red neuronal que mejor se comporta es la tercera, que evidentemente gracias a los Embeddings logra pronosticar mejor los valores y vemos picos “más alejados” de la media de 200 que son <<buenos aciertos>>.

Extra!: publica tu modelo con Flask

Ahora está disponible un nuevo artículo “Tu propio Servicio de Machine Learning” en el cual se toma el modelo de embeddings tratado aqui y se publica mediante una API creada con Flask. Te recomiendo que lo leas y así publicas tu modelo online!

Conclusiones

Como primer conclusión podemos decir que mejoran las predicciones al agregar más variables de entrada a la red. Realmente notamos mejoría con nuestro modelo 3 al usar Embeddings en la red neuronal.

NOTA 1: recordemos que hay muchos de los parámetros para “tunear” que hemos fijado arbitrariamente. Al igual que en artículo anterior, animo al lector a variar esos parámetros en los 3 modelos para mejorarlos, empezando por la cantidad de EPOCHS=40 (aumentar a 100), ó la variable de PASOS que está en 7 (probar con 4 ó con 10).

NOTA 2: en el modelo de múltiples variables “hicimos un truco” tomando como variable adicional la fecha, pero realmente estaría bien tener otras variables con datos útiles como en el ejemplo de pronóstico del clima: 3 variables con temperatura, presión y humedad.

Podemos ver cómo el Machine Learning, puede a partir de relativamente pocos datos, sacar de su galera nuevas herramientas y adaptar y mejorar el modelo. En este caso, sabemos que podemos utilizar las variables categóricas a través de Embeddings y mejorar sustancialmente los resultados obtenidos.

Te recomiendo leer “Interpretación de Modelos de Machine Learning”, pues se comentan diversas herramientas que te ayudarán a seleccionar y valorar la características más importantes que uses en tus modelos.

Suscripción al Blog – recibe nuevos artículos

Recibe antes que nadie los nuevos artículos sobre Machine Learning, redes neuronales y todo el código Python en tu casilla de correo.

NOTA: algunos usuarios reportaron que el email de confirmación a la suscripción entraron en la carpeta SPAM. Te sugiero que revises y recomiendo agregar el remitente a tus contactos. Gracias!

Recursos del Artículo y Enlaces

Otros Artículos recomendados (en inglés)

The post Pronóstico de Ventas con Redes Neuronales – Parte 2 first appeared on Aprende Machine Learning.

]]>
https://ftp.aprendemachinelearning.com/pronostico-de-ventas-redes-neuronales-python-embeddings/feed/ 24 6692
¿Cómo funcionan las Convolutional Neural Networks? Visión por Ordenador https://ftp.aprendemachinelearning.com/como-funcionan-las-convolutional-neural-networks-vision-por-ordenador/ https://ftp.aprendemachinelearning.com/como-funcionan-las-convolutional-neural-networks-vision-por-ordenador/#comments Thu, 29 Nov 2018 09:00:00 +0000 https://www.aprendemachinelearning.com/?p=6209 En este artículo intentaré explicar la teoría relativa a las Redes Neuronales Convolucionales (en inglés CNN) que son el algoritmo utilizado en Aprendizaje Automático para dar la capacidad de “ver” al ordenador. Gracias a esto, desde apenas 1998, podemos clasificar imágenes, detectar diversos tipos de tumores automáticamente, enseñar a conducir a los coches autónomos y […]

The post ¿Cómo funcionan las Convolutional Neural Networks? Visión por Ordenador first appeared on Aprende Machine Learning.

]]>
En este artículo intentaré explicar la teoría relativa a las Redes Neuronales Convolucionales (en inglés CNN) que son el algoritmo utilizado en Aprendizaje Automático para dar la capacidad de “ver” al ordenador. Gracias a esto, desde apenas 1998, podemos clasificar imágenes, detectar diversos tipos de tumores automáticamente, enseñar a conducir a los coches autónomos y un sinfín de otras aplicaciones.

El tema es bastante complejo/complicado e intentaré explicarlo lo más claro posible. En este artículo doy por sentado que tienes conocimientos básicos de cómo funciona una red neuronal artificial multicapa feedforward (fully connected). Si no es así te recomiendo que antes leas sobre ello:

¿Qúe es una CNN? ¿Cómo puede ver una red neuronal? ¿Cómo clasifica imagenes y distingue un perro de un gato?

La CNN es un tipo de Red Neuronal Artificial con aprendizaje supervisado que procesa sus capas imitando al cortex visual del ojo humano para identificar distintas características en las entradas que en definitiva hacen que pueda identificar objetos y “ver”. Para ello, la CNN contiene varias capas ocultas especializadas y con una jerarquía: esto quiere decir que las primeras capas pueden detectar lineas, curvas y se van especializando hasta llegar a capas más profundas que reconocen formas complejas como un rostro o la silueta de un animal.

Necesitaremos…

Recodemos que la red neuronal deberá aprender por sí sola a reconocer una diversidad de objetos dentro de imágenes y para ello necesitaremos una gran cantidad de imágenes -lease más de 10.000 imágenes de gatos, otras 10.000 de perros,…- para que la red pueda captar sus características únicas -de cada objeto- y a su vez, poder generalizarlo -esto es que pueda reconocer como gato tanto a un felino negro, uno blanco, un gato de frente, un gato de perfil, gato saltando, etc.-

Pixeles y neuronas

Para comenzar, la red toma como entrada los pixeles de una imagen. Si tenemos una imagen con apenas 28×28 pixeles de alto y ancho, eso equivale a  784 neuronas. Y eso es si sólo tenemos 1 color (escala de grises). Si tuviéramos una imagen a color, necesitaríamos 3 canales (red, green, blue) y entonces usaríamos 28x28x3 = 2352 neuronas de entrada. Esa es nuestra capa de entrada. Para continuar con el ejemplo, supondremos que utilizamos la imagen con 1 sólo color.

No Olvides: Pre-procesamiento

Antes de alimentar la red, recuerda que como entrada nos conviene normalizar los valores. Los colores de los pixeles tienen valores que van de 0 a 255, haremos una transformación de cada pixel: “valor/255” y nos quedará siempre un valor entre 0 y 1.

Convoluciones

Ahora comienza el “procesado distintivo” de las CNN. Es decir, haremos las llamadas “convoluciones”: Estas consisten en tomar “grupos de pixeles cercanos” de la imagen de entrada e ir operando matemáticamente (producto escalar) contra una pequeña matriz que se llama kernel. Ese kernel supongamos de tamaño 3×3 pixels “recorre” todas las neuronas de entrada (de izquierda-derecha, de arriba-abajo) y genera una nueva matriz de salida, que en definitiva será nuestra nueva capa de neuronas ocultas. NOTA: si la imagen fuera a color, el kernel realmente sería de 3x3x3 es decir: un filtro con 3 kernels de 3×3; luego  esos 3 filtros se suman (y se le suma una unidad bias) y conformarán 1 salida (cómo si fuera 1 solo canal).

El kernel tomará inicialmente valores aleatorios(1) y se irán ajustando mediante backpropagation. (1)Una mejora es hacer que siga una distribución normal siguiendo simetrías, pero sus valores son aleatorios.

Filtro: conjunto de kernels

UN DETALLE: en realidad, no aplicaremos 1 sólo kernel, si no que tendremos muchos kernel (su conjunto se llama filtros). Por ejemplo en esta primer convolución podríamos tener 32 filtros, con lo cual realmente obtendremos 32 matrices de salida (este conjunto se conoce como “feature mapping”), cada una de 28x28x1 dando un total del 25.088 neuronas para nuestra PRIMER CAPA OCULTA de neuronas. ¿No les parecen muchas para una imagen cuadrada de apenas 28 pixeles? Imaginen cuántas más serían si tomáramos una imagen de entrada de 224x224x3 (que aún es considerado un tamaño pequeño)…

Aquí vemos al kernel realizando el producto matricial con la imagen de entrada y desplazando de a 1 pixel de izquierda a derecha y de arriba-abajo y va generando una nueva matriz que compone al mapa de features

A medida que vamos desplazando el kernel y vamos obteniendo una “nueva imagen” filtrada por el kernel. En esta primer convolución y siguiendo con el ejemplo anterior, es como si obtuviéramos 32 “imágenes filtradas nuevas”. Estas imágenes nuevas lo que están “dibujando” son ciertas características de la imagen original. Esto ayudará en el futuro a poder distinguir un objeto de otro (por ej. gato ó perro).

La imagen realiza una convolución con un kernel y aplica la función de activación, en este caso ReLu

La función de Activación

La función de activación más utilizada para este tipo de redes neuronales es la llamada ReLu por Rectifier Linear Unit  y consiste en f(x)=max(0,x).

Subsampling

Ahora viene un paso en el que reduciremos la cantidad de neuronas antes de hacer una nueva convolución. ¿Por qué? Como vimos, a partir de nuestra imagen blanco y negro de 28x28px tenemos una primer capa de entrada de 784 neuronas y luego de la primer convolución obtenemos una capa oculta de 25.088 neuronas -que realmente son nuestros 32 mapas de características de 28×28-

Si hiciéramos una nueva convolución a partir de esta capa, el número de neuronas de la próxima capa se iría por las nubes (y ello implica mayor procesamiento)! Para reducir el tamaño de la próxima capa de neuronas haremos un proceso de subsampling en el que reduciremos el tamaño de nuestras imágenes filtradas pero en donde deberán prevalecer las características más importantes que detectó cada filtro. Hay diversos tipos de subsampling, yo comentaré el “más usado”: Max-Pooling

Subsampling con Max-Pooling

Vamos a intentar explicarlo con un ejemplo: supongamos que haremos Max-pooling de tamaño 2×2. Esto quiere decir que recorreremos cada una de nuestras 32 imágenes de características obtenidas anteriormente de 28x28px de izquierda-derecha, arriba-abajo PERO en vez de tomar de a 1 pixel, tomaremos de “2×2” (2 de alto por 2 de ancho = 4 pixeles) e iremos preservando el valor “más alto” de entre esos 4 pixeles (por eso lo de “Max”). En este caso, usando 2×2, la imagen resultante es reducida “a la mitad”y quedará de 14×14 pixeles. Luego de este proceso de subsamplig nos quedarán  32 imágenes de 14×14, pasando de haber tenido 25.088 neuronas a  6272, son bastantes menos y -en teoría- siguen almacenando la información más importante para detectar características deseadas.

¿Ya terminamos? NO: ahora más convoluciones!!

Muy bien, pues esa ha sido una primer convolución: consiste de una entrada, un conjunto de filtros, generamos un mapa de características y hacemos un subsampling. Con lo cual, en el ejemplo de imágenes de 1 sólo color tendremos:

1)Entrada: Imagen 2)Aplico Kernel 3)Obtengo Feature Mapping 4)Aplico Max-Pooling 5)Obtengo “Salida” de la Convolución
28x28x1 32 filtros de 3×3 28x28x32 de 2×2 14x14x32

La primer convolución es capaz de detectar características primitivas como lineas ó curvas. A medida que hagamos más capas con las convoluciones, los mapas de características serán capaces de reconocer formas más complejas, y el conjunto total de capas de convoluciones podrá “ver”.

Pues ahora deberemos hacer una Segunda convolución que será:

1)Entrada: Imagen 2)Aplico Kernel 3)Obtengo Feature Mapping 4)Aplico Max-Pooling 5)Obtengo “Salida” de la Convolución
14x14x32 64 filtros de 3×3 14x14x64 de 2×2 7x7x64

La 3er convolución comenzará en tamaño 7×7 pixels y luego del max-pooling quedará en 3×3 con lo cual podríamos hacer sólo 1 convolución más. En este ejemplo empezamos con una imagen de 28x28px e hicimos 3 convoluciones. Si la imagen inicial hubiese sido mayor (de 224x224px) aún hubiéramos podido seguir haciendo convoluciones.

1)Entrada: Imagen 2)Aplico Kernel 3)Obtengo Feature Mapping 4)Aplico Max-Pooling 5)Obtengo “Salida” de la Convolución
7x7x64 128 filtros de 3×3 7x7x128 de 2×2 3x3x128

Llegamos a la última convolución y nos queda el desenlace…

Conectar con una red neuronal “tradicional”.

Para terminar, tomaremos la última capa oculta a la que hicimos subsampling, que se dice que es “tridimensional” por tomar la forma -en nuestro ejemplo- 3x3x128 (alto,ancho,mapas) y la “aplanamos”, esto es que deja de ser tridimensional, y pasa a ser una capa de neuronas “tradicionales”, de las que ya conocíamos. Por ejemplo, podríamos aplanar (y conectar) a una nueva capa oculta de 100 neuronas feedforward.

Entonces, a esta nueva capa oculta “tradicional”, le aplicamos una función llamada Softmax que conecta contra la capa de salida final que tendrá la cantidad de neuronas correspondientes con las clases que estamos clasificando. Si clasificamos perros y gatos, serán 2 neuronas. Si es el dataset Mnist numérico serán 10 neuronas de salida. Si clasificamos coches, aviones ó barcos serán 3, etc.

Las salidas al momento del entrenamiento tendrán el formato conocido como “one-hot-encoding” en el que para perros y gatos sera: [1,0] y [0,1], para coches, aviones ó barcos será [1,0,0]; [0,1,0];[0,0,1].

Y la función de Softmax se encarga de pasar a probabilidad (entre 0 y 1) a las neuronas de salida. Por ejemplo una salida [0,2 0,8] nos indica 20% probabilidades de que sea perro y 80% de que sea gato.

¿Y cómo aprendió la CNN a “ver”?: Backpropagation

El proceso es similar al de las redes tradicionales en las que tenemos una entrada y una salida esperada (por eso aprendizaje supervisado) y mediante el backpropagation mejoramos el valor de los pesos de las interconexiones entre capas de neuronas y a medida que iteramos esos pesos se ajustan hasta ser óptimos. PERO…

En el caso de la CNN, deberemos ajustar el valor de los pesos de los distintos kernels. Esto es una gran ventaja al momento del aprendizaje pues como vimos cada kernel es de un tamaño reducido, en nuestro ejemplo en la primer convolución es de tamaño de 3×3, eso son sólo 9 parámetros que debemos ajustar en 32 filtros dan un total de 288 parámetros. En comparación con los pesos entre dos capas de neuronas “tradicionales”: una de 748 y otra de  6272 en donde están TODAS interconectarlas con TODAS y eso equivaldría a tener que entrenar y ajustar más de 4,5 millones de pesos (repito: sólo para 1 capa).

Comparativa entre una red neuronal “tradicional” y una CNN

Dejaré un cuadro resumen para intentar aclarar más las diferencias entre las redes Fully connected y las Convolutional Neural Networks.

  Red “tradicional” Feedforward multicapa Red Neuronal Convolucional CNN
Datos de entrada en la Capa Inicial Las características que analizamos. Por ejemplo: ancho, alto, grosor, etc. Pixeles de una imagen. Si es color, serán 3 capas para rojo,verde,azul
Capas ocultas elegimos una cantidad de neuronas para las capas ocultas. Tenemos de tipo:
* Convolución (con un tamaño de kernel y una cantidad de filtros)
* Subsampling
Capa de Salida La cantidad de neuronas que queremos clasificar. Para “comprar” ó “alquilar” serán 2 neuronas. Debemos “aplanar” la última convolución con una (ó más) capas de neuronas ocultas “tradicionales” y hacer una salida mediante SoftMax a la capa de salida que clasifica “perro” y “gato” serán 2 neuronas.
Aprendizaje Supervisado Supervisado
Interconexiones Entre capas, todas las neuronas de una capa con la siguiente. Son muchas menos conexiones necesarias, pues realmente los pesos que ajustamos serán los de los filtros/kernels que usamos.
Significado de la cantidad de capas ocultas Realmente es algo desconocido y no representa algo en sí mismo. Las capas ocultas son mapas de detección de características de la imagen y tienen jerarquía: primeras capas detectan lineas, luego curvas y formas cada vez más elaboradas.
Backpropagation Se utiliza para ajustar los pesos de todas las interconexiones de las capas Se utiliza para ajustar los pesos de los kernels.

Arquitectura básica

Resumiendo: podemos decir que los elementos que usamos para crear CNNs son:

  • Entrada: Serán los pixeles de la imagen. Serán alto, ancho y profundidad será 1 sólo color o 3 para Red,Green,Blue.
  • Capa De Convolución: procesará la salida de neuronas que están conectadas en “regiones locales” de entrada (es decir pixeles cercanos), calculando el producto escalar entre sus pesos (valor de pixel) y una pequeña región a la que están conectados en el volumen de entrada. Aquí usaremos por ejemplo 32 filtros o la cantidad que decidamos y ese será el volumen de salida.
  • “CAPA RELU” aplicará la función de activación en los elementos de la matriz.
  • POOL ó SUBSAMPLING: Hará una reducción en las dimensiones alto y ancho, pero se mantiene la profundidad.
  • CAPA “TRADICIONAL” red de neuronas feedforward que conectará con la última capa de subsampling y finalizará con la cantidad de neuronas que queremos clasificar.

Pon en práctica YA MISMO la teoría y aprende a clasificar imágenes en Python mediante este ejercicio!!

Finalizando…

Se me quedan en el tintero muchísimas cosas más que explicar… pero creo que lo iré completando con el tiempo o crearé un nuevo artículo con mayor detalle/más técnico. Temas y definiciones como padding, stride, evitar overfitting, image-aumentation, dropout… o por nombrar algunas redes famosas ResNet, AlexNet, GoogLeNet and DenseNet, al mismísimo Yann LeCun… todo eso.. se queda fuera de este texto.

Este artículo pretende ser un punto inicial para seguir investigando y aprendiendo sobre las CNN. Al final dejo enlace a varios artículos para ampliar información sobre CNN.

También puedes pasar a un nuevo nivel y hacer Detección de Objetos en Python!

Conclusiones

Hemos visto cómo este algoritmo utiliza variantes de una red neuronal tradicional y las combina con el comportamiento biológico del ojo humano, para lograr aprender a ver. Recuerda que puedes hacer un ejercicio propuesto para clasificar más de 70.000 imágenes deportivas con Python en tu ordenador!

Suscripción al Blog

Recibe nuevos artículos sobre Machine Learning, redes neuronales y código Python cada 15 días 

Más recursos sobre CNN (en Inglés)


El libro del Blog (en desarrollo)

Puedes colaborar comprando el libro ó lo puedes descargar gratuitamente. Aún está en borrador, pero apreciaré mucho tu ayuda! Contiene Extras descargares como el “Lego Dataset” utilizado en el artículo de Detección de Objetos.

The post ¿Cómo funcionan las Convolutional Neural Networks? Visión por Ordenador first appeared on Aprende Machine Learning.

]]>
https://ftp.aprendemachinelearning.com/como-funcionan-las-convolutional-neural-networks-vision-por-ordenador/feed/ 28 6209
Clasificación de Imágenes en Python https://ftp.aprendemachinelearning.com/clasificacion-de-imagenes-en-python/ https://ftp.aprendemachinelearning.com/clasificacion-de-imagenes-en-python/#comments Thu, 08 Nov 2018 07:30:00 +0000 https://www.aprendemachinelearning.com/?p=5910 Crearemos una Convolutional Neural Network con Keras y Tensorflow en Python para reconocimiento de Imágenes. En este artículo iremos directo al grano: veremos el código que crea la red neuronal para visión por computador. En un próximo artículo explicaré bien los conceptos utilizados, pero esta vez haremos un aprendizaje Top-down 😉 Ejercicio Propuesto: Clasificar imágenes […]

The post Clasificación de Imágenes en Python first appeared on Aprende Machine Learning.

]]>
Crearemos una Convolutional Neural Network con Keras y Tensorflow en Python para reconocimiento de Imágenes.

En este artículo iremos directo al grano: veremos el código que crea la red neuronal para visión por computador. En un próximo artículo explicaré bien los conceptos utilizados, pero esta vez haremos un aprendizaje Top-down 😉

Ejercicio Propuesto: Clasificar imágenes de deportes

Para el ejercicio se me ocurrió crear “mi propio set MNIST” con imágenes de deportes. Para ello, seleccioné los 10 deportes más populares del mundo -según la sabiduría de internet- : Fútbol, Basket, Golf, Futbol Americano, Tenis, Fórmula 1, Ciclismo, Boxeo, Beisball y Natación (enumerados sin orden particular entre ellos).

Obtuve entre 5000 y 9000 imágenes de cada deporte, a partir de videos de Youtube (usando a FFMpeg!). Las imágenes están en tamaño <<diminuto>> de 21×28 pixeles en color y son un total de 77.000. Si bien el tamaño en pixeles puede parecer pequeño ES SUFICIENTE para que nuestra red neuronal pueda distinguirlas!!! (¿increíble, no?).

Entonces el objetivo es que nuestra máquina: “red neuronal convolucional” aprenda a clasificar -por sí sóla-, dada una nueva imagen, de qué deporte se trata.

Ejemplo de imágenes de los deportes más populares del mundo

Dividiremos el set de datos en 80-20 para entrenamiento y para test. A su vez, el conjunto de entrenamiento también lo subdividiremos en otro 80-20 para Entrenamiento y Validación en cada iteración (EPOCH) de aprendizaje.

Una muestra de las imágenes del Dataset que he titulado sportsMNIST. Contiene más de 70.000 imágenes de los 10 deportes más populares del mundo.

Requerimientos para realizar el Ejercicio

Necesitaremos por supuesto tener Python 3.6 y como lo haremos en una Notebook Jupyter, recomiendo tener instalada una suite como Anaconda, que nos facilitará las tareas.

Además instalar Keras y Tensorflow como backend. Puedes seguir este artículo en donde se explica como instalar todo el ambiente de desarrollo rápidamente.

Necesitarás descargar el archivo zip con las imágenes (están comprimidas) y decomprimirlas en el mismo directorio en donde ejecutarás la Notebook con el código. Al descomprimir, se crearán 10 subdirectorios con las imágenes: uno por cada deporte

Al código Python sin más!

Por más que no entiendas del todo el código sigue adelante, intentaré explicar brevemente qué hacemos paso a paso y en un próximo artículo se explicará cada parte de las CNN (Convolutional Neural Networks). También dejaré al final varios enlaces con información adicional que te ayudarán.

Esto es lo que haremos hoy:

  1. Importar librerías
  2. Cargar las 70.000 imágenes (en memoria!)
  3. Crear dinámicamente las etiquetas de resultado.
  4. Dividir en sets de Entrenamiento, Validación y Test
    • algo de preprocesamiento de datos
  5. Crear el modelo de la CNN
  6. Ejecutar nuestra máquina de aprendizaje (Entrenar la red)
  7. Revisar los resultados obtenidos

Empecemos a programar!:

1- Importar librerías

Cargaremos las libs que utilizaremos para el ejercicio.

import numpy as np
import os
import re
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
import keras
from keras.utils import to_categorical
from keras.models import Sequential,Input,Model
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras.layers.normalization import BatchNormalization
from keras.layers.advanced_activations import LeakyReLU

2-Cargar las imágenes

Recuerda tener DESCOMPRIMIDAS las imágenes!!! Y ejecutar el código en el MISMO directorio donde descomprimiste el directorio llamado “sportimages” (contiene 10 subdirectorios: uno por cada deporte).

Este proceso plt.imread(filepath)  cargará a memoria en un array las 77mil imágenes, por lo que puede tomar varios minutos y consumirá algo de memoria RAM de tu ordenador.

dirname = os.path.join(os.getcwd(), 'sportimages')
imgpath = dirname + os.sep 

images = []
directories = []
dircount = []
prevRoot=''
cant=0

print("leyendo imagenes de ",imgpath)

for root, dirnames, filenames in os.walk(imgpath):
    for filename in filenames:
        if re.search("\.(jpg|jpeg|png|bmp|tiff)$", filename):
            cant=cant+1
            filepath = os.path.join(root, filename)
            image = plt.imread(filepath)
            images.append(image)
            b = "Leyendo..." + str(cant)
            print (b, end="\r")
            if prevRoot !=root:
                print(root, cant)
                prevRoot=root
                directories.append(root)
                dircount.append(cant)
                cant=0
dircount.append(cant)

dircount = dircount[1:]
dircount[0]=dircount[0]+1
print('Directorios leidos:',len(directories))
print("Imagenes en cada directorio", dircount)
print('suma Total de imagenes en subdirs:',sum(dircount))
leyendo imagenes de /Users/xxx/proyecto_python/sportimages/
Directorios leidos: 10
Imagenes en cada directorio [9769, 8823, 8937, 5172, 7533, 7752, 7617, 9348, 5053, 7124]
suma Total de imagenes en subdirs: 77128

3- Crear etiquetas y clases

Crearemos las etiquetas en labels , es decir, le daremos valores de 0 al 9 a cada deporte. Esto lo hacemos para poder usar el algoritmo supervisado e indicar que cuando cargamos una imagen de futbol en la red, ya sabemos que corresponde con la “etiqueta 6”. Y con esa información, entrada y salida esperada, la red al entrenar, ajustará los pesos de las neuronas.

Luego convertimos las etiquetas y las imágenes en numpy array con np.array()

labels=[]
indice=0
for cantidad in dircount:
    for i in range(cantidad):
        labels.append(indice)
    indice=indice+1
print("Cantidad etiquetas creadas: ",len(labels))

deportes=[]
indice=0
for directorio in directories:
    name = directorio.split(os.sep)
    print(indice , name[len(name)-1])
    deportes.append(name[len(name)-1])
    indice=indice+1

y = np.array(labels)
X = np.array(images, dtype=np.uint8) #convierto de lista a numpy

# Find the unique numbers from the train labels
classes = np.unique(y)
nClasses = len(classes)
print('Total number of outputs : ', nClasses)
print('Output classes : ', classes)
Cantidad etiquetas creadas: 77128
0 golf
1 basket
2 tenis
3 natacion
4 ciclismo
5 beisball
6 futbol
7 americano
8 f1
9 boxeo
Total number of outputs : 10
Output classes : [0 1 2 3 4 5 6 7 8 9]

4-Creamos sets de Entrenamiento y Test, Validación y Preprocesar

Nótese la “forma” (shape) de los arrays: veremos que son de 21×28 y por 3 pues el 3 se refiere a los 3 canales de colores que tiene cada imagen: RGB (red, green, blue) que tiene valores de 0 a 255.

Preprocesamos el valor de los pixeles y lo normalizamos para que tengan un valor entre 0 y 1, por eso dividimos en 255.

Ademas haremos el “One-Hot encoding” con to_categorical()  que se refiere a convertir las etiquetas (nuestras clases) por ejemplo de fútbol un 6 a una salida de tipo (0 0 0 0 0 0 1 0 0 0) Esto es porque así funcionan mejor las redes neuronales para clasificar y se corresponde con una capa de salida de la red neuronal de 10 neuronas.
NOTA: por si no lo entendiste, se pone un 1 en la “sexta posición” del array y el resto en ceros, PERO no te olvides que empieza a contar incluyendo el cero!!! por eso la “etiqueta 6” queda realmente en la séptima posición.

Por último en este bloque, subdividimos los datos en 80-20 para test y entrenamiento con train_test_split()  y nuevamente en 80-20 el de training para obtener un subconjunto de validación.

#Mezclar todo y crear los grupos de entrenamiento y testing
train_X,test_X,train_Y,test_Y = train_test_split(X,y,test_size=0.2)
print('Training data shape : ', train_X.shape, train_Y.shape)
print('Testing data shape : ', test_X.shape, test_Y.shape)

train_X = train_X.astype('float32')
test_X = test_X.astype('float32')
train_X = train_X / 255.
test_X = test_X / 255.

# Change the labels from categorical to one-hot encoding
train_Y_one_hot = to_categorical(train_Y)
test_Y_one_hot = to_categorical(test_Y)

# Display the change for category label using one-hot encoding
print('Original label:', train_Y[0])
print('After conversion to one-hot:', train_Y_one_hot[0])

train_X,valid_X,train_label,valid_label = train_test_split(train_X, train_Y_one_hot, test_size=0.2, random_state=13)

print(train_X.shape,valid_X.shape,train_label.shape,valid_label.shape)
Training data shape : (61702, 21, 28, 3) (61702,)
Testing data shape : (15426, 21, 28, 3) (15426,)
Original label: 0
After conversion to one-hot: [1. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
(49361, 21, 28, 3) (12341, 21, 28, 3) (49361, 10) (12341, 10)

5 – Creamos la red (Aquí la Magia)

Ahora sí que nos apoyamos en Keras para crear la Convolutional Neural Network. En un futuro artículo explicaré mejor lo que se está haciendo. Por ahora “confíen” en mi:

  • Declaramos 3 “constantes”:
    • El valor inicial del learning rate INIT_LR
    • cantidad de epochs  y
    • tamaño batch de imágenes a procesar batch_size  (cargan en memoria).
  • Crearemos una primer capa de neuronas  “Convolucional de 2 Dimensiones” Conv2D() , donde entrarán nuestras imágenes de 21x28x3.
  • Aplicaremos 32 filtros (kernel) de tamaño 3×3 (no te preocupes si aún no entiendes esto!) que detectan ciertas características de la imagen (ejemplo: lineas verticales).
  • Utilizaremos La función LeakyReLU como activación de las neuronas.
  • Haremos un MaxPooling (de 2×2) que reduce la imagen que entra de 21×28 a la mitad,(11×14) manteniendo las características “únicas” que detectó cada kernel.
  • Para evitar el overfitting, añadimos una técnica llamada Dropout
  • “Aplanamos” Flatten()  los 32 filtros y creamos una capa de 32 neuronas “tradicionales” Dense()
  • Y finalizamos la capa de salida con 10 neuronas con activación Softmax, para que se corresponda con el “hot encoding” que hicimos antes.
  • Luego compilamos nuestra red sport_model.compile()  y le asignamos un optimizador (en este caso de llama Adagrad).
INIT_LR = 1e-3
epochs = 6
batch_size = 64

sport_model = Sequential()
sport_model.add(Conv2D(32, kernel_size=(3, 3),activation='linear',padding='same',input_shape=(21,28,3)))
sport_model.add(LeakyReLU(alpha=0.1))
sport_model.add(MaxPooling2D((2, 2),padding='same'))
sport_model.add(Dropout(0.5))

sport_model.add(Flatten())
sport_model.add(Dense(32, activation='linear'))
sport_model.add(LeakyReLU(alpha=0.1))
sport_model.add(Dropout(0.5)) 
sport_model.add(Dense(nClasses, activation='softmax'))

sport_model.summary()

sport_model.compile(loss=keras.losses.categorical_crossentropy, optimizer=keras.optimizers.Adagrad(lr=INIT_LR, decay=INIT_LR / 100),metrics=['accuracy'])

6-Entrenamos la CNN

Llegó el momento!!! con esta linea sport_model.fit()  iniciaremos el entrenamiento y validación de nuestra máquina! Pensemos que introduciremos miles de imágenes, pixeles, arrays, colores… filtros y la red se irá regulando sola, “aprendiendo” los mejores pesos para las más de 150.000 interconexiones para distinguir los 10 deportes. Esto tomará tiempo en un ordenador como mi Macbook Pro (del 2016) unos 4 minutos… puede parecer mucho o muy poco… según se lo mire. NOTA: podemos ejecutar este mismo código pero utilizando GPU (en tu ordenador o en la nube) y los mismos cálculos tomaría apenas 40 segundos.

Por último guardamos la red YA ENTRENADA sport_model.save()  en un formato de archivo h5py ya que nos permitirá poder utilizarla en el futuro SIN necesidad de volver a entrenar (y ahorrarnos los 4 minutos de impaciencia! ó incluso si contamos con GPU, ahorrarnos esa espera).

sport_train_dropout = sport_model.fit(train_X, train_label, batch_size=batch_size,epochs=epochs,verbose=1,validation_data=(valid_X, valid_label))

# guardamos la red, para reutilizarla en el futuro, sin tener que volver a entrenar
sport_model.save("sports_mnist.h5py")
Train on 49361 samples, validate on 12341 samples
Epoch 1/6
49361/49361 [==============================] – 40s 814us/step – loss: 1.5198 – acc: 0.4897 – val_loss: 1.0611 – val_acc: 0.7136
Epoch 2/6
49361/49361 [==============================] – 38s 775us/step – loss: 1.2002 – acc: 0.6063 – val_loss: 0.8987 – val_acc: 0.7717
Epoch 3/6
49361/49361 [==============================] – 43s 864us/step – loss: 1.0886 – acc: 0.6469 – val_loss: 0.8078 – val_acc: 0.7977
Epoch 4/6
49361/49361 [==============================] – 41s 832us/step – loss: 1.0166 – acc: 0.6720 – val_loss: 0.7512 – val_acc: 0.8180
Epoch 5/6
49361/49361 [==============================] – 36s 725us/step – loss: 0.9647 – acc: 0.6894 – val_loss: 0.7033 – val_acc: 0.8323
Epoch 6/6
49361/49361 [==============================] – 40s 802us/step – loss: 0.9258 – acc: 0.7032 – val_loss: 0.6717 – val_acc: 0.8379

Vemos que tras 6 iteraciones completas al set de entrenamiento, logramos un valor de precisión del 70% y en el set de validación alcanza un 83%. ¿Será esto suficiente para distinguir las imágenes deportivas?

7-Resultados obtenidos

Ya con nuestra red entrenada, es la hora de la verdad: ponerla a prueba con el set de imágenes para Test que separamos al principio y que son muestras que nunca fueron “vistas” por la máquina.

test_eval = sport_model.evaluate(test_X, test_Y_one_hot, verbose=1)

print('Test loss:', test_eval[0])
print('Test accuracy:', test_eval[1])
15426/15426 [==============================] – 5s 310us/step
Test loss: 0.6687967825782881
Test accuracy: 0.8409179307662388

En el conjunto de Testing vemos que alcanza una precisión del 84% reconociendo las imágenes de deportes. Ahora podríamos hacer un análisis más profundo, para mejorar la red, revisando los fallos que tuvimos… pero lo dejaremos para otra ocasión (BONUS: en la Jupyter Notebook verás más información con esto!) Spoiler Alert: La clase que peor detecta, son las de Fórmula 1.

Puedes probar con esta imagen de Basketball y de Fútbol a clasificarlas. En mi caso, fueron clasificadas con éxito.
En mis pruebas, a veces confundía esta imagen de Fútbol con Golf… ¿Será por el verde del campo?

Conclusiones y promesa futura!

Creamos una red neuronal “novedosa”: una red convolucional, que aplica filtros a las imágenes y es capaz de distinguir distintos deportes con un tamaño 21×28 pixels a color en tan sólo 4 minutos de entrenamiento.

Esta vez fuimos a la inversa que en otras ocasiones y antes de conocer la teoría de las redes específicas para reconocimiento de imágenes (las CNN) les he propuesto que hagamos un ejercicio práctico. Aunque pueda parecer contra-intuitivo, muchas veces este método de aprendizaje (en humanos!) funciona mejor, pues vuelve algo más dinámica la teoría. Espero que les hayan quedado algunos de los conceptos y los terminaremos de asentar en un próximo artículo (ya puedes leerlo!)

Suscripción al Blog

Recibe el próximo artículo con más teoría, prácticas y material para seguir aprendiendo Machine Learning! 

Los recursos y… Más recursos

Y mientras escribo el próximo artículo para el blog en español…

Ya disponible: ¿Qué son las Convolutional Neural Networks y cómo funcionan? La Teoría que faltaba 🙂

…les dejo varios enlaces (que seguramente utilizaré como inspiración) con más información sobre las Convolutional Neural Networks:

Y por último MIS artículos sobre Redes Neuronales (en Español! ejem-ejem!)

Otros:


El libro del Blog (en desarrollo)

Puedes colaborar comprando el libro ó lo puedes descargar gratuitamente. Aún está en borrador, pero apreciaré mucho tu ayuda! Contiene Extras descargares como el “Lego Dataset” utilizado en el artículo de Detección de Objetos.

The post Clasificación de Imágenes en Python first appeared on Aprende Machine Learning.

]]>
https://ftp.aprendemachinelearning.com/clasificacion-de-imagenes-en-python/feed/ 92 5910
Breve Historia de las Redes Neuronales Artificiales https://ftp.aprendemachinelearning.com/breve-historia-de-las-redes-neuronales-artificiales/ https://ftp.aprendemachinelearning.com/breve-historia-de-las-redes-neuronales-artificiales/#comments Wed, 12 Sep 2018 07:00:00 +0000 https://www.aprendemachinelearning.com/?p=5917 Arquitecturas y Aplicaciones de las Redes Neuronales más usadas. Vamos a hacer un repaso por las diversas estructuras inventadas, mejoradas y utilizadas a lo largo de la historia para crear redes neuronales y sacar el mayor potencial al Deep Learning para resolver toda clase de problemas de regresión y clasificación. Evolución de las Redes Neuronales […]

The post Breve Historia de las Redes Neuronales Artificiales first appeared on Aprende Machine Learning.

]]>
Arquitecturas y Aplicaciones de las Redes Neuronales más usadas.

Vamos a hacer un repaso por las diversas estructuras inventadas, mejoradas y utilizadas a lo largo de la historia para crear redes neuronales y sacar el mayor potencial al Deep Learning para resolver toda clase de problemas de regresión y clasificación.

Evolución de las Redes Neuronales en Ciencias de la Computación

Vamos a revisar las siguientes redes/arquitecturas:

  • 1958 – Perceptron
  • 1965 – Multilayer Perceptron
  • 1980’s
    • Neuronas Sigmoidales
    • Redes Feedforward
    • Backpropagation
  • 1989 – Convolutional neural networks (CNN) / Recurent neural networks (RNN)
  • 1997 – Long short term memory (LSTM)
  • 2006 – Deep Belief Networks (DBN): Nace deep learning
    • Restricted Boltzmann Machine
    • Encoder / Decoder = Auto-encoder
  • 2014 – Generative Adversarial Networks (GAN)

Si bien esta lista no es exhaustiva y no se abarcan todos los modelos creados desde los años 50, he recopilado las que fueron -a mi parecer- las redes y tecnologías más importantes desarrolladas para llegar al punto en que estamos hoy: el Aprendizaje Profundo.

El inicio de todo: la neurona artificial

1958 – Perceptron

Entre las décadas de 1950 y 1960 el científico Frank Rosenblatt, inspirado en el trabajo de Warren McCulloch y Walter Pitts creó el Perceptron, la unidad desde donde nacería y se potenciarían las redes neuronales artificiales.

Un perceptron toma varias entradas binarias x1, x2, etc y produce una sóla salida binaria. Para calcular la salida, Rosenblatt introduce el concepto de “pesos” w1, w2, etc, un número real que expresa la importancia de la respectiva entrada con la salida. La salida de la neurona será 1 o 0 si la suma de la multiplicación de pesos por entradas es mayor o menor a un determinado umbral.

Sus principales usos son decisiones binarias sencillas, o para crear funciones lógicas como OR, AND.

1965 – Multilayer Perceptron

Como se imaginarán, el multilayer perceptron es una “amplicación” del percepción de una única neurona a más de una. Además aparece el concepto de capas de entrada, oculta y salida. Pero con valores de entrada y salida binarios. No olvidemos que tanto el valor de los pesos como el de umbral de cada neurona lo asignaba manualmente el científico. Cuantos más perceptrones en las capas, mucho más difícil conseguir los pesos para obtener salidas deseadas.

Los 1980s: aprendizaje automático

Neuronas Sigmoides

Para poder lograr que las redes de neuronas aprendieran solas fue necesario introducir un nuevo tipo de neuronas. Las llamadas Neuronas Sigmoides son similares al perceptron, pero permiten que las entradas, en vez de ser ceros o unos, puedan tener valores reales como 0,5 ó 0,377 ó lo que sea. También aparecen las neuronas “bias” que siempre suman 1 en las diversas capas para resolver ciertas situaciones. Ahora las salidas en vez de ser 0 ó 1, será d(w . x + b) donde d será la función sigmoide definida como d(z) = 1/( 1 +e-z). Esta es la primer función de activación!

Imagen de la Curva Logística Normalizada de Wikipedia

Con esta nueva fórmula, se puede lograr que pequeñas alteraciones en valores de los pesos (deltas) produzcan pequeñas alteraciones en la salida. Por lo tanto, podemos ir ajustando muy de a poco los pesos de las conexiones e ir obteniendo las salidas deseadas.

Redes Feedforward

Se les llama así a las redes en que las salidas de una capa son utilizadas como entradas en la próxima capa. Esto quiere decir que no hay loops “hacia atrás”. Siempre se “alimenta” de valores hacia adelante. Hay redes que veremos más adelante en las que sí que existen esos loops (Recurrent Neural Networks).

Además existe el concepto de “fully connected Feedforward Networks” y se refiere a que todas las neuronas de entrada, están conectadas con todas las neuronas de la siguiente capa.

1986 – Backpropagation

Gracias al algoritmo de backpropagation se hizo posible entrenar redes neuronales de multiples capas de manera supervisada. Al calcular el error obtenido en la salida e ir propagando hacia las capas anteriores se van haciendo ajustes pequeños (minimizando costo) en cada iteración para lograr que la red aprenda consiguiendo que la red pueda -por ejemplo- clasificar las entradas correctamente.

Nuevo Artículo: Pronóstico de Series Temporales con Redes Neuronales

1989 – Convolutional Neural Network

Las Convolutional Neural Networks son redes multilayered que toman su inspiración del cortex visual de los animales. Esta arquitectura es útil en varias aplicaciones, principalmente procesamiento de imágenes. La primera CNN fue creada por Yann LeCun y estaba enfocada en el reconocimiento de letras manuscritas.

La arquitectura constaba de varias capas que implementaban la extracción de características y luego clasificar. La imagen se divide en campos receptivos que alimentan una capa convolutional que extrae features de la imagen de entrada (Por ejemplo, detectar lineas verticales, vértices, etc). El siguiente paso es pooling que reduce la dimensionalidad de las features extraídas manteniendo la información más importante. Luego se hace una nueva convolución y otro pooling que alimenta una red feedforward multicapa. La salida final de la red es un grupo de nodos que clasifican el resultado, por ejemplo un nodo para cada número del 0 al 9 (es decir, 10 nodos, se “activan” de a uno).

Nuevo artículo: ¿Qué son y cómo funcionan las Convolutional Neural Networks?

Esta arquitectura usando capas profundas y la clasificación de salida abrieron un mundo nuevo de posibilidades en las redes neuronales. Las CNN se usan también en reconocimiento de video y tareas de Procesamiento del Lenguaje natural. ¿Quieres hacer tu propia CNN en Python?

1997 Long Short Term Memory / Recurrent Neural Network

Aqui vemos que la red LSTM tiene neuronas ocultas con loops hacia atrás (en azul). Esto permite que almacene información en celdas de memoria.

Las Long short term memory son un tipo de Recurrent neural network. Esta arquitectura permite conexiones “hacia atrás” entre las capas. Esto las hace buenas para procesar datos de tipo “time series” (datos históricos). En 1997 se crearon las LSTM que consisten en unas celdas de memoria que permiten a la red recordar valores por períodos cortos o largos.

Una celda de memoria contiene compuertas que administran como la información fluye dentro o fuera. La puerta de entrada controla cuando puede entran nueva información en la memoria. La puerta de “olvido” controla cuanto tiempo existe y se retiene esa información. La puerta de salida controla cuando la información en la celda es usada como salida de la celda. La celda contiene pesos que controlan cada compuerta. El algoritmo de entrenamiento -conocido como backpropagation-through-time optimiza estos pesos basado en el error de resultado.

Las LSTM se han aplicado en reconocimiento de voz, de escritura, text-to-speech y otras tareas.

Se alcanza el Deep Learning

2006 – Deep Belief Networks (DBN)

La Deep Belief Network utiliza un Autoencoder con Restricted Boltzmann Machines para preentrenar a las neuronas de la red y obtener un mejor resultado final.

Antes de las DBN en 2006 los modelos con “profundidad” (decenas o cientos de capas) eran considerados demasiado difíciles de entrenar (incluso con backpropagation) y el uso de las redes neuronales artificiales quedó estancado. Con la creación de una DBN que logro obtener un mejor resultado en el MNIST, se devolvió el entusiasmo en poder lograr el aprendizaje profundo en redes neuronales. Hoy en día las DBN no se utilizan demasiado, pero fueron un gran hito en la historia en el desarrollo del deep learning y permitieron seguir la exploración para mejorar las redes existentes CNN, LSTM, etc.

Las Deep Belief Networks, demostraron que utilizar pesos aleatorios al inicializar las redes son una mala idea: por ejemplo al utilizar Backpropagation con Descenso por gradiente muchas veces se caía en mínimos locales, sin lograr optimizar los pesos. Mejor será utilizar una asignación de pesos inteligente mediante un preentrenamiento de las capas de la red -en inglés “pretrain”-. Se basa en el uso de la utilización de Restricted Boltzmann Machines y Autoencoders para pre-entrenar la red de manera no supervisada. Ojo! luego de pre-entrenar y asignar esos pesos iniciales, deberemos entrenar la red por de forma habitual, supervisada (por ejemplo con backpropagation).

Se cree que ese preentrenamiento es una de las causas de la gran mejora en las redes neuronales y permitir el deep learning: pues para asignar los valores se evalúa capa a capa, de a una, y no “sufre” de cierto sesgo que causa el backpropagation, al entrenar a todas las capas en simultáneo.

2014 – Generative Adversarial Networks

Las GAN, entrenan dos redes neuronales en simultáneo. La red de Generación y la red de Discriminación. A medida que la máquina aprende, comienza a crear muestras que son indistinguibles de los datos reales.

Estas redes pueden aprender a crear muestras, de manera similar a los datos con las que las alimentamos.

La idea detrás de GAN es la de tener dos modelos de redes neuronales compitiendo. Uno, llamado Generador, toma inicialmente “datos basura” como entrada y genera muestras. El otro modelo, llamado Discriminador, recibe a la vez muestras del Generador y del conjunto de entrenamiento (real) y deberá ser capaz de diferenciar entre las dos fuentes. Estas dos redes juegan una partida continua donde el Generador aprende a producir muestras más realistas y el Discriminador aprende a distinguir entre datos reales y muestras artificiales. Estas redes son entrenadas simultáneamente para finalmente lograr que los datos generados no puedan detectarse de datos reales.

Sus aplicaciones principales son la de generación de imágenes realistas, pero también la de mejorar imágenes ya existentes, o generar textos (captions) en imágenes, o generar textos siguiendo un estilo determinado y hasta desarrollo de moléculas para industria farmacéutica.

Conclusión, repaso y Nuevos descubrimientos

Hemos recorrido estos primeros -casi- 80 años de avances en las redes neuronales en la historia de la inteligencia artificial. Se suele dividir en 3 etapas, del 40 al 70 en donde se pasó del asombro de estos nuevos modelos hasta el escepticismo, el retorno de un invierno de 10 años cuando en los ochentas surgen mejoras en mecanismos y maneras de entrenar las redes (backpropagation) y se alcanza una meseta en la que no se puede alcanzar la “profundidad” de aprendizaje seguramente también por falta de poder de cómputo. Y una tercer etapa a partir de 2006 en la que se logra superar esa barrera y aprovechando el poder de las GPU y nuevas ideas se logra entrenar cientos de capas jerárquicas que conforman y potencian el Deep Learning y dan una capacidad casi ilimitada a estas redes.

Como último comentario, me gustaría decir que recientemente (feb 2018) hay nuevos estudios de las neuronas humanas biológicas en las que se está redescubriendo su funcionamiento y se está produciendo una nueva revolución, pues parece que es totalmente distinto a lo que hasta hoy conocíamos. Esto puede ser el principio de una nueva etapa totalmente nueva y seguramente mejor del Aprendizaje Profundo, el Machine Learning y la Inteligencia Artificial.

Suscripción al Blog

Recibe nuevos artículos sobre Machine Learning, redes neuronales y código Python cada 15 días 

Más recursos /  Seguir leyendo.

The post Breve Historia de las Redes Neuronales Artificiales first appeared on Aprende Machine Learning.

]]>
https://ftp.aprendemachinelearning.com/breve-historia-de-las-redes-neuronales-artificiales/feed/ 6 5917
Una sencilla Red Neuronal en Python con Keras y Tensorflow https://ftp.aprendemachinelearning.com/una-sencilla-red-neuronal-en-python-con-keras-y-tensorflow/ https://ftp.aprendemachinelearning.com/una-sencilla-red-neuronal-en-python-con-keras-y-tensorflow/#comments Tue, 29 May 2018 07:00:31 +0000 https://www.aprendemachinelearning.com/?p=5782 historCrearemos una red neuronal artificial muy sencilla en Python con Keras y Tensorflow para comprender su uso. Implementaremos la compuerta XOR e intentaré comparar las ventajas del aprendizaje automático frente a la programación tradicional. Requerimientos para el ejercicio Puedes simplemente leer el código y comprenderlo o si quieres ejecutarlo deberás tener un ambiente de desarrollo […]

The post Una sencilla Red Neuronal en Python con Keras y Tensorflow first appeared on Aprende Machine Learning.

]]>
historCrearemos una red neuronal artificial muy sencilla en Python con Keras y Tensorflow para comprender su uso. Implementaremos la compuerta XOR e intentaré comparar las ventajas del aprendizaje automático frente a la programación tradicional.

Requerimientos para el ejercicio

Puedes simplemente leer el código y comprenderlo o si quieres ejecutarlo deberás tener un ambiente de desarrollo Python como Anaconda para ejecutar el Jupyter Notebook (también funciona con python en línea de comandos). Sigue el tutorial para tener tu suite preparada e instalar Keras y Tensorflow. Al final del artículo podrás ver y descargar el código de GitHub.

Si aún no tienes muy claro qué son o cómo funcionan las Redes Neuronales, pues leer mi Guía Rápida sobre Deep Learning y luego volver aquí.

Las compuertas XOR

Para el ejemplo, utilizaremos las compuertas XOR. Si no las conoces o no las recuerdas, funcionan de la siguiente manera:

Tenemos dos entradas binarias (1 ó 0) y la salida será 1 sólo si una de las entradas es verdadera (1) y la otra falsa (0).

Es decir que de cuatro combinaciones posibles, sólo dos tienen salida 1 y las otras dos serán 0, como vemos aquí:

  • XOR(0,0) = 0
  • XOR(0,1) = 1
  • XOR(1,0) = 1
  • XOR(1,1) = 0

Una Red Neuronal Artificial sencilla con Python y Keras

Veamos el código completo en donde creamos una red neuronal con datos de entrada las 4 combinaciones de XOR y sus 4 salidas ordenadas. Luego analizamos el código linea a linea.

import numpy as np
from keras.models import Sequential
from keras.layers.core import Dense

# cargamos las 4 combinaciones de las compuertas XOR
training_data = np.array([[0,0],[0,1],[1,0],[1,1]], "float32")

# y estos son los resultados que se obtienen, en el mismo orden
target_data = np.array([[0],[1],[1],[0]], "float32")

model = Sequential()
model.add(Dense(16, input_dim=2, activation='relu'))
model.add(Dense(1, activation='sigmoid'))

model.compile(loss='mean_squared_error',
              optimizer='adam',
              metrics=['binary_accuracy'])

model.fit(training_data, target_data, epochs=1000)

# evaluamos el modelo
scores = model.evaluate(training_data, target_data)

print("\n%s: %.2f%%" % (model.metrics_names[1], scores[1]*100))
print (model.predict(training_data).round())

¿Keras y Tensorflow? What??

Utilizaremos Keras que es una librería de alto nivel, para que nos sea más fácil describir las capas de la red que creamos y en background es decir, el motor que ejecutará la red neuronal y la entrenará estará la implementación de Google llamada Tensorflow, que es la mejor que existe hoy en día.

¿Quieres crear una Red Neuronal desde cero y sin librerías? Aquí el código Python!

Analicemos la red neuronal que hicimos

Primero importamos las clases que utilizaremos:

import numpy as np
from keras.models import Sequential
from keras.layers.core import Dense

Utilizaremos numpy para el manejo de arrays. De Keras importamos el tipo de modelo Sequential y el tipo de capa Dense que es la “normal”.

Creamos los arrays de entrada y salida.

# cargamos las 4 combinaciones de las compuertas XOR
training_data = np.array([[0,0],[0,1],[1,0],[1,1]], "float32")

# y estos son los resultados que se obtienen, en el mismo orden
target_data = np.array([[0],[1],[1],[0]], "float32")

Como se puede ver son las cuatro entradas posibles de la función XOR [0,0], [0,1], [1,0],[1,1] y sus cuatro salidas: 0, 1,1,0.

Ahora crearemos la arquitectura de nuestra red neuronal:

model = Sequential()
model.add(Dense(16, input_dim=2, activation='relu'))
model.add(Dense(1, activation='sigmoid'))

Primero creamos un modelo vació de tipo Sequential. Este modelo se refiere a que crearemos una serie de capas de neuronas secuenciales, “una delante de otra”.

Agregamos dos capas Dense con “model.add()”. Realmente serán 3 capas, pues al poner input_dim=2 estamos definiendo la capa de entrada con 2 neuronas (para nuestras entradas de la función XOR) y la primer capa oculta (hidden) de 16 neuronas. Como función de activación utilizaremos “relu” que sabemos que da buenos resultados. Podría ser otra función, esto es un mero ejemplo, y según la implementación de la red que haremos, deberemos variar la cantidad de neuronas, capas y sus funciones de activación.

Y agregamos una capa con 1 neurona de salida y función de activación sigmoid.

Visualización de la red Neuronal

Veamos que hemos hecho hasta ahora:

La arquitectura de 3 capas que creamos para esta Red Neuronal Artificial

A Entrenar la red!

Antes de de entrenar la red haremos unos ajustes de nuestro modelo:

model.compile(loss='mean_squared_error',
              optimizer='adam',
              metrics=['binary_accuracy'])

Con esto indicamos el tipo de pérdida (loss) que utilizaremos, el “optimizador” de los pesos de las conexiones de las neuronas y las métricas que queremos obtener.

Ahora sí que entrenaremos la red:

model.fit(training_data, target_data, epochs=1000)

Indicamos con model.fit() las entradas y sus salidas y la cantidad de iteraciones de aprendizaje (epochs) de entrenamiento. Este es un ejemplo sencillo, pero recuerda que en modelos más grandes y complejos, necesitarán más iteraciones y a la vez será más lento el entrenamiento.

Resultados del Entrenamiento

Si vemos las salidas del entrenamiento, vemos que las primeras linea pone:

Epoch 1/1000
4/4 [==============================] - 0s 43ms/step - loss: 0.2634 - binary_accuracy: 0.5000
Epoch 2/1000
4/4 [==============================] - 0s 457us/step - loss: 0.2630 - binary_accuracy: 0.2500

con esto vemos que la primer iteración “tuvo algo de suerte” y acierto la mitad de las salidas (0.5) pero a partir de la segunda, sólo acierta 1 de cada 4 (0.25).

Luego en la “epoch” 24 recupera el 0.5 de aciertos, ya no es “por suerte”, si no por haber ajustado correctamente los pesos de la red.

Epoch 24/1000
4/4 [==============================] - 0s 482us/step - loss: 0.2549 - binary_accuracy: 0.5000

Epoch 107/1000
4/4 [==============================] - 0s 621us/step - loss: 0.2319 - binary_accuracy: 0.7500

Epoch 169/1000
4/4 [==============================] - 0s 1ms/step - loss: 0.2142 - binary_accuracy: 1.0000

Y -en mi caso- en la iteración 107 aumenta los aciertos al 0,75 (son 3 de 4) y en la iteración 169 logra el 100% de aciertos y se mantiene así hasta finalizar. Como los pesos iniciales de la red son aleatorios, puede que las salidas que tengas en tu ordenador sean levemente distintas en cuanto a las iteraciones, pero llegarás a la “precisión binaria” (binara_accuracy) de 1.0.

Evaluamos y Predecimos

Primero evaluamos el modelo

scores = model.evaluate(training_data, target_data)
print("\n%s: %.2f%%" % (model.metrics_names[1], scores[1]*100))

Y vemos que tuvimos un 100% de precisión (recordemos lo trivial de este ejemplo).

Y hacemos las 4 predicciones posibles de XOR, pasando nuestras entradas:

print (model.predict(training_data).round())

y vemos las salidas 0,1,1,0 que son las correctas.

Afinando parámetros de la red neuronal

Recordemos que este es un ejemplo muy sencillo y con sólo 4 entradas posibles. Pero si en la realidad tuviéramos una red compleja, deberemos poder ajustar muchos parámetros, repasemos:

  • Cantidad de capas de la red (en nuestro caso son 3)
  • Cantidad de neuronas en cada red (nosotros tenemos 2 de entrada, 16 en capa oculta y 1 de salida)
  • Funciones de activación de cada capa. Nosotros utilizamos relu y sigmoid
  • Al compilar el modelo definir las funciones de pérdida, optimizer y métricas.
  • Cantidad de iteraciones de entrenamiento.

En este ejemplo que es muy sencillo, puedes intentar variar por ejemplo la cantidad de neuronas de entrada, probar con 8 o con 32 y ver qué resultados obtienes. Por ejemplo, si necesita más o menos iteraciones para alcanzar el 100% de aciertos. Realmente podemos apreciar que hay muchos meta-parámetros para ajustar. Si hiciéramos la combinatoria de todos ellos, tendríamos una cantidad terrible de ajustes posibles. Y queda sobretodo en ti, decidir esos parámetros y ajustarlos.

Guardar la red y usarla -de verdad-

Si esto fuera un caso real, en el cual entrenamos una red, la ajustamos y obtenemos buenos resultados, ahora deberíamos Guardar esa red ya que esa red óptima, tiene los pesos que estábamos buscando. Sería tonto y lento entrenar cada vez la red antes de “publicar en producción”.

Lo que hacemos es guardar esa red y en OTRO código cargaríamos la red y la utilizamos como si fuera una librería o una funcion que creamos. Pasándole entradas y obteniendo las predicciones.

Para guardar y cargar nuestra red, utilizaremos el siguiente código de ejemplo:

# serializar el modelo a JSON
model_json = model.to_json()
with open("model.json", "w") as json_file:
    json_file.write(model_json)
# serializar los pesos a HDF5
model.save_weights("model.h5")
print("Modelo Guardado!")
 
# mas tarde...
 
# cargar json y crear el modelo
json_file = open('model.json', 'r')
loaded_model_json = json_file.read()
json_file.close()
loaded_model = model_from_json(loaded_model_json)
# cargar pesos al nuevo modelo
loaded_model.load_weights("model.h5")
print("Cargado modelo desde disco.")
 
# Compilar modelo cargado y listo para usar.
loaded_model.compile(loss='mean_squared_error', optimizer='adam', metrics=['binary_accuracy'])

Luego de esto, ya usaríamos normalmente loaded_model.predict() y listo!

¿Vale la pena una red neuronal? ¿porqué no programar con if-then-else?

Luego de visto todo esto, ¿no conviene hacer una programación “tradicional” en vez de entrenar una red neuronal? Pues siempre dependerá del caso. Por ejemplo para la función XOR tendríamos algo así:

function predecir_XOR(entrada1, entrada2){

if(entrada1 == 0 && entrada2 == 0){
    return 0;
}else if(entrada1 == 0 && entrada2 == 1){
    return 1;
}else if(entrada1 == 1 && entrada2 == 0){
    return 1;
}else if(entrada1 == 1 && entrada2 == 1){
    return 0;
}

}

Vemos que es una función con “4 ifs” que evalúa cada condición (se podría mejorar, lo sé). ¿Pero que pasaría si en vez de 2 entradas tuviéramos más parámetros?… pues seguramente la cantidad de “ifs” aumentaría creando un código caótico y propenso a errores, difícil de mantener. Piénsalo un momento. No quiere decir que haya que reemplazar todo el código del mundo con redes neuronales, pero sí pensar en que casos las redes neuronales nos brindan una flexibilidad y un poder de predicción increíbles -y que se justifican el tiempo de desarrollo-.

Para más ejemplo de Algoritmos de Machine Learning completos y en Español, visita la categoría de Práctica

Conclusión

Hemos creado nuestra primera red neuronal artificial con 3 capas para recrear la función XOR. Hemos utilizado la librería Keras -y a través de ella, Tensorflow como backend- y creamos el modelo, entrenamos los datos y obtuvimos un buen resultado. Este es el puntapié inicial para seguir viendo diversas arquitecturas de Redes Neuronales e ir aprendiendo poco a poco con Python.

Espero les haya gustado el artículo y más adelante vendrán nuevos ejemplos y ejercicios prácticos como el de crear una red con reconocimiento de imágenes-próximamente-.

Les invito a Suscribirse al blog y seguir de cerca todos los ejercicios y artículos que vendrán.

Ya estás listo para crear otra Red Neuronal con Keras y Tensorflow: Pronóstico de Ventas

 

Suscribirme al Blog

Recibir los nuevos artículos (quincenal) sobre Machine Learning y ejemplos en Python 

Recursos Adicionales y Descarga del código

Pueden ver el código en mi cuenta de GitHub aqui.

O pueden descargar el código de la Notebook Jupyter desde aqui.

Otros recursos Keras y Tensorflow


El libro del Blog

Puedes colaborar con esta cuasa comprando el libro ó lo puedes descargar gratuitamente. Aún está en borrador, pero apreciaré mucho tu ayuda! Contiene Extras descargables como el “Lego Dataset” utilizado en el artículo de Detección de Objetos.

The post Una sencilla Red Neuronal en Python con Keras y Tensorflow first appeared on Aprende Machine Learning.

]]>
https://ftp.aprendemachinelearning.com/una-sencilla-red-neuronal-en-python-con-keras-y-tensorflow/feed/ 59 5782
Instalar ambiente de Desarrollo Python Anaconda para Aprendizaje Automático https://ftp.aprendemachinelearning.com/instalar-ambiente-de-desarrollo-python-anaconda-para-aprendizaje-automatico/ https://ftp.aprendemachinelearning.com/instalar-ambiente-de-desarrollo-python-anaconda-para-aprendizaje-automatico/#comments Fri, 23 Mar 2018 09:00:16 +0000 https://www.aprendemachinelearning.com/?p=5577 Para programar tu propia Máquina de Inteligencia Artificial necesitarás tener listo tu ambiente de desarrollo local, en tu computadora de escritorio o portátil. En este tutorial explicaremos una manera sencilla de configurar Python y las librerías necesarias para programar como un Científico de Datos y utilizar los algoritmos más conocidos de Machine Learning. ¿Por qué […]

The post Instalar ambiente de Desarrollo Python Anaconda para Aprendizaje Automático first appeared on Aprende Machine Learning.

]]>
Para programar tu propia Máquina de Inteligencia Artificial necesitarás tener listo tu ambiente de desarrollo local, en tu computadora de escritorio o portátil. En este tutorial explicaremos una manera sencilla de configurar Python y las librerías necesarias para programar como un Científico de Datos y utilizar los algoritmos más conocidos de Machine Learning.

¿Por qué instalar Python y Anaconda en mi ordenador?

Python es un lenguaje sencillo, rápido y liviano y es ideal para aprender, experimentar, practicar y trabajar con machine learning, redes neuronales y aprendizaje profundoentre otros-.

Utilizaremos la Suite de Anaconda que nos facilitará la tarea de instalar el ambiente e incluirá las Jupyter Notebooks, que es una aplicación que nos ayudará a hacer ejercicios paso a paso en Machine Learning, crear visualizaciones de datos y escribir comentarios tal como si se tratase de un cuaderno de notas del colegio o la universidad.

Esta Suite es multiplataforma y se puede utilizar para Windows, Linux y Macintosh. En mi caso descargaré la versión para mi Macbook Pro, pero para otro sistema operativo será similar.

Atención! Tenemos la opción de Ejecutar nuestro ambiente en la Nube, gratis con una cuenta en Google Colab, en este artículo te lo cuento!

Agenda del futuro Científico de Datos

Nuestra agenda de hoy incluye:

  1. Descargar Anaconda
  2. Instalar Anaconda
  3. Iniciar y Actualizar Anaconda
  4. Actualizar paquete scikit-learn
  5. Instalar Librerías para Deep Learning

Comencemos!

1 – Descargar Anaconda

En este paso veremos como descargar anaconda a nuestro disco y obtener esta suite científica de Python

Nos dirigimos a la Home de Anaconda e iremos a la sección de Download (descargas)

Elegimos nuestra plataforma: Windows, Mac o Linux (en mi caso seleccionaré la de Apple)

Atención: Elegir la versión de Python 3.6 (y no la de 2.7) y seleccionar el instalador Gráfico (Graphical Installer)

Con esto guardaremos en nuestro disco duro unos 620MB (según sistema operativo) y obtendremos un archivo con el nombre similar a Anaconda3-5.1.10-MacOSX-x86_64.pkg

2 – Instalar Anaconda

En este paso instalaremos la app en nuestro sistema. (Deberá tener permisos de Administrador si instala para todos los usuarios).

Ejecutamos el archivo que descargamos haciendo doble click.

Se abrirá un “Típico Wizard” de instalación.

Seguiremos los pasos, podemos seleccionar instalación sólo para nuestro usuario, seleccionar la ruta en disco donde instalaremos y listo.

Al instalarse el tamaño total podrá superar 1Gb en disco.

3 – Iniciar y Actualizar Anaconda

En este paso comprobaremos que se haya instalado correctamente y verificar tener la versión más reciente.

Anaconda viene con una suite de herramientas gráficas llamada “Anaconda Navigator”. Iniciemos la aplicación y veremos una pantalla como esta:

Entre otros vemos que podemos lanzar las Jupyter Notebooks! (más adelante escribiré específicamente sobre esto).

Para comprobar la instalación abrimos una Terminal de Mac/Linux/Ubuntu o la Linea de Comandos de Windows.

Escribimos

conda -V

y obtenemos la versión

conda 4.3.30

luego tipeamos

python -V

y verificamos la versión de Python de nuestro sistema.

Para asegurarnos de tener la versión más reciente de la suite ejecutaremos

conda update conda

debemos poner ‘y’ para actualizar y se descargarán. Luego ejecutamos

conda update anaconda

Para confirmar que todo funciona bien, crearemos un archivo de texto para escribir un breve script de python. Nombra al archivo versiones.py y su contenido será:

# scipy
import scipy
print('scipy: %s' % scipy.__version__)
# numpy
import numpy
print('numpy: %s' % numpy.__version__)
# matplotlib
import matplotlib
print('matplotlib: %s' % matplotlib.__version__)
# pandas
import pandas
print('pandas: %s' % pandas.__version__)
# statsmodels
import statsmodels
print('statsmodels: %s' % statsmodels.__version__)
# scikit-learn
import sklearn
print('sklearn: %s' % sklearn.__version__)

En la linea de comandos, en el mismo directorio donde está el archivo escribiremos:

python versiones.py

y deberemos ver una salida similar a esta:

scipy: 0.18.1
numpy: 1.12.1
matplotlib: 1.5.3
pandas: 0.19.2
statsmodels: 0.8.0
sklearn: 0.18.1

4 – Actualizar libreria scikit-learn

En este paso actualizaremos la librería más usada para Machine Learning en python llamada SciKit Learn

En la Terminal escribiremos

conda update scikit-learn

Deberemos confirmar la actualización poniendo ‘y’ en la terminal.

Podemos volver a verificar que todo es correcto ejecutando

python versiones.py

Ahora ya puedes hacer nuestros Ejercicios paso a paso de Regresión LinealRegresión Logística , Arbol de Decisión ó de Aprendizaje no supervisado clustering K-means.

5 – Instalar librerías para Deep Learning

En este paso instalaremos las librerías utilizadas para Aprendizaje profundo. Específicamente serán keras –nuevo tutorial Sencilla Red Neuronal– la famosa y querida Tensorflow de Google.

Para ello ejecutaremos en nuestra línea de comandos

conda install -c conda-forge tensorflow
pip install keras

Y crearemos un nuevo script para probar que se instalaron correctamente. Le llamaremos versiones_deep.py y tendrá las siguientes lineas:

# tensorflow
import tensorflow
print('tensorflow: %s' % tensorflow.__version__)
# keras
import keras
print('keras: %s' % keras.__version__)

Ejecutamos en línea de comandos

python versiones_deep.py

en la terminal y veremos la salida:

tensorflow: 1.0.1
Using TensorFlow backend.
keras: 2.0.2

Ya tenemos nuestro ambiente de desarrollo preparado para el combate 🙂

Conclusión del tutorial

Para nuestra carrera en Machine Learning, el enfrentamiento con Big Data y el perfeccionamiento como Data Scientist necesitamos un buen entorno en el que programar y “cacharrear” -lease, probar cosas y divertirse-. Para ello contamos con la suite de herramientas gratuitas de Anaconda que nos ofrece un entorno amable y sencillo en el que crear nuestras máquinas en código Python.

Crea tu primer Red Neuronal en un simple ejemplo de 15 líneas de código

Espero que puedan seguir el tutorial paso a paso y si tienen problemas escriban comentarios e intentaré ayudar.

También les dejo a continuación una serie de enlaces a sitios oficiales con más información.

Hasta la próxima y no olviden Inscribirse en el blog para continuar este camino de aprendizaje juntos!.

Nuevo! “Pronóstico de Series Temporales con Redes Neuronales en Python

Suscripción al Blog

Quieres recibir el próximo artículo quincenal sobre Machine Learning en tu email? 

 

Otras Herramientas útiles:

GuardarGuardarGuardarGuardar

GuardarGuardar

GuardarGuardar


El libro del Blog

Si estos artículos te gustan y quieres darme una palmada de apoyo puedes comprar el libro con opción gratuita. Aún está en borrador, pero apreciaré mucho tu ayuda! Contiene Extras descargables como el “Lego Dataset” utilizado en el artículo de Detección de Objetos.

The post Instalar ambiente de Desarrollo Python Anaconda para Aprendizaje Automático first appeared on Aprende Machine Learning.

]]>
https://ftp.aprendemachinelearning.com/instalar-ambiente-de-desarrollo-python-anaconda-para-aprendizaje-automatico/feed/ 45 5577
Aprendizaje Profundo: una Guía rápida https://ftp.aprendemachinelearning.com/aprendizaje-profundo-una-guia-rapida/ https://ftp.aprendemachinelearning.com/aprendizaje-profundo-una-guia-rapida/#comments Tue, 14 Nov 2017 10:00:42 +0000 https://www.aprendemachinelearning.com/?p=5338 Explicando Deep Learning y Redes Neuronales -sin código- Intentaré explicar brevemente en qué consiste el Deep Learning ó Aprendizaje Profundo utilizado en Machine Learning describiendo sus componentes básicos. Conocimientos Previos Daré por sentado que el lector ya conoce la definición de Machine Learning y sus principales aplicaciones en el mundo real y el panorama de algoritmos […]

The post Aprendizaje Profundo: una Guía rápida first appeared on Aprende Machine Learning.

]]>
Explicando Deep Learning y Redes Neuronales -sin código-

Intentaré explicar brevemente en qué consiste el Deep Learning ó Aprendizaje Profundo utilizado en Machine Learning describiendo sus componentes básicos.

Conocimientos Previos

Daré por sentado que el lector ya conoce la definición de Machine Learning y sus principales aplicaciones en el mundo real y el panorama de algoritmos utilizados con mayor frecuencia. Nos centraremos en Aprendizaje Profundo aplicando Redes Neuronales Artificiales.

Entonces, ¿cómo funciona el Deep Learning? Mejor un Ejemplo

El Aprendizaje Profundo es un método del Machine Learning que nos permite entrenar una Inteligencia Artificial para obtener una predicción dado un conjunto de entradas. Esta inteligencia logrará un nivel de cognición por jerarquías. Se puede utilizar Aprendizaje Supervisado o No Supervisado.

Explicaré como funciona el Deep Learning mediante un ejemplo hipotético de predicción sobre quién ganará el próximo mundial de futbol. Utilizaremos aprendizaje supervisado mediante algoritmos de Redes Neuronales Artificiales.

Para lograr las predicciones de los partidos de fútbol usaremos como ejemplo las siguientes entradas:

  •  Cantidad de Partidos Ganados
  •  Cantidad de Partidos Empatados
  •  Cantidad de Partidos Perdidos
  • Cantidad de Goles a Favor
  • Cantidad de Goles en Contra
  • “Racha Ganadora” del equipo (cant. max de partidos ganados seguidos sobre el total jugado)

Y podríamos tener muchísimas entradas más, por ejemplo la puntuación media de los jugadores del equipo, o el score que da la FIFA al equipo. Como en cada partido tenemos a 2 rivales, deberemos estos 6 datos de entrada por cada equipo, es decir, 6 entradas del equipo 1 y otras 6 del equipo 2 dando un total de 12 entradas.

La predicción de salida será el resultado del partido: Local, Empate o Visitante.

Creamos una Red Neuronal

En la programación “tradicional” escribiríamos código en donde indicamos reglas por ejemplo “si goles  de equipo 1 mayor a goles de equipo 2 entonces probabilidad de Local aumenta”. Es decir que deberíamos programar artesanalmente unas reglas de inteligencia bastante extensa e inter-relacionar las 12 variables. Para evitar todo ese enredo y hacer que nuestro código sea escalaba y flexible a cambios recurrimos a las Redes Neuronales de Machine Learning para indicar una arquitectura de interconexiones y dejar que este modelo aprenda por sí mismo (y descubra él mismo relaciones de variables que nosotros desconocemos).

Lee aqui, sobre la historia de las Redes Neuronales

Vamos a crear una Red Neuronal con 12 valores de entrada (Input Layer) y con 3 neuronas de Salida (Output Layer). Las neuronas que tenemos en medio se llaman Hidden Layers y podemos tener muchas, cada una con una distinta cantidad de neuronas. Todas las neuronas estarán inter-conectadas unas con otras en las distintas capas como vemos en el dibujo. Las Neuronas son los círculos blancos.

  • La capa de entrada recibe los datos de entrada y los pasa a la primer capa oculta.
  • Las capas ocultas realizarán cálculos matemáticos con nuestras entradas. Uno de los desafíos al crear la Red Neuronal es decidir el número de capas ocultas y la cantidad de neuronas de cada capa.
  • La capa de Salida devuelve la predicción realizada. En nuestro caso de 3 resultados discretos las salidas podrán ser “1 0 0” para Local, “0 1 0” para Empate y “0 0 1” para Visitante.

La cantidad total de capas en la cadena le da “profundidad” al modelo. De aquí es que surge la terminología de Aprendizaje Profundo.

¿Cómo se calcula la predicción?

Cada conexión de nuestra red neuronal está asociada a un peso. Este peso dictamina la importancia que tendrá esa relación en la neurona al multiplicarse por el valor de entrada. Los valores iniciales de peso se asignan aleatoriamente (SPOILER: más adelante los pesos se ajustarán solos).

Imitando a las neuronas biológicas. cada Neurona tiene una Función de Activación. Esta función determinará si la suma de sus valores recibidos (previamente multiplicados por el peso de la conexión) supera un umbral que hace que la neurona se active y dispare un valor hacia la siguiente capa conectada. Hay diversas Funciones de Activación conocidas que se suelen utilizar en estas redes.

Cuando todas las capas finalizan de realizar sus cómputos, se llegará a la capa final con una predicción. Por Ejemplo si nuestro modelo nos devuelve 0.6 0.25 0.15 está prediciendo que ganará Local con 60% probabilidades, será Empate 25% o que gane Visitante 15%.

Entrenando Nuestra Red Neuronal

Entrenar nuestra IA puede llegar a ser la parte más difícil del Deep Learning. Necesitamos:

  1. Gran cantidad de valores en nuestro conjunto de Datos de Entrada
  2. Gran poder de cálculo computacional

Para nuestro ejemplo de “predicción de Partidos de Futbol para el próximo Mundial” deberemos crear una base de datos con todos los resultados históricos de los Equipos de Fútbol en mundiales, en partidos amistosos, en clasificatorios, los goles, las rachas a lo largo de los años, etc.

Para entrenar nuestra máquina, deberemos alimentarla con nuestro conjunto de datos de entrada y comparar el resultado (local, empate, visitante) contra la predicción obtenida. Como nuestro modelo fue inicializado con pesos aleatorios, y aún está sin entrenar, las salidas obtenidas seguramente serán erróneas.

Una vez que tenemos nuestro conjunto de datos, comenzaremos un proceso iterativo: usaremos una función para comparar cuan bueno/malo fue nuestro resultado contra el resultado real. Esta función es llamada “Función Coste“. Idealmente queremos que nuestro coste sea cero, es decir sin error(cuando el valor de la predicción es igual al resultado real del partido). A medida que entrena el modelo irá ajustando los pesos de inter-conexiones de las neuronas de manera automática hasta obtener buenas predicciones. A ese proceso de “ir y venir” por las capas de neuronas se le conoce como Back-Propagation. Más detalle a continuación.

¿Cómo reducimos la función coste -y mejoramos las predicciones-?

Para poder ajustar los pesos de las conexiones entre neuronas haciendo que el coste se aproxime a cero usaremos una técnica llamada Gradient Descent. Esta técnica permite encontrar el mínimo de una función. En nuestro caso, buscaremos el mínimo en la Función Coste.

Funciona cambiando los pesos en pequeños incrementos luego de cada iteración del conjunto de datos. Al calcular la derivada (o gradiente) de la Función Coste en un cierto conjunto de pesos, podremos ver en que dirección “descender” hacia el mínimo global. Aquí se puede ver un ejemplo de Descenso de Gradiente en  2 dimensiones, imaginen la dificultad de tener que encontrar un mínimo global en 12 dimensiones!

Para minimizar la función de coste necesitaremos iterar por el conjunto de datos cientos de miles de veces (ó más), por eso es tan necesario tener gran capacidad de cómputo en el ordenador/nube en la que entrenamos la red.

La actualización del valor de los pesos se realizará automáticamente usando el Descenso de Gradiente. Esta es parte de la magia del Aprendizaje Profundo “Automático”.

Una vez que finalizamos de entrenar nuestro Predictor de Partidos de Futbol del Mundial, sólo tendremos que alimentarlo con los partidos que se disputarán y podremos saber quién ganará Rusia 2018… Es un caso hipotético, pero es un ejercicio divertido para hacer.

¿Dónde puedo aprender más?

Hay muchos tipos de Redes Neuronales,  Convolutional Neural Networks (CNN) usadas para Vision por Computadora o las Recurrent Neural Networks RNN para Procesamiento Natural del Lenguaje. Puedes leer mi artículo con una sencilla implementación en Python con Keras, un artículo con un ejercicio en Python pero sin librerias. O un artículo sobre la historia de las Redes Neuronales. Si quieres aprender el aspecto técnico del Aprendizaje Profundo puedo sugerir tomar un curso online. Actualmente el más popular es el de Andrew Ng: Deep Learning Specialization. Se puede cursar gratuitamente o pagar para obtener la certificación. O para un conocimiento general de Machine Learning también puedo recomendar el curso estrella de Coursera. Un gran problema que surge al crear y entrenar Redes Neuronales es el Overfitting al dar demasiada complejidad a nuestra arquitectura de capas.

Si tienes dudas o preguntas sobre este tema puedo ayudarte, deja tus comentarios al finalizar este artículo.

Quieres preparar tu ambiente de desarrollo en Python?
Sigue este tutorial! Y crea tu primer red neuronal aquí

En Conclusión

  • El Aprendizaje Profundo utiliza Algoritmos de Redes Neuronales Artificiales que imitan el comportamiento biológico del cerebro.
  • Hay 3 tipos de Capas de Neuronas: de Entrada, Ocultas y de Salida.
  • Las conexiones entre neuronas llevan asociadas un peso, que denota la importancia del valor de entrada en esa relación.
  • Las neuronas aplican una Función de Activación para Estandarizar su valor de salida a la próxima capa de neuronas.
  • Para entrenar una red neuronal necesitaremos un gran conjunto de datos.
  • Iterar el conjunto de datos y comparar sus salidas producirá una Función Coste que indicará cuán alejado está nuestra predicción del valor real.
  • Luego de cada iteración del conjunto de datos de entrada, se ajustarán los pesos de las neuronas utilizando el Descenso de Gradiente para reducir el valor de Coste y acercar las predicciones a las salidas reales.

Si te gusta este artículo puedes ayudarme difundiendo en Redes Sociales el enlace para que más personas lo encuentren.

Y si vas a crear tu propia máquina, recuerda seguir los 7 pasos que comento en este artículo.

Para más actualizaciones te sugiero que te suscribas al blog o que me sigas en Twitter!

Nuevo! Ejercicio con Redes Neuronales: Pronóstico de Ventas

Entérate Primero – Suscripción

Anótate al blog y te notificará al publicarse el próximo post quincenal sobre Machine Learning. Súbete a la ola de Tecnología Disruptiva! 

GuardarGuardar

The post Aprendizaje Profundo: una Guía rápida first appeared on Aprende Machine Learning.

]]>
https://ftp.aprendemachinelearning.com/aprendizaje-profundo-una-guia-rapida/feed/ 13 5338