Archive for the 'Aprendizaje Automático' Category

Aplicando Machine Learning a FinTech (2) Algoritmo Genético para Estrategia de Trading

Friday, December 25th, 2015

Anterior Post

El año pasado puse a punto una librería de algoritmos genéticos, con ejemplos que usé en la JSConf 2014 de Argentina.

https://github.com/ajlopez/SimpleGA

Hace unas semanas volví a usarla para otro ejemplo, esta vez orientada a FinTech: generar estrategias de compra/venta de acciones. Era una de las ideas que tenía preparadas para el Hackathon internot de Poincenot. Pero luego el tema del hackathon no fue FinTech, sino orientado a CashMoon. Igual me gustó la idea inicial, y hoy seguí explorándola. Veamos los primeros resultados. Pueden verlo en:

https://github.com/ajlopez/SimpleGA/tree/master/samples/trading

Lo que me faltaba eran datos de acciones. Los conseguí de los datos que usa el juego de Bloomberg

http://www.bloomberg.com/features/2015-stock-chart-trading-game/

Cada compañía tiene valores en un archivo .csv, y los tomé como ejemplos de entrenamiento. Muchos de los valores son diarios, y otros son por día/hora, o por día pero espaciados. Debería conseguir mejores valores. Espero que el próximo experimento lo haga con valores diarios de acciones de compañías de mi pais, Argentina. Eso queda para próximo post.

El desarrollo del genotipo fue encarado, en lo que se pudo, siguiendo TDD (Test-Driven Development). Como hay un componente aleatorio en el desarrollo de una población, algunos tests quedaron siendo no determinísticos. Pero para lo que necesito ahora basta.

Como siempre, sigo dos guías en mis desarrollos: simplicity pays, y baby steps.

Esos dos principios me llevaron a primero probar con datos simples, de series ascendentes, o series de valores descendentes. Despues, a no preocuparme por los días: solo me interesa cómo varia el valor de una acción del tiempo T al tiempo T+1, donde el intervalo puede ser cualquiera. Luego de los primeros resultados se puede ir mejorando el experimento, el algoritmo y los datos.

Y con respecto al algoritmo del genotipo, su forma de representarse y evaluarse, quedará como tema de otro post. Pero baste adelantar que se basa en examinar valores consecutivos en el tiempo de una acción (por ejemplo, su comportanmiento en 3 “días”), y si baja o sube, comprar o vender tal monto (en unidades de moneda). Cada uno de los genes expresa una de esas estrategias.

El tema de la simplicidad me lleva a usar NodeJS y mi propia librería: no necesito frameworks mamutescos para realizar estos experimentos. Como suele decir @substack, NodeJS es ideal para estos experimentos de “mad science”.

Si en el directorio del ejemplo ejecutan:

node train ge lulu

Pueden obtener:

Lo que hace internamente es:

– Generar una población inicial de 1000 estrategias de trading aleatorias
– Ejecutar 100 generaciones (evaluaciones) de esas estrategias contra los datos de entrenamiento (en este caso dos compañías)
– En cada generación/pasada quedarse con los mejores y mutarlos, para alimentar a la próxima generación de traders (notablemente, no necesité cruzamiento, solo mutación, de nuevo, simplicidad, baby step, no usar algo si no se necesita todavía)

El resultado final muestra el mejor trader encontrado, su composición genética (a explicar en próximo post) y su evaluación. En este caso, partiendo de 2000 dólares iniciales (1000 por empresa), consiguió generar 2500 dólares. La longitud de estas series está en los 200 valores promedio. Si fueran días, hubiéramos obtenido un retorno de un 25% en menos de un año. No está mal para el primer experimento.

Una vez obtenido un resultado interesante (el de arriba fue mi primer primer experimento con datos no inventados), pasé a entregar traders con unas compañías y comparar sus resultados con los valores de otras.

Así, ejecutando:

node train tsla nflx — googl yhoo

se entrena con dos compañías (Tesla, Netflix) y se ejecuta el mejor trader obtenido con valores de otras dos compañías (Google, Yahoo):

 

En próximos posts: más detalle del cromosoma usado, algoritmo de mutación, y pruebas con más datos.

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

Aplicando Machine Learning a FinTech (1) Arboles de Decisión

Monday, December 21st, 2015

Siguiente Post

El año pasando, para la charla de JavaScript e Inteligencia Artificial de preparé para JSConf Argentina, había escrito una librería en JavaScript (para NodeJs y browser) que implementa Arboles de Decisión, basados en una descripción que encontré en el libro de Quinlan, “C 4.5 Programs for Machine Learning”.  Pueden encontrar una descripción del algoritmo en:

https://en.wikipedia.org/wiki/C4.5_algorithm

El ejemplo que había escrito usa un dataset de “Database for fitting contact lenses”, que encontré en:

http://archive.ics.uci.edu/ml/machine-learning-databases/lenses/

mencionado en el libro “Machine Learning in Action” de Peter Harrington (http://www.manning.com/pharrington/). Pueden ver el ejemplo browser en:

https://github.com/ajlopez/SimpleDT/tree/master/samples/lenses

Hoy publiqué una versión 0.0.2 de la librería SimpleDT:

https://github.com/ajlopez/SimpleDT

que permite decidir sobre atributos numéricos, no sólo por atributos de texto. Y lo apliqué para deducir un árbol de decisión de riesgo crediticio, tomando como dataset el publicado en:

https://archive.ics.uci.edu/ml/datasets/Statlog+(German+Credit+Data)

Pero veamos, ¿cómo eso de tomar un dataset como entrada y obtener un árbol de decisión? Primero, un dataset es una lista de ejemplos, cada uno con una cantidad de atributos. Por ejemplo, el dataset que usé para créditos, es un archivo de texto que comienza con:

A11 6 A34 A43 1169 A65 A75 4 A93 A101 4 A121 67 A143 A152 2 A173 1 A192 A201 1
A12 48 A32 A43 5951 A61 A73 2 A92 A101 2 A121 22 A143 A152 1 A173 1 A191 A201 2
A14 12 A34 A46 2096 A61 A74 2 A93 A101 3 A121 49 A143 A152 1 A172 2 A191 A201 1
A11 42 A32 A42 7882 A61 A74 2 A93 A103 4 A122 45 A143 A153 1 A173 2 A191 A201 1
A11 24 A33 A40 4870 A61 A73 3 A93 A101 4 A124 53 A143 A153 2 A173 2 A191 A201 2
A14 36 A32 A46 9055 A65 A73 2 A93 A101 4 A124 35 A143 A153 1 A172 2 A192 A201 1

Ver el archivo completo en:

https://github.com/ajlopez/SimpleDT/blob/master/samples/scoring/german/german.data.txt

La primera columna es un atributo cualitativo (no numérico) que indica la existencia de una cuenta de cheques, en marcos alemaneas, con valores posibles:

  • A11: … < 0 DM (importe negativo)
  • A12: 0 <= …. < 200 DM (importe entre 0 y 200 marcos)
  • A13: … > 200 DM (importe mayor o igual a 200 marcos)
  • A14: sin cuenta de cheques

Estos valores son ingresos mensuales en esa cuenta, de por lo menos un año.

La segunda columna, en cambio, es un atributo numérico que indica el plazo en meses del préstamo solicitado.

La tercera columna indica la historia de crédito, teniendo valores no numéricos:

  • A30: No tomó créditos, o todos sus créditos fueron pagados en término
  • A31: Todos los créditos en este banco fueron pagados
  • A32: Todos los créditos pagados pero todavía no fueron cancelados, faltan cuotas por vencer
  • A33: Tuvo atrasos en el pasado
  • A34: Cuenta en estado crítico

Y así. Pueden leer la descripción de las columnas en: https://github.com/ajlopez/SimpleDT/blob/master/samples/scoring/german/german.txt

O sea, cada renglón es un registro que describe una persona que pidió un crédito. La última columna toma dos valores posibles:

  • 1: la persona fue calificada como de buen crédito
  • 2: la persona tiene mal crédito

El algoritmo que apliqué permite analizar este dataset (son mil casos) y deducir un árbol de decisión para decidir si un caso cualquiera tiene buen o mal crédito, en base a la experiencia de este dataset.

Se ejecuta el programa (con NodeJS) con el comando:

node process

y obtendremos por pantalla el vuelco de un archivo JSON. El resultado de la última vez que lo ejecuté está en:

https://github.com/ajlopez/SimpleDT/blob/master/samples/scoring/german/tree.json

Veamos el comienzo de este resultado:

{
    "attribute": "0",
    "values": {
        "A11": {
            "attribute": "2",
            "values": {
                "A34": {
                    "attribute": "3",
                    "values": {
 ....

La línea:

    "attribute": "0",

Indica que el primer atributo a tomar en cuenta, por el que el árbol de decisión pregunta, es el 0 (corresponde al atributo 1 del documento original, usé base 0 como en JavaScript). Y las líneas:

    "values": {
        "A11": {
            "attribute": "2",
            "values": {
                "A34": {
....

Dicen “Si ese atributo tiene valor A11, seguir este otro árbol de decisión….” preguntando entonces por el atributo 2, y así.

Cuando un atributo que le interesa al algoritmo es numérico, ve cuál es la partición de valores que más información le da para seguir avanzando. Ejemplo:

"attribute": "1",
    "values": {
        "<= 11": {
            "value": 1
        },
        "> 11": {
            "attribute": "9",
            "values": {

Acá decide examinar el atributo 1, y si su valor es menor que 11, decide que la persona tiene buen crédito (resultado 1). Sino, sigue con otro árbol de decisión.

La forma de elegir por qué atributo preguntar y qué valores, la decide el algoritmo tomando siempre el próximo atributo que arroje más información (técnicamente, que disminuya la entropía).

Y el programa que lanza este proceso es muy simple:

var sdt = require('../../..');

var fs = require('fs');

var filetext = fs.readFileSync('german.data.txt').toString();

var lines = filetext.split('\n');

for (var k in lines)
    lines[k] = lines[k].trim();
    
var data = [];

for (var k in lines) {
    var values = lines[k].split(' ');
    for (var j in values) {
        var value = values[j];
        
        if (value[0] >= '0' && value[0] <= '9')
            values[j] = parseInt(value);
    }
    data.push(values);
}

var tree = sdt.tree(data, data[0].length - 1);

console.log(JSON.stringify(tree, null, 4));

Sólo es largo porque la librería todavía no reconoce por sí misma cuáles valores son numéricos y hay que alimentarla con los datos ya digeridos. Espero mejorar la salida, y hacer una implementación en el browser de este ejemplo, como había hecho para el caso de las lentes de contacto.

Imaginénse este tipo de algoritmo aplicado a datos recolectados en el tiempo dentro de un sitio P2P Lending como el que comenté ayer en este blog, MoneyPool. Como el algoritmo es genérico (no depende del dominio) también podría exponerse como una API. Una especie de Machine Learning usando Decision Trees, as a Service 😉

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

Sobre Machine Learning (1)

Tuesday, June 23rd, 2015

El año pasado toqué el tema de Inteligencia Artificial con JavaScript, y me gustaría ahora comenzar a comentar sobre un tema relacionado, que está digamos “de moda” por estos tiempos. Es el tema de Machine Learning, aprendizaje automático. También estoy preparando una charla, y parte de ese material que estoy investigando quiero volcarlo en esta serie de posts.

Es un tema que ya tiene décadas de desarrollo. Lo que veo al revisitarlo y enterarame de los últimos avances, es que ha cambiado su definición común. Veamos una definición. Leo en el curso de Coursera:

https://www.coursera.org/course/ml

Machine learning is the science of getting computers to act without being explicitly programmed. In the past decade, machine learning has given us self-driving cars, practical speech recognition, effective web search, and a vastly improved understanding of the human genome. Machine learning is so pervasive today that you probably use it dozens of times a day without knowing it. Many researchers also think it is the best way to make progress towards human-level AI. In this class, you will learn about the most effective machine learning techniques, and gain practice implementing them and getting them to work for yourself. More importantly, you’ll learn about not only the theoretical underpinnings of learning, but also gain the practical know-how needed to quickly and powerfully apply these techniques to new problems. Finally, you’ll learn about some of Silicon Valley’s best practices in innovation as it pertains to machine learning and AI.

Esa definición es la que yo tenía en mente desde el siglo pasado: hacer que las computadoras actuaran de alguna forma sin haber sido explícitamente programadas para ello, tal vez con el agregado de ir mejorando en un tiempo inicial en la tarea (que no sea simplemente conducta aleatoria).

Ahora bien, hay otras definiciones que involucran datos. Veamos la definición en el artículo actual de la Wikipedia:

http://en.wikipedia.org/wiki/Machine_learning

Machine learning is a subfield of computer science[1] that evolved from the study of pattern recognition and computational learning theory in artificial intelligence.[1] Machine learning explores the construction and study of algorithms that can learn from and make predictions on data.[2] Such algorithms operate by building a model from example inputs in order to make data-driven predictions or decisions,[3]:2 rather than following strictly static program instructions.

Si bien es la definición más en boga en estos tiempos (usar datos como base del aprendizaje) no es la única, al menos en la historia de las ciencias de la computación. Lo que pasa es que vivimos en una época donde aparece el Big Data, y el Machine Learning sobre eso, e incluso en tiempo real, ha motivado varias implementaciones, a partir de “startups” y otros emprendimientos.

Veremos en los próximos posts algunos ejemplos históricos de Machine Learning, que no involucraban datos, y luego sí, nos sumergiremos en el actual estado del arte, con datos, aprendizaje supervisado, no supervisado, distribuido y en tiempo real.

Mientras, algunos enlaces y otros posts relacionados en inglés:

https://ajlopez.wordpress.com/category/machine-learning/

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez