Tal y como vimos en un post anterior (“Construyendo Chatbots”), las plataformas de construcción de chatbots (Bot frameworks), pueden agruparse en tres grandes familias:

Cada uno de ellos, tiene sus pros y sus contras, y su mayor o menor idoneidad va depender tanto del objetivo y funcionalidad del chatbot que se quiere construir como de los recursos disponibles. En este artículo, nos vamos a centrar en las plataformas programables. Es decir, aquellas que requieren más conocimientos técnicos, pero permiten desde la construcción de chatbots sencillos hasta otros más avanzados, capaces de incorporar funcionalidades más completas. Hay bastantes plataformas programables. No obstante, aquí centraremos en las que nosotros hemos manejado desde que iniciamos nuestra andadura en el mundo del desarrollo de Chatbots. Por cierto, si tienes duda con algunos de los conceptos que mencionamos aquí, te recomendamos que, antes de seguir, te leas este otro artículo: ¿Cómo nos entienden los Chatbots?

Dialogflow (Google)

Desarrollo Avanzado Chatbots Bot Frameworks Programables

Plataforma de desarrollo de chatbots, adquirida por Google en septiembre de 2016. En Dialogflow pueden crearse chatbots o agents con un NLP (Natural Language Processing). Este permite el uso de intents (intenciones) y entities (entidades), además de la gestión dinámica de subcontextos, en base a los intents detectados. Así, la existencia de un/os determinado/s subcontexto/s, puede/n ser clave/s para la detección de otros intents. Por ejemplo, si un usuario dice “Me gustaría encargar una hamburguesa”, el sistema detectaría el intent “Encargar”. Una vez que este indica el tipo y tamaño de la hamburguesa, acciones asociadas a este intent, se generaría el subcontexto “Hamburguesa_Seleccionada”. Si posteriormente, el usuario dijera “¿Cuál es el tiempo de entrega?”, el chatbot solo podría decirlo porque la existencia del sub-contexto “Hamburguesa_Seleccionada”, daría acceso al otro intent “Obtener_Informacion_Pedido”, que contiene dicha información. Si no existiera el subcontexto, no podría tener acceso a este intent y la información que contiene. Otro aspecto interesante de esta plataforma es que permite la definición de roles en las entidades e indicar si estás son o no obligatorias. Así en la frase “Quiero ir de Madrid a Bilbao el próximo 11 de julio”, se podría establecer que la primera ciudad es la de salida y la segunda es la de llegada. Algunos de los entornos de desarrollo disponibles en Dialogflow son: Node.js, .NET, C++, Python, Ruby, PHP, Java, Android, Xamarin e iOs. Permite el despliegue de chatbots en muchas de las aplicaciones de mensajería, VoIP, en páginas webasistentes virtuales y aplicaciones propias. Algunas de ellas son: Actions de Google, Web, Slack, Facebook Messenger, Skype, Cisco Spark, Kik, Line, Telegram, Amazon Alexa, Cortana, Twilio y Twitter. Otros aspectos importantes de esta plataforma son que:

La calidad de la documentación es muy buena y hay un buen número de ejemplos de desarrollo de Chatbots.

Facebook Bot Engine

Desarrollo Avanzado Chatbots Bot Frameworks Programables

Se creó en abril de 2016 y se integra muy bien con la plataforma Wit.ai (adquirida por Facebook a principios de 2015) para el procesamiento de lenguaje natural. En ella pueden desarrollarse chatbots con Node.js, Android, iOS, Unity PHP. Para ellos se han creado un buen número de funcionalidades, entre ellas una buena integración con los elementos de su red social. Solo permite el despliegue de chatbots en el Facebook Messenger. Permite el NLP a través del uso de intents y entities, e incorpora las llamadas stories (historias), elementos clave para definir el comportamiento del chatbot. Cada story es un ejemplo de una conversación o conjunto de intenciones (intents) relacionadas (grafo de intents). A ellas se pueden ir añadiendo ramas que se activan ante la existencia o no de una determinada información en las frases entrantes. De este modo, se puede definir un flujo de conversación. También hay habilitado un mecanismo de marcadores que sirve para saltar entre intenciones e historias. También permite definir los roles de las entidades que se van creando. La integración de chatbots con sistemas externos como: APIs, Bases de datos, servicios cognitivos, etc., puede hacerse a través de los Bots sends commands, que son básicamente, llamadas a funciones. Con Facebook Analytics para hacer un seguimiento y monitorización de la actividad del chatbot. Cuenta con una buenadocumentación y un buen número de ejemplos de desarrollo de chatbots.

Microsoft Bot Framework

Desarrollo Avanzado Chatbots Bot Frameworks Programables

La plataforma de desarrollo de Microsoft consta de tres partes:

El portal de desarrollo permite hacer desarrollos en Node.js y .Net, frameworks de programación maduros. Son de amplio uso en la actualidad y han desarrollado muchas funcionalidades para ellos. También existen implementaciones de esta plataforma con Python. El Bot Connector es una clase que permite la multicanalidad de los chatbots. Así, a través de él, se pueden desplegar los chatbots en las principales aplicaciones de mensajería: Slack, Facebook Messenger, Kik, Line, Telegram, Twilio SMS, Twitter, etc., páginas webaplicaciones de VoIP (Skype) email, asistentes virtuales (Cortana) y aplicaciones propias, a través del Direct Line. El Bot Directory es una colección de chatbots desarrollados con Microsoft Bot Framework. Esta plataforma también permite monitorizar, hacer analíticas (con Azure Application Insights) e integrar otros servicios como: bases de datos,servicios cognitivos deMicrosoft (para el procesamiento de texto, voz e imágenes) y las APIs de Bing para hacer búsquedas, entre otros. Para el NLP, usa el LUIS (Language Understanding Intelligent Service) de Microsoft. LUIS soporta intentsentities y features para analizar el contenido de los mensajes entrantes y definir el comportamiento del chatbot. Las features son diccionarios de palabras o expresiones que permiten que el modelo aprenda más rápido. Gracias a ellas, puede reconocer una entidad con el menor número de ejemplos posibles.

Desarrollo Avanzado Chatbots Bot Frameworks Programables

Mediante las phrase list features pueden definirse conjuntos de posibles valores de una entidad. Estos tienen que tratarse de manera idéntica. LUIS también admite los pattern features, útiles cuando una de nuestras entidades. Es, por ejemplo, un código de vuelo o un producto cuyo formato es representable mediante una expresión regular. La calidad de la documentación es buena y proporcionan un buen número de ejemplos de desarrollo de chatbots.

IBM Watson

Desarrollo Avanzado Chatbots Bot Frameworks Programables

En el cloud de IBM la construcción de chatbot se hace mediante los Conversation Services de Watson. Los chatbots se conocen como workshop. Se pueden construir haciendo uso de varios frameworks de desarrolloNode.js, Python, .Net, Android, iOS, etc. El NLP que usa esta basado en el uso de intentsentities y synonyms. Estos últimos son conjuntos palabras, reconocidas dentro de una misma entity. Por ejemplo: paella, pizza, bocadillo y gazpacho, estarían dentro de la entity “comida”. Otro aspecto interesante es que incluye una funcionalidad, llamada Fuzzy Matching, con la que reconocer las palabras que el usuario escribe mal. Por ejemplo: si el usuario escribe piza, el sistema sería capaz de interpretar que se refiere pizza. La herramienta de NLP de IBM también permite la creación flujos de diálogos de forma gráfica, teniendo en cuenta las intents y entities definidas, y la gestión de subcontextos, de forma similar a como se hace en Dialogflow. Permite el despliegue de chatbots en la web, dentro de aplicaciones propias (similar al Direct Line de Microsoft), SlackFacebook Messenger y Twillo. También incluye una herramienta monitorización analítica. Y permite la integración de otras APIs de Watson, bases de datos, etc. Tiene una buenadocumentación y se proporcionan bastantes ejemplos de desarrollo de chatbots.

Amazon Lex

Desarrollo Avanzado Chatbots Bot Frameworks Programables

Es un servicio de AWS (cloud de Amazon) para crear interfaces conversacionales o chatbots. El sistema de NLP se basa en el uso de intents y slots. Los slots son los parámetros que puede requerir un intent, aunque no son obligatorios. Por ejemplo, el intent OrderFly podría requerir slots como origendestino y clase, teniendo cada uno de ellos un tipo, como:

El usuario podrá responder con un valor de slot que incluya palabras adicionales, como “Quiero ir desde a Madrid a San Petesburgo” o “Prefiero la clase Business” y el sistema de Amazon Lex seguirá entendiendo el valor de slot integrado. Cuenta con los siguientes entornos de programaciónNode.js, Python, .NET, Android, iOS, Java, Javascript, PHP y Ruby. La integración con otros servicios (DynamoDB, Amazon Cognito APIs), se hace a través de los AWS Lambda. Estos están integrados dentro de Amazon Lex. Incluye herramientas para la monitorización y analítica, y también permite la integración del Amazon CloudWatch. Además, los chatbots creados con Amazon Lex pueden desplegarse en Facebook Messenger, Slack y Twillo. Tiene una buenadocumentación y se proporcionan algunos ejemplos de desarrollo de chatbots.

Aspect CXP

Desarrollo Avanzado Chatbots Bot Frameworks Programables

La Aspect Customer Experience Platform (CXP) es una plataforma para el diseño, implementación y despliegue de aplicaciones de para el customer service, entre los que se incluyen los chatbots. Lo hace a través de canales de comunicación como; SMS, voz, web, Skype y redes sociales como Facebook y TwitterNo permite el uso de lenguajes de programación. El diseño y desarrollo de chatbots se hace a través de una herramienta propietaria, llamada Aspect CXP Designer. Es una aplicación con bastantes posibilidades que está a medio camino entre una aplicación gráfica y un lenguaje de programación. Para sacarle el máximo partido hay que tener conocimientos de lógica de programación. Sin embargo, es importante aclarar que el grado de personalización y adaptación que permite es menor que cuando usamos un lenguaje de programación. También permite la integración de otros serviciosAPIs, Bases de datos, servicios cognitivos, etc. Para el NLP usa un componente llamado Aspect NLU (Natutal Language Understanding) que permite recorrer las frases entrantes e ir identificando los elementos relevantes y su significado. Este sistema de procesamiento del lenguaje natural es diferente a los vistos anteriormente. Los anteriores se basan más en el entrenamiento de sistemas pre-entrenados y sus sistemas de interpretación se construyen a través de un sistema de reglas apoyado en una serie de bases de datos léxicas, que están alienadas entre los diferentes lenguajes y permiten a los elementos identificados funcionar en varios idiomas.  Así, un mismo sistema de identificación puede ser utilizado para diferentes idiomas. Las implementaciones de NLP hechas con Aspect NLU son más robustas, pero menos flexibles y más complejas de construir. La calidad de la documentación es aceptable, los ejemplos desarrollo de chatbots con esta plataforma son escasos y su código no es accesible.

Gupshup

Desarrollo Avanzado de Chatbots Bot Frameworks Programables

Es una plataforma de desarrollo apta tanto para desarrolladores como para aquellos que no lo son, ya que ofrece dos herramientas: Flow Bot Builder y Bot Builder IDE. La Flow Bot Buider es un editor visual, apto para usuarios sin conocimiento de programación, que permite la construcción y despliegue de chatbots sin necesidad de escribir código de programación. Permite la construcción de chatbots sencillos. El Bot Builder IDE es una herramienta de desarrollo que permite el uso de varios entornos de programación (Node.js, Python, Ruby, PHP, Java, C#, Android e iOS). Incluye herramientas de analítica y monitorización, y el  NLP que trae por defecto (NLP on the fly) es sencillo y muy fácil de implementar, pero sólo permite el manejo de intents y entities. También permite hacer uso de otros motores de NLP (más completos), en especial los de Dialogflow y Wit.ai. Tanto una herramienta como la otra, permiten el despliegue de chatbots en varios canales: Facebook Messenger, SMS, Twitter, Telegram, Slack, Hipchat, Skype, Kik, Twillio, Line, Cisco Spark, Teamchat, etc. También permite la integración de servicios como APIs, Bases de datos, servicios cognitivos, etc. La calidad de la documentación es aceptable y no hay muchos ejemplos de desarrollo de chatbots con Gupshup.

HACIENDO BALANCE

A continuación, y para resumir todo lo visto anteriormente, se muestra una tabla comparativa con los datos relativos a cada una de las plataformas que se han visto.

Tabla comparativa - Desarrollo Avanzado de Chatbots Bot Frameworks Programables

En esta valoración se han tenido en cuenta tanto la variedad de servicios disponibles, madurez y accesibilidad, como el nivel de documentación de los mismos. Las tres plataformas de desarrollo de chatbots más recomendadas actualmente, en orden de prioridad, serían:

Mejores plataformas- Desarrollo Avanzado de Chatbots Bot Frameworks Programables

Como se puede ver, existe un gran número de posibilidades para crear chatbots avanzados. A partir de aquí, tendríamos que ir viendo y probando cada una de las plataformas disponibles, para ver cuál de ellas se ajusta mejor a los requerimientos de nuestro proyecto. En cualquier caso, una cosa sí está muy clara: la creatividad, capacidad de adaptación y ganas de aprender serán elementos clave. Buen desarrollo a tod@s! ????

Se puede resumir el rumbo que están siguiendo las empresas en la segunda década del siglo XXI en dos palabras: transformación digital. La nueva economía digital plantea nuevos desafíos a las empresas y sus líderes. La integración de herramientas digitales ha penetrado al negocio. Además, esto está provocando cambios importantes en la forma en que trabajan, se comunican y venden. La digitalización de los procesos y actividades del negocio amplía el alcance de las organizaciones, tanto para mejorar las decisiones que toma la dirección y acelerar el desarrollo de nuevos productos y servicios como para transformar radicalmente los modelos de negocio tradicionales. De este modo, todas las empresas se han convertido en tecnológicas y sus plataformas digitales son un elemento vital para el negocio.

EVOLUCIÓN DE ARQUITECTURAS Y APLICACIONES EMPRESARIALES

Los requerimientos de las aplicaciones han cambiado drásticamente en los últimos años. Solo unos pocos años atrás, una aplicación grande tenía decenas de servidores, segundos de tiempo de respuesta, horas de mantenimiento fuera de línea y gigabytes en datos, lo que hacía necesario su procesamiento. Luego se incorporaron los ERP y CRM a las webs con arquitecturas cliente/servidor y finalmente a las aplicaciones modernas actuales, basadas en los microservicios, los contenedores virtuales y el Big Data. Estos últimos basados en componentes de código abierto y/o software libre.

Aplicaciones Empresariales Modernas: arquitecturas reactivas y microservicios

Hoy, las aplicaciones se despliegan en casi “cualquier cosa”, desde dispositivos móviles, dispositivos industriales, hasta clústeres en la nube corriendo en miles de procesadores multi-core. Esto se debe a que los usuarios “digitales” esperamos que los tiempos de respuesta sean de milisegundos y que nuestros sistemas estén operativos el 100% del tiempo. Las demandas de hoy simplemente no están siendo satisfechas por las arquitecturas software de ayer. Las arquitecturas reactivas surgen como un nuevo patrón para construir unos sistemas más robustos, más flexibles y que están mejor posicionados para cumplir demandas modernas. Las aplicaciones monolíticas se descomponen en micro-aplicaciones o microservicios, que se despliegan en diferentes contenedores. En muchas ocasiones, estos microservicios utilizan motores de cálculo basados en tecnologías Big DataMachine Learning y de Inteligencia Artificial. Estos motores proporcionan capacidades de analítica avanzada en tiempo real, procesando grandes cantidades de información. Los microservicios se integran entre ellos utilizando APIs asíncronos, muy robustos, con un bajo acoplamiento y con grandes capacidades para escalar según las demandas. De esta forma, logran responder a las limitaciones de escalado de los modelos de desarrollo anteriores, que se caracterizan por su desaprovechamiento del uso de la CPU, el sobreuso de memoria y la ineficiencia de las interacciones bloqueantes.

MÁSTER EXPERTO EN BIG DATA & ANALYTICS

Gracias al Master en Big Data Analytics 100% Online tendrás amplios conocimientos sobre las herramientas y técnicas analíticas necesarias para la modelización de los principales retos de negocio, con el fin de mejorar la toma de decisiones a través de los datos y el conocimiento.

Como decíamos en la entrada anterior sobre arquitecturas reactivas, las demandas de hoy en las empresas requieren tiempos de respuesta cortos, con la necesidad de tener que procesar ingentes cantidades de datosdesplegarse en cualquier cosa y que los sistemas estén operativos el 100% del tiempo. Para ellos, distintos tipos de organizaciones están dando de manera independiente con patrones similares con los que construir software que haga frente a estas demandas.

Este conjunto de patrones y técnicas es el que se conoce como Arquitecturas Reactivas y se utilizan para construir sistemas que:

PRINCIPIOS DE LA PROGRAMACIÓN REACTIVA

Dirigida por datos

En el modelo de actores, uno de los patrones más utilizados en programación reactiva, se definen cadenas de transformación funcional. Estas son atravesadas por flujos de datos para su procesamiento. Se podría decir que este tipo de soluciones están dirigidas por los datos porque en ellos descansa, además de gran parte de la lógica de la aplicación, el propio comportamiento reactivo del sistema.

Centrada en la composición

Las operaciones que forman parte del procesamiento de datos en programación reactiva, que normalmente se implementan en actores distintos, se encadenan de forma compositiva. De este modo, el resultado de cada transformación es la entrada para la siguiente. Para poder articular esta composición adecuadamente, debemos tener en cuenta tres reglas fundamentales en la programación funcional:

IDEMPOTENCIA DE LAS FUNCIONES

Las funciones siempre deben devolver los mismos resultados para los mismos valores de entrada.

TRANSPARENCIA REFERENCIAL

El valor de retorno de las funciones depende de los parámetros de entrada, nunca de condiciones ambientales (parámetros externos o contexto).

INMUTABILIDAD DE LOS DATOS

Los datos de entrada que manejan las funciones son inmutables, es decir, las funciones nunca deben alterar los parámetros de entrada.

PRINCIPALES LENGUAJES Y PLATAFORMAS DE LA PROGRAMACIÓN REACTIVA:

Como ya se ha dicho antes, la programación reactiva implica el conocimiento y la integración de varios lenguajes de programación y plataformas, como podrían ser:

MÁSTER EXPERTO EN BIG DATA & ANALYTICS

Gracias al Master en Big Data Analytics 100% Online tendrás amplios conocimientos sobre las herramientas y técnicas analíticas necesarias para la modelización de los principales retos de negocio, con el fin de mejorar la toma de decisiones a través de los datos y el conocimiento.

En el primer artículo de esta serie sobre Computación Cuántica se expuso cómo la unidad fundamental de información en sistemas de Computación Clásica era el bit y cómo se tratan las distribuciones de probabilidad en ese paradigma. El objetivo de esta nueva entrega es el de ampliar nuestra perspectiva a la hora de abordar la modelización de problemas. Comencemos.

Qubits

La Computación Cuántica emplea, como se comentó anteriormente, principios presentes en física cuántica como los fenómenos de superposición y entrelazamiento, entre otros, para llevar a cabo cálculos de una forma más eficiente que con la computación tradicional. Esto lo consigue empleando como unidad de información el qubit, que es un sistema de mecánica cuántica de 2 estados pero que, cuando es observado y medido, puede tomar cualquier posible combinación de esos 2 valores. En el artículo inicial se presentó el ejemplo del lanzamiento de una moneda como un caso que podía modelizarse como una distribución de probabilidad en Computación Clásica y se representaba como un vector columnar.

PRIMERA APROXIMACIÓN AL ESTADO CUÁNTICO

Como primera aproximación, podemos acercarnos al concepto de estado cuántico también como una distribución de probabilidad representada a través de un vector columnar. Para identificarlo y distinguirlo del vector de Computación Clásica se empleará el denominado ket de la notación Dirac. Siguiendo esta nomenclatura, el ket que representa el estado de un qubit se escribirá de la siguiente forma:

introducción a la computación cuántica

Donde a0, a1 ∈ ℂ y se denominan amplitudes de probabilidad de forma que cada amplitud estará asociada a un estado cuántico. La diferencia con el modelo clásico es que ahora el requisito de normalización es en la norma l2 en vez de en l1. Formalmente esto se traduce en que la raíz cuadrada de la suma de los cuadrados de los valores absolutos de las amplitudes será igual a 1:

introducción a la computación cuántica

PROFUNDIZANDO EN LA REPRESENTACIÓN DEL ESTADO CUÁNTICO

Profundizando en cómo representar un estado cuántico, hay que decir que se emplean como vectores de base canónica en 2 dimensiones los kets 0 y 1 cuya notación Dirac será la siguiente:

introducción a la computación cuántica

Combinando lo que hemos visto sobre cómo representar el estado de un qubit con la notación de la base canónica en computación cuántica, podemos describir el estado de dicho qubit empleando esa base canónica de la siguiente forma:

introducción a la computación cuántica

La expansión del estado del qubit  (|) en una base nos lleva a unos de los fenómenos más importantes en mecánica cuántica, la Superposición. Si observamos una muestra de esa distribución de probabilidad que representa el qubit y la medimos, obtendremos la salida ‘0’ con una probabilidad igual al cuadrado del valor absoluto de la amplitud que acompaña a la base canónica ket 0, es decir, |a0|2 y que obtendremos un ‘1’ con probabilidad |a1|2 (el cuadrado del valor absoluto de amplitud que acompaña al ket 1).  Esta regla que nos permite calcular la probabilidad con la que se obtendrá cada uno de los estados cuánticos recibe el nombre de regla de Born.

Circuitos Cuánticos con Qiskit

Como la idea es ir viendo cómo implementar estos conceptos de teoría empleando el framework Qiskit de python, vamos a comenzar simulando el ejemplo del lanzamiento de una moneda totalmente sesgada donde se obtendrá “cara” en el 100% de los lanzamientos, por lo que el ket

introducción a la computación cuántica

La librería ‘BasicAer’ proporciona un framework de simulación para la pila de software de Qiskit. En concreto, mediante su método ‘get_backed’ permite definir el entorno de ejecución que podrá ser o bien un simulador o un procesador cuántico real. En este caso, se está indicando que se utilizará el simulador ‘qasm_simulator’, por lo que la ejecución no se realizará en un entorno cuántico auténtico pero tratará de imitarlo. También devolverá un diccionario con el contador de las medidas realizadas que estarán almacenadas en registros clásicos del circuito cuántico. En la variable ‘qr’ se almacenará la referencia a un registro cuántico que permitirá almacenar un qubit. Mientras que la variable ‘cr’ se empleará para manejar un registro clásico que contendrá un bit. Por último, en la variable ‘circuit’ se define un circuito cuántico que inicialmente dispondrá del registro cuántico ‘qr’ y del registro clásico ‘cr’. Hay que decir que cualquier qubit estará siempre inicializado por defecto en el ket 0, por lo que, si lo medimos, obtendremos el resultado deseado de una moneda totalmente sesgada que devuelva siempre ‘cara’. Para realizar esa medición emplearemos el método ‘measure’ del circuito cuántico que hemos definido en la variable ‘circuit’:

introducción a la computación cuántica

El método ‘measure’ recibirá el qubit que hemos almacenado en el registro cuántico ‘qr’, y cuando sea ejecutado el circuito, realizará una medición mediante la observación del estado cuántico lo que provocará que dicho estado colapse y se obtenga un valor concreto que será almacenado en el registro clásico definido en la variable ‘cr’.  

EL SIGUIENTE PASO

Una vez que se ha añadido esa operación de medición al circuito procederemos a ejecutarlo 50 veces (parámetro shots=50) mediante la librería ‘execute’ de Qiskit almacenado la referencia a esa llamada en la variable ‘job’. Dicho método ‘execute’ recibirá el circuito a ejecutar y el backend de ejecución. Una vez hecho eso, se guardará en la variable ‘result’ la llamada al método ‘result’ del objeto ‘job’. Por último, como estamos empleando el ‘qasm_simulator’ dispondremos del método ‘get_counts’ para obtener un diccionario donde cada clave será un estado y su valor el número de ocurrencias del mismo durante los experimentos (shots). Podremos comprobar que las 50 veces que se repite la ejecución del circuito cuántico y se realiza su medición se obtiene siempre un ‘0’. Si estas ejecuciones se hubieran realizado en un procesador cuántico real podríamos encontrar que esos resultados no  coincidirían exactamente con estas medidas debido entre otros factores al ruido.

introducción a la computación cuántica

Conclusión

Acabamos de definir y ejecutar nuestro primer circuito cuántico para simular el problema del lanzamiento de una moneda sesgada. Y como probablemente os hayáis quedado con ganas de seguir jugando os emplazo al siguiente artículo de esta serie donde continuaremos profundizando en este apasionante campo.  

MÁSTER EXPERTO EN BIG DATA & ANALYTICS

Gracias al Master en Big Data Analytics 100% Online tendrás amplios conocimientos sobre las herramientas y técnicas analíticas necesarias para la modelización de los principales retos de negocio, con el fin de mejorar la toma de decisiones a través de los datos y el conocimiento.

Dentro del mundo del Data Science, existen iniciativas muy interesantes, y una de las que más no puede interesar, además de todos las opciones formativas y herramientas disponibles, son los Google Colab.

Colab es un servicio cloud, basado en los Notebooks de Jupyter, que permite el uso gratuito de las GPUs y TPUs de Google, con librerías como: Scikit-learn, PyTorch, TensorFlow, Keras y OpenCV. Todo ello con bajo Python 2.7 y 3.6, que aún no está disponible para R y Scala.

Aunque tiene algunas limitaciones, que pueden consultarse en su página de FAQ, es una herramienta ideal, no solo para practicar y mejorar nuestros conocimientos en técnicas y herramientas de Data Science, sino también para el para el desarrollo de aplicaciones (pilotos) de machine learning y deep learning, sin tener que invertir en recursos hardware o del Cloud.

Con Colab se pueden crear notebooks o importar los que ya tengamos creados, además de compartirlos y exportarlos cuando queramos. Esta fluidez a la hora de manejar la información también es aplicable a las fuentes de datos que usemos en nuestros proyectos (notebooks), de modo que podremos trabajar con información contenida en nuestro propio Google Drive, unidad de almacenamiento local, github e incluso en otros sistemas de almacenamiento cloud, como el S3 de Amazon.

Empezando a trabajar con Colab

Para poder tener nuestro espacio de trabajo en Colab, tendremos que tener una cuenta de google y acceder al servicio de Google Drive. Una vez dentro, le daremos a Nuevo > Carpeta, poniéndole el nombre que consideremos, por ejemplo: “MisColabs”.

introducción google colab data science

Para crear nuestro primer Colab, entraremos dentro de la carpeta que hemos creado y daremos a Nuevo > Más > Colaboratory,  a continuación se abrirá un nuevo notebook.

introducción google colab data science

Otra opción sería ir directamente a Google Colab.

Lo siguiente sería cambiar el nombre del notebook, haciendo clic en el nombre del notebook (esquina superior-izquierda) o yendo al menú Archivo > Cambiar nombre.

introducción google colab data science

Una vez hecho esto, hay que establecer el entorno de ejecución: menú Entorno de ejecucción > Cambiar tipo de entorno de ejecucción, tras lo que se abrirá la siguiente ventana:

introducción google colab data science

En la mismo indicaremos las versión de Python ( 2 ó 3)  y la unidad de procesamiento que se usará para ejecutar el código del Notebook: CPU (None), GPU ó TPU.

Cargando los datos

A la hora cargar los datos, que se usarán en el notebook, existen varias opciones, pero aquí veremos tres:

Para montar y habilitar el acceso a nuestro Google Drive, ejecutaremos el siguiente código:

from google.colab import drive

drive.mount('/content/gdrive')

Al hacer esto, nos pedirá un código de autorización y la url donde podemos conseguirlo. Al hacer clic en dicha url, nos llevará al proceso de validación de nuestra cuenta de Google y luego nos mostrará el código de acceso que tenemos que copiar y pegar, en el sitio correspondiente. A continuación hay que dar a Enter.

introducción google colab data science

Tras hacerlo, lo validará y montará nuestro google drive en el notebook, apareciendo el siguiente mensaje: “Mounted at /content/gdrive”.

introducción google colab data science

Para verlo, tendremos que hacer clic en la flecha que esta en el margen superior izquierdo e ir a la pestaña de archivos. En el veremos dos carpetas: sample_data (datos de ejemplo) y gdrive (nuestro google drive).

introducción google colab data science

Si lo que queremos es traernos los datos de una fuente externa, por ejemplo, una instancia S3 de Amazon, podremos hacerlo haciendo uso de comandos como: !wget y !unzip. Tal y como se muestra a continuación:

!wget -cq https://s3.amazonaws.com/content.udacity-data.com/courses/nd188/flower_data.zip

!unzip -qq flower_data.zip

Al ejecutar estás dos sentencias, el dataset flower_data, se cargará y estará disponible en nuestro notebook, podremos verlo en la pestaña de archivo.

introducción google colab data science

Por último, si queremos cargar datos que tenemos en nuestro disco local, podremos hacerlo siguiendo los siguientes pasos:

1.- Dar al botón subir, que esta en el margen superior izquierdo de la pestaña de archivos.

introducción google colab data science

2.- Buscamos el archivo que queremos subir, en mi caso el archivo winequality.csv que tengo el directorio ./Descargas/data, de mi disco duro local.

introducción google colab data science

3.- Cuando le damos a abrir, nos aparecerá un mensaje de advertencia, diciendo que los datos se borrarán al finalizar la sesión, lógico al tratarse de un servicio gratuito. Simplemente es algo que tendremos que tener en cuenta a la hora de usar este servicio. Una opción sería guardar nuestros datos en Google Drive y evitar que se borren cuando cerremos nuestra sesión de Colab.

introducción google colab data science

4.- El archivo que hemos cargado, aparecerá en la pestaña de Archivos.

introducción google colab data science

Operaciones básicas

Con los archivos cargados,  podremos realizar una operativa similar a la que haríamos desde una consola de linux. Se usan los mismos comandos, pero poniendo el símbolo de admiración delante. Así, podremos:

A continuación pongo un par de imágenes con algunos ejemplos, pero si queréis probar vosotros mismos, cosa que recomiendo, os dejo un enlace al notebook donde he ido haciendo todo esto

Nota: El archivo winequality.csv, lo podéis descargar desde el siguiente enlace.

introducción google colab data science

Y hasta aquí esta introducción a los Google Colab, en la próxima entrega veremos como instalar librerías de Python, para luego usarlas en la construcción y entrenamiento de un modelo de clasificación.

Saludos a tod@s y ¡a seguir a tope con vuestros proyectos!.

MÁSTER EXPERTO EN BIG DATA & ANALYTICS

Gracias al Master en Big Data Analytics 100% Online tendrás amplios conocimientos sobre las herramientas y técnicas analíticas necesarias para la modelización de los principales retos de negocio, con el fin de mejorar la toma de decisiones a través de los datos y el conocimiento.

La librería scikit-learn de Python sigue siendo una de las favoritas de los Kagglers (aunque Keras y Tensorflow ganan cada vez más adeptos). Igualmente, para todo el que desea iniciarse en Machine Learning utilizando Python como lenguaje de cabecera, la caja de herramientas que conforman numpy, pandas, matplotlib y scikit-learn se presenta como una manera razonablemente amigable de hacer los primeros pinitos.

Por ello, el hecho de que scikit-learn (biblioteca que encapsula distintas funciones de preprocesamiento de datos así como implementaciones de multitud de modelos orientados a resolver problemas tanto de aprendizaje supervisado como aprendizaje no supervisado) haya alcanzado la versión 0.20, es motivo de celebración. Qué mejor manera que celebrarlo con un pequeño post con algunas de las novedades que esta versión incorpora.

Empezando con la nueva versión de scikit-learn

Lo primero de todo es actualizar nuestra versión de scikit-learn para empezar a trastear con ella. Se recomienda utilizar algún entorno experimental (si tenéis instalado Anaconda podéis crearos uno con conda create y si no, pues con virtualenv  env). Aquí, por ejemplo, utilizamos Anaconda y lo que haremos será simplemente listar nuestros entornos y activar aquel en el cual queremos actualizar la versión de scikit-learn.

Scikit-learn versión 0.20, más madera para tus PipeLines

Una de las primeras novedades que nos llamó la atención es la que afecta a la imputación o procedimiento. Mediante esta, se rellenaban aquellos huecos en el conjunto de datos propiciados por los valores missing (nulos, NA, NaN…como se prefiera llamar). La herramienta que scikit-learn proporcionaba para solventar esta tarea era principalmente el Imputer, si bien es cierto que presentaba algunas carencias. Por ejemplo: solo podía reemplazar valores missing o enteros o no permitía imputar un valor constante. Ahora SimpleImputer pone remedio a ambas carencias. Veamos un ejemplo:

Scikit-learn versión 0.20, más madera para tus PipeLines

Dataframes y features categóricas

Se define un dataframe de pandas con columnas de distintos tipos, en la columna disponibilidad, el último de los valores es u. Consideremos u el valor que queremos reemplazar y constant la estrategia a utilizar. Al aplicar el SimpleImputer definido sobre nuestro dataframe, vemos como el valor u ha sido reemplazado por la constante definida mediante fill_value: d.

Existen casos como el de OrdinalEncoder, en el que nuevas funcionalidades han sido añadidas un componente ya existente. Recordemos que este componente transforma las features con valores categóricos, asignando a cada uno de sus posibles valores un número entre 0 y el número de categorías - 1.

Veamos un ejemplo centrado únicamente en dos features categóricas:

Scikit-learn versión 0.20, más madera para tus PipeLines

Se define de nuevo un dataframe con las dos features categóricas que va a gestionar el OrdinalEncoder. Luego, este se entrena con este dataframe aprendiendo los posibles valores que pueden tomar dichas features y transformándolos en números (del tipo indicado mediante el parámetro dtype) en el rango de 0 a número de categorías - 1. Al examinar las categorías que ha detectado el OrdinalEncoder, apreciamos que lo que ha hecho es ordenarlas alfabéticamente y asignar un número empezando por 0 a cada una de ellas para cada una de las dos features. Pero ¿qué ocurre si aplicamos el OrdinalEncoder entrenado a nuevos datos?

Usando el OrdinalEncoder para entrenar nuevos datos

Scikit-learn versión 0.20, más madera para tus PipeLines

Si fichamos un manager para nuestro equipo, OrdinalEncoder será incapaz de hacer la transformación del nuevo dataframe. La razón de esto es que ha recibido una categoría (manager) con la cual no ha sido entrenado… Aquí es cuando viene al rescate el parámetro categories. Repitamos el ejemplo:

Scikit-learn versión 0.20, más madera para tus PipeLines

La gran diferencia es que, al definir el OrdinalEncoder, hemos indicado, mediante el parámetro categories, todos los posibles valores de nuestras features categóricas. Si no especificamos ningún valor para dicho parámetro, su valor por defecto será auto. Esto básicamente indica que los posibles valores de las features categóricas se inferirán de los datos con los que se entrene. Nota: en la versión 0.20.0 el uso del parámetro categories con otro valor que no sea el por defecto, dará un error. En la versión 0.20.1 está subsanado.

Otras novedades de interés

ColumnTransformer

Finalmente, mencionaremos una de las novedades que más nos ha gustado. Scikit-Learn ya ofrecía una amplia cantidad de transformers que permiten llevar a cabo distintas operaciones sobre nuestros datos. El problema es que, en el mundo real, es sencillo encontrarse datos en los que las distintas features son de diversos tipos, esto implica que los requisitos de preprocesamiento no serán los mismos para todas ellas. Es necesario, por tanto, aplicar transformaciones de manera focalizada según el tipo de cada feature. ColumnTransformer (aun en versión experimental) nos permite seleccionar a qué columna o columnas les será aplicada cada transformación. Veamos un ejemplo:

Scikit-learn versión 0.20, más madera para tus PipeLines

Definimos primeramente un dataframe nuevo. A diferencia de los ejemplos anteriores, en los que cada transformer se aplicaba a todas las columnas de cada dataframe, en esta ocasión definimos un ColumnTransformer que nos permite montar un pipeline. En este, indicaremos las transformaciones que se desean aplicar y a qué columnas deseamos aplicarlas. El primer parámetro es una lista de tuplas en la que cada tupla indica:

Una vez hayamos definido la lista de tuplas, especificaremos, mediante el parámetro remainder, lo que queremos que les pase a las columnas que no han sido afectadas por ninguna transformación: passthrough (si queremos que pasen al final del pipeline intactas), drop (si queremos que se eliminen del resultado).

Es interesante recalcar, aún más, que el funcionamiento del ColumnTransformer es como el de un pipeline. Por tanto podremos acceder a los “eslabones” de la estructura que hayamos especificado a través de las tuplas, mediante los nombres que hayamos utilizado para denominar cada una. Por ejemplo en el caso anterior:

Scikit-learn versión 0.20, más madera para tus PipeLines

Named_transformer_

La propiedad named_transformer_ devuelve un diccionario en el que cada clave corresponde con los nombres utilizados para definir los transformer (el primer elemento de cada tupla). Al acceder al diccionario utilizando uno de estos nombres estaremos accediendo a su vez a cada uno de los transformer definidos.

Incluso es posible construir un ColumnTransformer sin necesidad de especificar un nombre para cada transformación. Por ejemplo:

Scikit-learn versión 0.20, más madera para tus PipeLines

Esta vez, no hemos especificado nombre alguno para los transformadores definidos, scikit-learn los ha nombrado por nosotros y podremos acceder a ellos a través de los nombres generados.

 

Esperemos que algunas de estas novedades introducidas en scikit-learn, os resulten tan interesantes como a nosotros; seguro que en un futuro cercano os facilitarán el trabajo. De todos modos, id con cuidado ya que algunas partes todavía son experimentales.


Alejandro Arranz, Data Engineer en datahack

MÁSTER EXPERTO EN BIG DATA & ANALYTICS

Gracias al Master en Big Data Analytics 100% Online tendrás amplios conocimientos sobre las herramientas y técnicas analíticas necesarias para la modelización de los principales retos de negocio, con el fin de mejorar la toma de decisiones a través de los datos y el conocimiento.

Tras ver qué podemos hacer conectando twitter y R y cómo hacerlo, además de algunas de las funciones más importantes, y cómo segmentamos seguidores, toca mostrar algunas de las funciones que nos permiten analizar publicaciones y hashtags.

ANÁLISIS DE PALABRAS MÁS REPETIDAS JUNTO A UN HASHTAG

Ver qué palabras tienen asociadas ciertos hashtags relevantes nos permiten no solo encontrar más hashtags para añadir a nuestra publicación, sino a detectar nuevas temáticas relacionadas y afinar las palabras que usamos en nuestras publicaciones. Lo primero que debemos hacer es instalar y llamar todas las librerías que vimos anteriormente, conectar con la API de twitter, usar la función para sacar la información del hashtag que nos interesa y convertirlo en un dataframe. Luego, lo convertimos en un string y hacemos todas las operaciones que mencioné en el artículo anterior para limpiar el texto al máximo y sacar una tabla de frecuencias con las palabras más repetidas ordenadas. Todas las instrucciones para hacer esto están en los artículos anteriores, por eso pasamos rápido por este punto.

QUÉ USUARIOS SON LOS QUE MÁS USAN ESE HASHTAG

Detectar los usuarios más activos en un tema nos ayuda no solo a detectar seguidores potenciales, sino también a influencers en el tema y a personas que pueden generar contenidos que nos interesa compartir con nuestra audiencia. Hacerlo es muy sencillo: sobre el dataframe que creamos inicialmente para sacar las publicaciones de un determinado hashtag, hacemos lo siguiente:

#qué usuarios son los que más han empleado el hashtag:
#eliminamos los retweet y nos quedamos sólo con los nombres de los usuarios que han escrito el tweet
usuarios <-subset(dataframehashtag,isRetweet==FALSE)$screenName
#Opción 1: los tabulamos y ordenamos.
usuarios<-sort(table(usuarios),decreasing=T)
#Opción 2: ver directamente los x iniciales
usuarios[1:x]

QUÉ CONTENIDOS DE UN HASHTAG SON MÁS POPULARES

En twitter, la medida de popularidad de una publicación está en la interacción que tiene (respuestas, favoritos y retweets, en especial estos dos últimos) así que sacar las publicaciones más populares de un hashtag es tan sencillo como crear un filtro en el dataframe para sacar las publicaciones en las que haya al menos x interacciones

#contenido más retuiteado
#retuiteado + fav
contenido_popular<-filter(dataframehashtag, dataframehashtag[["favoriteCount"]]>x, dataframehashtag[["retweetCount"]]>x)
#solo retuiteado
contenido_popular2<-filter(dataframehashtag, dataframehashtag[["retweetCount"]]>x)

Hay que tener presente que, según el sector, a veces la gente no hace retweet pero sí fav, o al revés, o no hace ninguna de las dos pero sí responde a las publicaciones. También, según el tipo de hashtag, x deberá ser mayor o menor. Así pues, es tan fácil como ajustar el código a las circunstancias. Luego, sobre eso, podemos hacer un nuevo filtro para sacar las palabras más populares del contenido más popular, lo que nos indicará qué no debe faltar en nuestras publicaciones para tener potencial de éxito.

ANÁLISIS DE SENTIMIENTOS DE UN HASHTAG

El análisis de sentimientos nos permite monitorizar opiniones sobre determinados temas, saber hasta qué punto en un sector se utilizan un tipo de mensajes u otros (aprovechando miedos de los consumidores para vender determinados productos frente a ventas atrayendo a los seguidores con los beneficios, por ejemplo)... Para hacerlo, además de las anteriores, necesitamos instalar y ejecutar las librerías SnowballC, tm y syuzhet. Con ellas hay que tener un poco de paciencia, a veces fallan y hay que ejecutarlas varias veces, aunque suelen funcionar de forma correcta. Hecho esto, creamos un dataframe con los datos del hashtag que nos interesa y, quedándonos solo con la columna text, eliminamos hashtags, @, url y toda la información que no es relevante para el análisis mediante la función gsub, que mostré en el artículo anterior. Luego comenzamos a trabajar con definiciones de sentimientos. Por ejemplo, podemos crear una tabla en la que nos muestre si las publicaciones contienen palabras asociadas a los sentimientos principales y cuántas hay.

#Insertando palabras de definición de sentimientos
word.df <- as.vector(dataframehashtag)
emotion.df <- get_nrc_sentiment(word.df)
emotion.df2 <- cbind(bigdata.df2, emotion.df)

Saldrá algo parecido a esto:

análisis datos twitter

También podemos sacar publicaciones donde predomine un sentimiento mediante este código:

#extrayendo puntuación de sentimientos
sent.value <- get_sentiment(word.df)
#más positivos (si queremos los más negativos, cambiamos max por min
most.positive <- word.df[sent.value == max(sent.value)]
#simplemente positivos (si queremos negativos o neutros, poner < o == respectivamente)
positive.tweets <- word.df[sent.value > 0]
#tabla resumen
category_senti <- ifelse(sent.value < 0, "Negative", ifelse(sent.value > 0, "Positive", "Neutral"))
table(category_senti)

Y este es el resumen del código utilizado en la charla de Analizando datos de twitter con R, impartida por Déborah Fernández el pasado día 27. Si queréis ver la charla completa con explicaciones más detalladas y ejecución de parte del código en directo, podéis visitar nuestro canal de youtube.

¿QUIERES APLICAR TODO ESTE CONOCIMIENTO? COMIENZA A A PROGRAMAR EN R

En nuestro curso de Análisis de datos con R aprenderás de forma rápida a utilizar este lenguaje.

Una vez tenemos claro qué podemos hacer conectando twitter y R y cómo hacerlo, además de algunas de las funciones más importantes, es el momento de comenzar nuestro análisis. El análisis de datos de twitter con R seguidores te ofrece la posibilidad de extraer más información sobre tus seguidores.

SEGMENTANDO A MIS SEGUIDORES

Una vez que hemos sacado los seguidores de un usuario con la función getfollowers que comenté en el artículo anterior, podemos hacer una segmentación por idioma, localización, nivel de influencia… El análisis de datos de twitter con R seguidores es clave para conocer más sobre los perfiles

CÓMO SE AUTODEFINEN MIS SEGUIDORES

La descripción de cada usuario en twitter es, obligatoriamente, corta. Esto le obliga a seleccionar muy bien el texto para autodefinirse de la forma más precisa. Así pues, hacer un análisis de esos textos nos ayudará a segmentarlos cualitativamente, aparte de las obvias segmentaciones más clásicas. Para ver las palabras más repetidas mediante una nube de palabras, debemos instalar y llamar las librerías wordcloud y RColorBrewer, además de las que mencioné en el artículo anterior. El análisis de datos de twitter con R seguidores es una serie de artículos.

Lo primero que debemos hacer es conectar con la API de twitter, cargar todas las librerías, sacar la información del usuario cuyos seguidores queremos analizar, conseguir sus seguidores y convertirlo todo en un dataframe (el código está en el artículo anterior). Para este ejemplo, usaremos un dataframe llamado seguidores

#convertimos la descripción de esos seguidores en un String. 
texto2 <- toString(seguidores$description)
#El texto lo transformamos en una lista separada por espacios
texto_split2 = strsplit(texto2, split=" ")
#Deshacemos esa lista y tenemos el data.frame
texto_col2 = as.character(unlist(texto_split2))
texto_col2 = data.frame(toupper(texto_col2))
names(texto_col2) = c("V1")
#Eliminamos algunos caracteres regulares
texto_col2$V1 = gsub("([[:space:]])","",texto_col2$V1)
texto_col2$V1 = gsub("([[:digit:]])","",texto_col2$V1)
texto_col2$V1 = gsub("([[:punct:]])","",texto_col2$V1)
#Creamos una variable longitud de la palabra
texto_col2$largo = nchar(texto_col2$V1)
#Quitamos palabras cortas (también hay funciones que permiten quitar palabras comunes como de, en, para...)
texto_col2 = subset(texto_col2,largo>4 & largo<=10)
#crear dataframe
palabras_seguidores = data.frame(table(texto_col2$V1))
#Ordenamos
palabras_seguidores_f<-filter(palabras_seguidores, palabras_seguidores[["Freq"]]>3)
arrange(palabras_seguidores_f, desc(palabras_seguidores_f[["Freq"]]))
#Hacemos la nube de palabras
wordcloud(words = palabras_seguidores_f$Var1, freq = palabras_seguidores_f$Freq, min.freq = 1, max.words=200, random.order=FALSE, rot.per=0.35,colors=brewer.pal(8, "Dark2"))

De esta forma, tendremos una tabla ordenada con las palabras más frecuentes y una nube de palabras que nos permitirá ver los resultados de una forma más sencilla y bonita. Por ejemplo, si lo hacemos con los seguidores de la academia digital para personas con discapacidad de Fundación ONCE, cuyos cursos hemos llevado a cabo, veremos algo parecido a esto:

análisis datos twitter

Como veis, de un solo vistazo vemos qué intereses tienen nuestros seguidores (o los seguidores de cualquiera) por orden de importancia, lo que nos da mucha información sobre ellos.

Optimizando followbacks

A la hora de crear una estrategia de followbacks efectiva no tenemos que perder el tiempo siguiendo a todo el que sigue a nuestra competencia para que nos siga de vuelta. Lo que debemos hacer es dirigirnos directamente a la gente que tiene potencial interés en nuestro tema, segmentada por lenguaje o localización y que además no sea de los que basan completamente en el followback su estrategia de crecimiento en redes sociales.

Para ello, podemos crear una columna nueva con la diferencia de seguidores y seguidos filtrando luego las filas con las características que nos interesan:

#creamos una columna nueva con la diferencia de seguidores y seguidos
followbackseguidores<-mutate(seguidores, DiferenciaSeguidos = followersCount-friendsCount)
#nos quedamos solo con las filas que tienen parámetros que nos interesan, en este caso lenguaje inglés con más seguidores que seguidos
followback1<-filter(followbackseguidores, lang=="en", DiferenciaSeguidos==TRUE)

Podemos incluso hilar más fino y quedarnos solo con los que en su descripción contienen ciertas palabras. análisis de datos de twitter con R seguidores

value <- "palabraquequieres"
followback2<-transmute(followback1, screenName, description, lang, DiferenciaSeguidos, contieneBD=grepl(value, followback1$description))
followback3<-followback2[followback2$contieneBD==TRUE,]

¿QUIERES APLICAR TODO ESTE CONOCIMIENTO? COMIENZA A A PROGRAMAR EN R

En nuestro curso de Análisis de datos con R aprenderás de forma rápida a utilizar este lenguaje.

 

Ya hemos hablado en otra entrada de qué es R y de su potencial. Hoy, nos centraremos en cómo puede esta herramienta ayudarnos a sacar el máximo partido de nuestros datos de twitter. Cada vez hay más librerías relacionadas con twitter que podemos utilizar para extraer y analizar estos datos, pero para este caso utilizaremos Twitter. ANÁLISIS DE DATOS DE TWITTER CON R

DATOS DE LOS TEXTOS GENERADOS

Cada tweet creado nos da mucha información relevante: desde su origen en según qué plataformas hasta cuántas interacciones posee, aparte del propio texto. En esta imagen, podemos ver qué información nos dan algunos de los tweets de datahack. ANÁLISIS DE DATOS DE TWITTER CON R

datos que podemos sacar de un tweet para análisis

DATOS DE LOS USUARIOS

Entre los datos más relevantes de cada usuario, podemos sacar desde su propia autodescripción, su nivel de influencia (seguidores-seguidos), cómo de activo es, procedencia… En esta imagen podemos ver la información de nuestro usuario @datahack_

datos que podemos sacar de un usuario para análisis

ANÁLISIS RELEVANTES

Con todo lo recogido, podemos sacar información bastante útil para optimizar nuestro posicionamiento y el tipo de mensajes que mandamos en las redes sociales y podemos realizar:

CÓMO EMPEZAR EL ANÁLISIS DE DATOS DE TWITTER CON R

Para conectar twitter con el programa en el que estemos ejecutando el lenguaje R, lo primero que necesitamos es una cuenta en la API de twitter. Una vez que la tengamos, podremos conectarnos gracias a las claves que nos proporcione.

La API de twitter tiene algunas limitaciones, como un número máximo de tweets recuperados por consulta y una limitación de tiempo mínimo entre consulta y consulta. Si nos pasamos podemos ser bloqueados, así que tenemos que tener cuidado y poner siempre un tamaño de muestra inferior a 200, sin hacer varias consultas en la misma ejecución. Si necesitamos muestras más grandes, podemos hacer varias consultas periódicamente en las que vayamos descargando datos (son en orden cronológico) y uniéndolos, por ejemplo. ANÁLISIS DE DATOS DE TWITTER CON R

En cualquier caso, lo más interesante del análisis de datos en twitter es la inmediatez, para ver las tendencias de cada momento, ya que los hashtags populares y las palabras asociadas a los mismos, por ejemplo, pueden cambiar de un día para otro, por lo que con una muestra de 100 es más que suficiente.

Conectaremos la API de twitter con R mediante el siguiente código:

# Cargar las credenciales
consumer_key <- "xxx"
consumer_secret <-"xxx"
access_token <-"xxx"
access_secret <-"xxx"
setup_twitter_oauth(consumer_key, consumer_secret, access_token=access_token, access_secret=access_secret)

FUNCIONES BÁSICAS

Una vez hecho esto, podemos ponernos a trabajar. Algunas de las funciones más básicas que debemos aprender son las llamadas para recuperar información y cómo convertirlas en dataframes   con los que trabajar. No olvidemos que, para trabajar con los datos de twitter, tendremos que instalar y llamar las librerías twitteR, base64enc y tidyverse

SACAR TODA LA INFORMACIÓN DEL TIMELINE Y CARACTERÍSTICAS DE UN USUARIO

#sacar tweets de un usuario:
usuario<- userTimeline('usuario',n=100)

Para conseguir solo algunos de los datos más importantes, como seguidores y seguidos, podemos usar este código (sin olvidar convertirlo después en un dataframe):

#Sacar información de un usuario:
usuario<- getUser('usuario')
#conseguir sus seguidores
usuario_seguidores <- usuario$getFollowers(retryOnRateLimit=120)
#conseguir sus seguidos
usuario_seguidores <- usuario$getFriends(retryOnRateLimit=120)

SACAR TODA LA INFORMACIÓN DE UN HASHTAG

#buscamos el hashtag, limitamos la búsqueda a 100 tweets desde el 01 de junio de 2018.
hashtag<-searchTwitter("#hashtag", n=100, since='2018-06-01')

HACER LOS DATAFRAMES

No hay que olvidar que toda esta información que saquemos, para trabajar con ella, hay que convertirla en un dataframe con la función do.call o twListToDF. Esta es la estructura de ambas:

do.call("rbind", lapply(xxx, as.data.frame))
twListToDF(xxx)

ANÁLISIS DE DATOS DE TWITTER CON R. Una vez que tenemos todo esto, podemos comenzar a trabajar en el análisis de toda esa información, que es lo que mostraremos en los próximos artículos:

¿QUIERES APLICAR TODO ESTE CONOCIMIENTO? COMIENZA A A PROGRAMAR EN R

En nuestro curso de Análisis de datos con R aprenderás de forma rápida a utilizar este lenguaje.

 

Ya estamos aquí para continuar el relato donde lo dejamos en el artículo anterior de esta serie. La trama quedó en suspense después de mostrar que un programa de Tensorflow se divide en 2 fases. La primera consiste en la construcción del grafo que alberga por un lado las operaciones a realizar y por otro los tensores que contienen los valores que alimentan a dichas operaciones. La segunda etapa se basa en la creación de un objeto de sesión que permitirá ejecutar el grafo sobre dispositivos locales o remotos. Sigamos con este recorrido por los principales componentes del Core de Tensorflow.

Sesión

La clase tf.Session permite conectar un programa cliente, que actúa como frontend en alguno de los lenguajes disponibles como Python, gracias al “Tensorflow Distributed Execution Engine” de C++. Un objeto de esta clase tf.Session proporciona el entorno para ejecutar objetos tf.Operation y evaluar objetos tf.Tensor. Esto lo hace tanto en dispositivos (como CPUs, GPUs, TPUs) de la máquina local como de máquinas remotas. También proporciona el entorno para cachear el grafo que tenga asociada dicha sesión.

Como se ha comentado, en DIA4RA vamos a emplear la API de alto nivel Estimator que, entre otros beneficios, creará y gestionará el objeto tf.Session por nosotros. Además, nos permitirá abstraernos de escribir el código de bajo nivel necesario para poder realizar un entrenamiento distribuido entre múltiples máquinas. Por ello, aunque no vayamos a manejar sesiones de forma explícita en nuestro proyecto, vamos a mostrar una pequeña introducción en las siguientes líneas.

El constructor de esta clase recibe de forma opcional 3 argumentos:

Una práctica habitual a la hora de crear una sesión es la de hacerlo mediante un bloque “with” de Python. De esta forma, la sesión estará activa dentro del ámbito de dicho bloque y al salir se cerrará automáticamente y se liberarán sus recursos. En caso de no emplearse un bloque “with” será necesario cerrar explícitamente esa sesión mediante tf.Session.close para que se liberen sus recursos.

Para realizar la ejecución propiamente dicha se emplea el método tf.Session.run que recibe una lista con los tf.Operation o/y tf.Tensor que se pretenden ejecutar y que deben estar presentes en el grafo asociado a dicha sesión.

En la siguiente captura de pantalla se muestra la creación del grafo por defecto que contendrá la operación creada mediante tf.add que trabajará sobre los arrays de numpy “a” y “b” (cuyo valor se obtiene inmediatamente al no ser tensores de Tensorflow). A continuación, se genera mediante un bloque “with” la sesión “sess” y dentro de su ámbito se ejecuta empleando sess.run la operación de suma. Al finalizar el ámbito del bloque “with” se cerrará automáticamente la sesión.

Programando con la API de Bajo Nivel de Tensorflow

A continuación, se puede ver otra imagen en la que se ha creado el grafo “g1” al que se le ha añadido la operación creada mediante tf.multiply que trabajará sobre los arrays de numpy “d” y “e”. Una vez hecho eso, se crea la sesión “sess1” que operará sobre el contenido del grafo “g1” únicamente. Mediante sess1.run se ejecuta la multiplicación presente en “g1” y como la sesión no se ha creado mediante un bloque “with”, como buena práctica cuando ya no se va a emplear más dicha sesión, se cierra utilizando sess1.close.

Programando con la API de Bajo Nivel de Tensorflow

En estos ejemplos se han utilizado sesiones que trabajan sobre recursos presentes en la máquina local. La API de Bajo Nivel de Tensorflow permite que la sesión pueda acceder a dispositivos presentes en otras máquinas que trabajen conjuntamente formando un clúster permitiendo un cálculo distribuido. En DIA4RA emplearemos la abstracción de ejecución distribuida que ofrece la Estimator API para realizar entrenamientos en paralelo entre múltiples máquinas presentes en el Cloud.

Los clúster distribuidos de Tensorflow

Un clúster distribuido de Tensorflow estará formado por uno o más jobs, de forma que cada job puede contener una o más tasks. Las tasks de un job colaboran en una ejecución distribuida de un grafo. Normalmente cada task se ejecuta en una máquina diferente pero también es posible ejecutar varias tasks en la misma máquina, por ejemplo, empleando un dispositivo diferente presente en dicha máquina (si dispone de varias GPUs). Cada tarea estará asociada a un tf.train.Server que estará formado por un master para crear sesiones y por un worker para ejecutar operaciones del grafo.

Una técnica muy utilizada cuando se realiza un entrenamiento distribuido consiste en emplear procesos que actuarán como Parameter Servers. Las variables serán repartidas entre los parameter servers disponibles en función de su tamaño para balancear la carga.  Cuando un proceso worker necesite un variable almacenada en un parameter server, hará referencia directamente a ella. Cuando un worker calcule un gradiente, será enviado al parameter server que almacene esa variable concreta.

Para crear un clúster será necesario por un lado crear un objeto de la clase tf.train.ClusterSpec y uno o varios tf.train.Server.

La clase tf.train.ClusterSpec permite indicar todas las tasks del clúster. Su constructor recibirá un diccionario mapeando cada nombre de job a una lista de direcciones de red de las tasks de ese job o a otro diccionario en el que cada clave será un índice de task y su correspondiente valor será la dirección de red de dicha task.

El siguiente fragmento de código crea la configuración de un clúster formado 2 workers y 1 parameter server.

cluster = tf.train.ClusterSpec({“worker”: [“192.168.1.120:3333”, “192.168.1.121:3335”],
                                            “ps”: [“192.168.1.122:3335”]
                                            })

A continuación, lo que habrá que hacer es instanciar  los servers correspondientes a los 2 workers y al parameter server.

server0 = tf.train.Server(cluster, job_name=“worker”, task_index=0)
server1 = tf.train.Server(cluster, job_name=“worker”, task_index=1)
serverPs = tf.train.Server(cluster, job_name=“ps”, task_index=0)

El siguiente paso será emplear la función tf.device para especificar en qué proceso se colocará cada operación:

with tf.device(“/job:ps/task:0”):
    var0 = tf.Variable( … )
    var1 = tf.Variable( … )
    var2 = tf.Variable( … )
with tf.device(“/job:worker/task:0”):
    res0 = tf.matmul(var0, var1)  
with tf.device(“/job:worker/task:0”):
    res1 = tf.matmul(var1, var2)

En este punto, se crearán las sesiones necesarias y cada una de ellas se asociará con un server (2 workers y 1 parameter server).

sessPs = tf.Session(target=serverPs.target)
sess0 = tf.Session(target=server0.target)
sess1 = tf.Session(target=server1.target)

Dichas sesiones se emplearán para ejecutar las operaciones asociadas a esos servers (tasks). En un futuro artículo se presentará de forma práctica un entrenamiento distribuido empleando la API de Bajo Nivel de Tensorflow. Pero antes, vamos a continuar con el recorrido por sus componentes básicos.

Asignación de dispositivos mediante tf.device()

En Tensorflow los dispositivos disponibles para ejecutar operaciones son CPUs y GPUs. La notación que se emplea para referenciarlos es la siguiente:

La secuencia seguiría aumentándose el índice de la GPU si existiesen más de estos dispositivos. Por defecto, si una operación está implementada para poder ejecutarse tanto en CPU como en GPU, los dispositivos GPU tendrán prioridad a la hora de recibir esa operación.

En primer lugar, para visualizar los dispositivos disponibles en la máquina se podrá ejecutar el siguiente código:

from tensorflow.python.client import device_lib
device_lib.list_local_devices()

Programando con la API de Bajo Nivel de Tensorflow

Si se desea colocar una o varias operaciones en un dispositivo en concreto la forma de hacerlo será empleando un bloque “with” con la función tf.device() que recibirá el nombre de dicho dispositivo.

with tf.device(“/gpu:0”):
    a = tf.constant([2, 7, 3])

Constantes

Se trata de un tensor que tiene un valor constante que se crea mediante la función tf.constant() y dispone de los siguientes argumentos:

Programando con la API de Bajo Nivel de Tensorflow

Variables

Una variable de Tensorflow permite almacenar un tensor cuyo valor puede ser cambiado ejecutando una serie de operaciones sobre ella. Esas modificaciones son visibles desde múltiples objetos tf.Session lo que permite que diferentes workers puedan acceder al valor de una misma variable.

A bajo nivel la clase que se encarga de su implementación se trata de tf.Variable. En cuanto a la creación de variables la forma recomendada es mediante la función tf.get_variable, que recibe el nombre de dicha variable y su shape entre otros argumentos opcionales como su valor inicial.

var1 = tf.get_variable(“test”, [2, 1, 4], dtype=tf.int64)

Ese comando creará una variable llamada “test” de 3 dimensiones y shape [2, 1, 4], cuyos valores serán de tipo tf.int64 (en caso de no indicarse el parámetro dtype, el tipo por defecto será tf.float32) y su valor inicial se establece por defecto a partir a partir de la distribución aleatoria determinada por tf.glorot_uniform_initializer.

Esta función (también llamada inicialización Xavier) generará muestras aleatorias entre [-a, a], donde:

Si se desea indicar un initializer en concreto se puede hacer de la siguiente forma:

var2 = tf.get_variable(“test2”, [5, 2, 4, 1], dtype=tf.int32, initializer=tf.zeros_initializer)

En caso de que el initializer sea un tf.Tensor entonces no habrá que indicar el shape en el constructor de tf.get_variable ya que lo inferirá a partir del shape de ese initializer ([2, 3]):

var4 = tf.get_variable(“test4”, initializer=tf.constant([2,3]))

Las “collections” de Tensorflow son listas con nombre de tensores u otros objetos como variables. Cuando se crea una variable se añadirá por defecto en las colecciones tf.GraphKeys.TRAINABLE_VARIABLES (son las variables para las que Tensorflow calculará sus gradientes) y tf.GraphKeys.GLOBAL_VARIABLES (variables que pueden ser compartidas entre múltiples dispositivos).

Para hacer que una variable no sea tenida en cuenta a la hora de calcular los gradientes habría que pasar el parámetro “trainable=False” a la hora de su creación.

var5 = tf.get_variable(“test5”, [4, 2], trainable=False)

Se pueden crear collections personalizadas utilizando cualquier cadena como nombre. Para añadir un objeto ya creado a una colección se empleará el método tf.add_to_collection.

tf.add_to_collection(“col1”, var4)

La forma de conocer todos los objetos de una collection es mediante la siguiente función:

tf.get_collection(“col1”)

Hasta este punto hemos visto cómo crear variables y cómo unirlas a collections. Pero antes de poder utilizar una variable hay que añadir una operación al grafo para que la inicialice explícitamente, lo que permite evitar que se vuelvan a ejecutar initializers que pueden consumir un tiempo importante, por ejemplo, al volver a cargar un modelo desde un “checkpoint”.

La función que emplearemos para inicializar una única variable será:

sess = tf.Session()
sess.run(var1.initializer)

Pero como ir inicializando variable por variable puede ser muy tedioso, hay una función que viene a nuestro rescate, tf.global_variables_initializer(). Se encarga de añadir una única operación al grafo que, cuando sea ejecutada, inicializará todas las variables presentes en la collection  tf.GraphKeys.GLOBAL_VARIABLES.

init = tf.global_variables_initializer()
sess1 = tf.Session()
sess1.run(init)

Esta función no asegura el orden en que serán inicializadas las variables. De forma que si hay variables que dependen de otras y no estamos seguros de si ya han sido inicializadas, una forma de programar de forma segura es empleando en la variable dependiente la función var_de_la_que_se_depende.initialized_value().

a = tf.get_variable(“a”, [1,2], initializer=tf.zeros_initializer())
b = tf.get_varible(“b”, initializer=a.initialized_value() * 2)

Si se quiere asignar un nuevo valor a una variable se podrán emplear la familia de funciones assign, assign_add.

sum = a.assign(a + 7.0)
sum2 = a.assign_add(8.0)

La instrucción tf.get_variable puede encontrarse en un bloque de código (una función) que puede ser ejecutado repetidas veces. No quedaría claro si lo que se pretende es volver a crear la misma variable o reutilizarla. Una forma de solucionar esto es creando una variable dentro de un bloque “with” con tf.variable_scope (eso añadirá el nombre del variable_scope al principio del nombre de la variable) y cuando se quiera reutilizar dicha variable, la instrucción tf.get_variable se incluirá en el interior de  un tf.variable_scope con el mismo nombre que cuando se creó pero que además recibirá el parámetro "reuse=True".

En caso de no utilizar el flag "reuse=True", si la variable ya había sido previamente creada mediante una llamada a get_variable, al volver a intentar crearla se obtendrá una excepción o si no se creó mediante una llamada a get_variable. Esto permite evitar reutilizar variables por error. Una vez establecido reuse a True ya no se puede poner a False dentro del bloque. También se puede fijar el flag reuse a True dentro del bloque llamando a scope.reuse_variables().

A continuación, vamos a ver un ejemplo de utilización de la función get_variable para crear una variable compartida si no existe o reutilizarla en caso de que exista. Esto se controla dentro del scope "relu". Si se definen otros variable scopes dentro del actual, heredarán el flag "reuse=True".

Las variables creadas usando get_variable siempre se nombran utilizando el nombre de su variable scope como prefijo. Por ejemplo, relu/threshold. Si se crea un scope con un nombre que ya había sido utilizado por otro scope, se añadirá un sufijo "índice" para que el nombre sea único.

Se definirá una función "relu()" que reutilizará una variable relu/threashold. Dicha variable será creada fuera de la función inicializándola a 0.0. A continuación se construirán 5 relus llamando 5 veces a la función "relu()".

tf.reset_default_graph()

def relu(X):
    with tf.variable_scope("relu", reuse=True): # Reutilización de la variable threshold
        threshold = tf.get_variable("threshold", shape=(), initializer=tf.constant_initializer(0.0))
        w_shape = int(X.get_shape()[1]), 1
        w = tf.Variable(tf.random_normal(w_shape), name="weights")
        b = tf.Variable(0.0, name="bias")
        linear = tf.add(tf.matmul(X, w), b, name="linear")
        return tf.maximum(linear, threshold, name="max")

X = tf.placeholder(tf.float32, shape=(None, n_features), name="X")
with tf.variable_scope("relu"): # Creación de la variable threshold
    threshold = tf.get_variable("threshold", shape=(), initializer=tf.constant_initializer(0.0))
relus = [relu(X) for i in range(5)]
output = tf.add_n(relus, name="output")

Placeholders

Un tf.placeholder es una estructura que almacenará datos pero dichos datos serán cargados en tiempo de ejecución. Por tanto, nos permitirá definir un almacén de información que podrá ser añadido al grafo sin tener que alimentarlo hasta que se cree una sesión y se desee ejecutar operaciones que dependan de este placeholder.

Para ello, el método sess.run deberá recibir como parámetro además de las operaciones a ejecutar, un argumento llamado feed_dict que será un diccionario donde cada clave será el nombre de un placeholder y su correspondiente valor será justamente el valor que queramos que reciba esa estructura.

import tensorflow as tf

a = tf.placeholder(“float”, None)
b = a + 7

with tf.Session() as sess:
    r = sess.run(b, feed_dict={a:[6,3]})

Como se ha podido apreciar, no es necesario definir estáticamente un tamaño para los datos que albergará un tf.placeholder. También puede tener cualquier número de dimensiones y cuando alguna de sus dimensiones sea “None”, significa que puede tener cualquier número de elementos en ella.

import tensorflow as tf

a = tf.placeholder(“float”, [None, 2])
b = a + 7

with tf.Session() as sess:
    r = sess.run(b, feed_dict={a:[[1, 4], [3, 5], [7, 9]]})

---

Hasta aquí este breve repaso a los componentes básicos del Core de Tensorflow. En próximos artículos continuaremos viendo APIs de más alto nivel de este potente framework de Google.

 

dia4ra cdtiEl proyecto empresarial de DATAHACK CONSULTING SL., denominado “DESARROLLO DE INTELIGENCIA ARTIFICIAL EN ROBOTS APLICADOS AL TRATAMIENTO DEL ALZHEIMER Y LA DEMENCIA” y número de expediente 00104725 / SNEO-20171211 ha sido subvencionado por el CENTRO PARA EL DESARROLLO TECNOLÓGICO INDUSTRIAL (CDTI)

MÁSTER EXPERTO EN BIG DATA & ANALYTICS

Gracias al Master en Big Data Analytics 100% Online tendrás amplios conocimientos sobre las herramientas y técnicas analíticas necesarias para la modelización de los principales retos de negocio, con el fin de mejorar la toma de decisiones a través de los datos y el conocimiento.

chevron-down