Nuevos proyectos y Python Toolbox 1

Hace ya unas semanas que no escribo nada y no me gusta. Este blog me permite poner en orden mis ideas y nuevos conocimientos y, la verdad, creo que me resultaba super útil, así que voy a intentar volver a escribir con regularidad. La razón por la que he dejado de escribir estas últimas semanas ha sido que en el trabajo me han asignado un nuevo proyecto y estaba a tope.

Nuevo proyecto: creación de datasets

En este nuevo proyecto que me han asignado estoy creando automáticamente datasets para lueg entrenar un sistema de extracción de intenciones. El objetivo es saber qué está pidiendo el usuario. En concreto, me centro en intenciones en el dominio de soporte informático (IT). Por ejemplo: ¿Quiere que le cambien el portátil? ¿No puede conectarse a internet? ¿Tiene un problema con su teclado?

Pero, antes de entrenar, lo que estamos haciendo es crear un dataset de posibles preguntas que puede hacer el usuario para pedir/preguntar todas esas cosas. Para crearlo estoy usando Chatito, una herramienta de código abierto, que genera conjuntos de datos (datasets) que luego podremos usar para entrenar el sistema.

El input de Chatito son nuestros posibles patrones, es decir, las posibles frases que el usuario puede usar para plantear esos problemas/peticiones al servicio técnico. El output son una serie de documentos JSON que pueden estar en formato RASA NLU, Flair, LUIS o snips NLU. En nuestro caso, vamos a trabajar con RASA NLU, así que cacharrear con este framework está ya entre mis deberes.

Python toolbox 1

Aparte del proyecto que comento, hoy continúo mi proceso de aprendizaje con DataCamp, con el curso de Python toolbox 1. Mi objetivo es completar los 4 cursos de Python que eran requisito del curso Natural Language Processing Fundamentals with Python, también de esta misma plataforma.

Este curso está compuesto de 3 módulos. El primero está dedicado a escribir tus propias funciones. Como antes, en algunos de los módulos de los cursos anteriores, ya sé cómo se hace, pero siempre aprendo algo nuevo y más dirigido a la ciencia de datos, no en general como en otros cursos que hice en el pasado.

Qué he aprendido hoy
  • Definir una función propia con un parámetro y devolver (return) un valor (vídeo 1)
def square(value) # function header with a parameter "value". Signature of the function
    new_value = value ** 2    
    return(new_value)

valor = square(4)  ## así llamamos a la función, usando un argumento concreto, en este caso 4.
print(valor)
  • Definir una función propia con más de un parámetro (vídeo 2)
def square(value1, value2)
    new_value = value1 ** value2
    return(new_value)

valor = square(4, 2)
print(valor)
  • Primeras nociones de tuplas: Son similares a las listas ya que pueden contener distintos valores, pero son inmutables, es decir, una vez creadas no podremos cambiar sus valores. Las tuplas se construyen con los paréntesis. (Recuerdo: los diccionarios los creábamos con {} y las listas con [] )
numeros_pares = (2, 4, 6) ## creamos una tupla

a, b, c = numeros_pares ## empaquetamos cada elemento en una variable

numeros_pares[1]  ## accede al segundo elemento de la tupla
print(numeros_pares) ## los imprimirá todos en pantalla

Y, hasta aquí llegamos por hoy (50% del primer módulo hecho), que tengo que volver al proyecto!

Acabando Python intermedio

Pues, tal y como digo en el título, hoy voy a intentar acabar por fin el curso intermedio de Python para Ciencia de Datos de DataCamp. Sólo me queda el último módulo: Hacker Statistics! 😀

Random Generators

Podemos generar números aleatorios con un submódulo del módulo Numpy (por eso lo llamamos con la notación del punto. Dentro de este subpaquete también habrá otras funciones como

  • seed()
  • rand(): por defecto, genera un número decimal aleatorio entre 0 y 1.
  • randint(): general números enteros aleatorios.
import numpy as np

np.random.rand()   # esto genera un número pseudo-aleatorio

coin = np.random.radint(0,2) # esto genera un número entero aleatorio (0 o 1). El dos no está incluido.

# simulación de un dado
dice = np.random.randint(1,7)

Concepto de Random Walk

max(): nos devuelve el mayor de dos argumentos.

np.transpose()

¡Acabado el curso!

El siguiente paso es el Python Data Science Toolbox (1). Este, junto con su segunda parte, completarán los prerequisitos exigidos para el curso de Procesamiento de Lenguaje Natural Básico con Python. ¡Qué ganas de seguir progresando, la verdad! 🙂

Python intermedio para ciencia de datos

Esta mañana he hecho una entrevista para un puesto de Data Scientist. Creo que todo ha ido bien!! 😀 Como mi sprint con RDF y Linked data era sobre todo para prepararme para la entrevista, hoy voy a continuar con el curso de Python intermedio que se me quedó a medias la semana pasada. No sé si voy a poder continuar con mi «estudio» durante las próximas semanas ya que tengo un proyecto de tres semanas en camino, así que me gustaría, al menos, acabar este curso.

Continúo pues con el módulo 3. Muy facilito: operadores de comparación, booleanos, control de flujo, etc.

Algunos apuntes/cosas nuevas:

  • Los operadores booleanos (and, or, not) no funcionan por sí solos en Numpy. Tendremos que usar np.logical_and(), np.logical_or(), np.logical_not().
if condition:
   expression
elif condition:
   expression
else:
   expression

Filtrar un DataFrame de Pandas

  1. Tendremos que encontrar la columna correcta. Aquí tendremos que seleccionar como output un Panda Series, no un Panda Dataframe, es decir, tendremos que hacerlo con corchetes simples. Por ejemplo: mi_dataframe[«columnaX»], mi_dataframe.loc[:, «columnaX»] o mi_dataframe.iloc[:, 2] (2 sería la columna 2).
  2. Establecer la comparación. Por ejemplo: mi_dataframe[«columnaX»] > 8. Esto nos devolverá la columna correspondiente como una Panda Series con booleans, es decir, True donde se cumpla y False donde no se cumpla esa condición.
  3. Filtrar. Podemos crear una nueva variable con la comparación. Ejemplo: is_huge = mi_dataframe[«columnaX»] > 8 . Si luego, filtramos (my_dataframe[is_huge]), obtendremos solo las filas de los elementos con la columnaX mayor de 8.

Como las filas de un dataframe son arrays de Numpy, si queremos usar los operadores lógicos/booleanos para filtrar, deberemos tener en cuenta las formas que comentábamos más arriba.

*** Módulo 3 acabado!!! ***

Empiezo el módulo 4, dedicado a los bucles.

while condition:
     expression
for var in seq:
     expression

# para iterar sobre un diccionario necesitamos el método items()
for key, value in my_dict.items(): 
...

# para iterar sobre un array multidimensional necesitamos esto
for val in np.enditer(my_array):
...

#iteraciones en DataFrames de Pandas
# esto nos dará los nombres de las columnas
for val in DataFrame:
    print(val)

# esto nos devolverá todos los datos de una fila
for lab, row in DataFrame.iterrows():
     print(lab)
     print(row)

Algunos apuntes/cosas nuevas:

enumerate() : nos devuelve el índice del elemento de una lista.

np.enditer(arrayname): nos devuelve los elementos del array en columna, no como una lista con corchetes.

Cuando iteramos sobre un diccionario el resultado estará desordenado ya que los diccionarios en Python no siguen un orden predeterminado.

*** Módulo 4 acabado!! **

Linked Data: RDF, SPARQL y Question Answering systems (2)

En la primera parte de la tarde he estado instalando MYSQL, pero mañana tengo una entrevista en la que piden un Data Scientist que sepa de sistemas pregunta-respuesta, así que voy a continuar con el artículo que empecé el otro día.

Dificultades de este tipo de sistemas:

  • traducir las preguntas hechas en lenguaje natural a SPARQL
  • elegir los datasets adecuados (donde podamos encontrar respuestas!).
  • encontrar los URIs correctos. Por ejemplo, la clase dbo:Film no tiene otras variantes como «movie» o similares. Esto nos obligará a conocer o tener que hacer una búsqueda de los URIs adecuados.
  • Problemas con cuantificadores como «el más» (most), «la menos» (less)… Este tipo de estructuras se corresponden con «aggregation operations» de SPARQL (como filtrar, ordenar, limitar…)
  • Casos de ambigüedad. Distintos RDF pueden tender distintos tipos de recursos.
  • Multilenguaje. La mayoría de los datasets están en inglés.
  • Accuracy: Respuestas erróneas en este tipo de sistemas son, normalmente, peores resusltados que no tener una respuesta. El sistema tendría que detectar casos en los que no tuviéramos respuesta posible en el dataset. Además podríamos encontrar inconsistencias entre distintos datasets.
  • Deberían dar una respuesta en tiempo real.
  • Mezcla de datos estructurados y no estructurados. Por ejemplo: ¿Dónde murió el primer hombre que fue al espacio? En este caso, tenemos que saber, por un lado, quién es el primer hombre que fue al espacio y, una vez que lo conocemos, ir al RDF y ver dónde murió.

Existen clasificaciones de los tipos de preguntas que un usuario puede hacer a este tipo de sistemas: preguntas de sí/no, preguntas de definiciones, preguntas de listas, etc.

Los recursos de datos que se pueden usar para llegar a la respuesta que busca el usuario son de distintos tipos:

  • Datos estructurados: bases de datos relacionales, linked data…
  • Datos semi-estructurados: documentos XML
  • Datos no estructurados: textos

Estos sistemas, por tanto, pueden ser híbridos (si consultan distintos tipos de datos) o solo basar sus respuestas en un único tipo de datos. Además, podrán consultar solo un data set, un conjunto de ellos o todos los que estén disponibles.

Por último, podrá ser un sistema de pregunta-respuesta para un dominio o un sistema general.

Empezando con SQL y SPARQL

Estoy viendo que en la mayoría de las ofertas a las que quiero postularme piden conocimientos de SQL así que, ya que estoy, voy a ponerme con ello también. He visto que el SPARQL se basa, en realidad, en SQL así que, de esta manera, mato dos pájaros de un tiro.

Ya sabía que SQL se trataba de un lenguaje con que preguntarle cosas a nuestras bases de datos, pero la verdad es que no tenía claro cómo o dónde poner esas preguntas! He estado buscando y creo que lo voy a poder hacer instalando MySQL, el software que me permitirá acceder a esas bases de datos.

Para instalarlo, uno de los requisitos era tener Microsoft Visual Studio instalado también. Sé que es una herramienta para desarrolladores, pero me voy a poner en los deberes el investigar un poquito más sobre esta herramienta.

En cuanto a SPARQL, tampoco me quedaba claro cómo usarlo para extraer información de los grafos RDF (no la sintaxis, sino CÓMO, DESDE DÓNDE!!). He estado buscando esto también y he descubierto que existen diferentes implementaciones de SPARQL donde poner esas «preguntas». Algunas como Virtuoso me sonaban de las ofertas de empleo.

Se pueden hacer queries a los distintos grafos RDF a través del web service de Virtuoso SPARQL .

Una hora después…. ok! Ya tengo MySQL instalado!! Yujuuu!! Ahora sólo falta que aprenda a usarlo porque no sé ni por dónde empezar, tiene millones de funcionalidades! OMG! :S

Deberes

  • Microsoft Visual Studio

¿Qué es RDF?

La semana pasada estuve investigando un poco sobre la web semántica y cómo utilizar los datos de ella para construir sistemas de pregunta-respuesta. Hoy, voy a leer un poquito más sobre qué es RDF.

Un triplet de RDF simplemente establece una relación entre dos recursos. El sujeto y el objeto son los elementos que relacionamos y el predicado es el tipo de relación que hay entre ellos. Esa relación entre el sujeto y el objeto representará lo que en RDF se llama una «propiedad«.

Sample triples (informal), pseudocode.

<Bob> <is a> <person>.
<Bob> <is a friend of> <Alice>.
<Bob> <is born on> <the 4th of July 1990>. 
<Bob> <is interested in> <the Mona Lisa>.
<the Mona Lisa> <was created by> <Leonardo da Vinci>.
<the video 'La Joconde à Washington'> <is about> <the Mona Lisa>

Estas relaciones conformarán grafos dirigidos (con una dirección concreta). Podemos hacer preguntas sobre la información de estos grafos con SPARQL.

Existen tres tipos de datos que pueden aparecer en estos nodos:

  • IRIs: el ID del recurso, similar a la URL de una web (de hecho una URL es un tipo específico de IRI), a lo que apunta. Pueden aparecer en el sujeto, el objeto o el predicado.
  • literales: strings, números, fechas, etc. Sólo pueden ser objetos.
  • nodos vacíos o variables. Representan elementos sin un identificador. Pueden ser objetos o sujetos. Esa parte del cuadro de la Mona Lisa es un ejemplo de nodo vacío.
Blank node example: cypress tree

Un dataset de RDF estará consituido por varios grafos. Cada grafo dentro de un dataset tendrá asociado su IRI. Por ejemplo:

Informal graph of the sample dataset

RDF SCHEMA

Los recursos serán clasificados en CLASES y subclases que especifican las categorías a las que pertenecen. Asimismo, existirán distintos TIPOS de propiedades. Así, se podrán crear jerarquías de clases y subclases y de tipos y subtipos de recursos. Las restricciones por tipo serán definidas por los DOMINIOS o los RANGOS de las propiedades. Queda más claro, en esta tabla:

ConstructSyntactic formDescription
Class (a class)C rdf:type rdfs:ClassC (a resource) is an RDF class
Property (a class)P rdf:type rdf:PropertyP (a resource) is an RDF property
type (a property)I rdf:type CI (a resource) is an instance of C (a class)
subClassOf (a property)C1 rdfs:subClassOf C2C1 (a class) is a subclass of C2 (a class)
subPropertyOf (a property)P1 rdfs:subPropertyOf P2P1 (a property) is a sub-property of P2 (a property)
domain (a property)P rdfs:domain Cdomain of P (a property) is C (a class)
range (a property)P rdfs:range Crange of P (a property) is C (a class)

Con este RDF Schema podremos crear modelos de datos RDF como el siguiente:

Example 5: RDF Schema triples (informal)

<Person> <type> <Class>
<is a friend of> <type> <Property>
<is a friend of> <domain> <Person>
<is a friend of> <range> <Person>
<is a good friend of> <subPropertyOf> <is a friend of>

Ejemplos de vocabularios RDF

Formatos para crear grafos RDF

Lo copio directamente de la web que estoy consultando:

  1. Turtle family of RDF languages (N-Triples, Turtle, TriG and N-Quads);
  2. JSON-LD (JSON-based RDF syntax);
  3. RDFa (for HTML and XML embedding);
  4. RDF/XML (XML syntax for RDF).

El que más me interesa es el JSON-LD, ya que es que el veo que más están pidiendo, así que sigo con este. El JSON-LD sigue la sintaxis de los documentos JSON para crear grafos y datasets de RDF. JSON-LD se puede utilizar para transformar documentos en JSON a RDF con cambios mínimos.

Example 12: JSON-LD

01    {
02      "@context": "example-context.json",
03      "@id": "http://example.org/bob#me",
04      "@type": "Person",
05      "birthdate": "1990-07-04",
06      "knows": "http://example.org/alice#me",
07      "interest": {
08        "@id": "http://www.wikidata.org/entity/Q12418",
09        "title": "Mona Lisa",
10        "subject_of": "http://data.europeana.eu/item/04802/243FA8618938F4117025F17A8B813C5F9AA4D619",
11        "creator": "http://dbpedia.org/resource/Leonardo_da_Vinci"
12      }
13    }

Ejemplos de datasets de RDF

  • Wikidata
  • DBpedia
  • WordNet
  • Europeana
  • VIAF

Debido a que los grafos son el resultado de distintas relaciones entre recursos, también podemos inducir propiedades de elementos que no están directamente relacionados en nuestro grafo. Por ejemplo, si sabemos que <Bob> <conoce a> <Ana>, entonces podemos deducir que <Bob> <es una> <persona> puesto que en nuestro grafo también definíamos el predicado <conoce a> como una relación entre dos <personas>.