Guía para aprender métodos cuantitativos en economía (IV)

compiling

Fuente de la tira cómica: xkcd bajo una creative commons license 2.5.

Prosigo con esta cuarta entrada la serie que he escrito este semestre sobre cómo aprender acerca de métodos cuantitativos en economía (las entregas anteriores están aquí, aquí y aquí).

La tercera de estas entradas se centraba en los métodos numéricos como instrumento para solucionar y estimar modelos en economía. Los mismos, para ser ejecutados eficientemente, precisan en la práctica de un ordenador. El problema, claro, es que a los ordenadores hay que decirles lo que tienen que hacer y para eso necesitamos aprender a programar.

Aquí hay que distinguir entre tres habilidades diferentes. La primera es la familiaridad con el manejo de los ordenadores a un nivel profesional (¿qué editor emplear? ¿qué es un compilador?). La segunda es el conocimiento de lenguajes de programación (¿Matlab? ¿R?). La tercera es la implementación algorítmica de los métodos numéricos (¿qué y cómo programo?).

Antes de entrar en materia, es preciso aclarar tres consideraciones. La primera es que, a diferencia de las entradas anteriores, cuando se responde a estas preguntas existirá un nivel de subjetividad considerable. No hay, por ejemplo, un “mejor” editor. Cada editor es diferente. Unos tienen unas ventajas, otros tienen otras. La valoración de las fortalezas y debilidades de cada uno de los instrumentos que voy a discutir es algo que varía de persona a persona. Lo que a mí me puede parecer intuitivo a otro lector le puede parecer innecesariamente complejo. Como me contaba hace ya mucho tiempo un profesor en Minnesota, las grandes guerras de religión de los siglos XVI y XVII europeos poco fueron en comparación con las discusiones de los programadores en los 90 sobre las ventajas y desventajas de GNU Emacs y Vim. Además, para complicar aún más la situación, una herramienta de trabajo puede haberse quedado un tanto anticuada pero eso no necesariamente justifica el abandonarla si el coste de ajuste a la nueva herramienta es superior al beneficio de la renovación. Uno no tira su coche en un descampado cada vez que sale un nuevo modelo en el mercado. Voy a intentar ser lo más objetivo posible en mis valoraciones pero los lectores tienen que pensar en mis comentarios como indicaciones, no como “verdades”.

La segunda consideración es aclarar que los economistas sí que necesitamos herramientas computacionales relativamente avanzadas y que buena parte de las soluciones a los problemas numéricos que tratamos no vienen “enlatadas” en un paquete estadístico o similar. Si uno quiere hacer cosas en la frontera, casi seguro que se encontrará con la necesidad de programar el método uno mismo y, además, acariciar los limites en términos de lo que se puede y no se puede calcular con los ordenadores actuales tanto en velocidad como en memoria. Un simple ejemplo es la solución y estimación de modelos con agentes heterogéneos, que son problemas (ya incorporando el uso de aproximaciones) de una altísima dimensionalidad. E incluso si un investigador emplea paquetes o librerías existentes, es preciso ser un usuario inteligente de los mismos y por tanto tener un conocimiento en cierto detalle de su funcionamiento.

La tercera consideración es resaltar que mucho de este material sería adecuado aprenderlo pronto en la carrera educativa, a nivel de grado o bachillerato (en vez de perder el tiempo, como a veces ocurre, con enseñar a manejar un procesador de texto o una hoja de cálculo, que es algo que se puede solventar en una mañana). Programar, incluso cosas bastante avanzadas, se puede hacer con 18 años (o antes) sin problema alguno. Una asignatura o dos en el grado de economía de programación (incluyendo cosas como manejar otras herramientas relacionadas como LaTeX o Git) me parecería una idea excelente. Entre dar una asignatura tan insulsa como política económica y dar programación, no resta color alguno.

Hoy me centraré en los lenguajes de programación. En una entrada final (o al menos final por el momento, esta serie crece más lejos de mis intenciones originales; esta cuarta entrada ya es la más larga de la serie incluso discutiendo únicamente algunas de las ideas más básicas de lenguajes de programación para economistas), hablaré sobre otras herramientas complementarias como editores, compiladores, depuradores, Git, etc.

Lenguajes de Programación

Existen quizás miles de lenguajes de programación. Algunos lenguajes son de bajo nivel: se acercan mucho a la manera en la que el ordenador opera y por tanto son más complejos de emplear, pero alcanzan una eficiencia muy alta. Otros lenguajes son de alto nivel y se acercan más a cómo “hablamos” los seres humanos, normalmente a coste de una menor velocidad. Algunos lenguajes son de propósito general: permiten diseñar desde un sistema operativo a invertir una matriz. Otros son de dominio específico: están diseñados para objetivos determinados, como la computación numérica. Una referencia general (que discute estas clasificaciones y muchas otras) es Programming Language Pragmatics (4th Ed.) de Michael L. Scott.

programming

Entre los lenguajes de propósito general, un economista puede encontrarse con el venerable Fortran, actualmente en su versión Fortran 2008, y con C++, actualmente en su versión C++14. Otros lenguajes comunes en la industria (aquí un índice de uso de lenguajes), desde el más primitivo C hasta todas los “primos” de C++ (Swift, Java o C#) tienen, por unos motivos o por otros, menos implantación en la comunidad científica (excepto parcialmente C, subsumido en este campo en buena medida dentro de los usuarios de C++) y por tanto no los discutiré más.

Fortran 2008 es un lenguaje relativamente sencillo de aprender y muy compacto. En términos de velocidad pura sigue estando en la frontera (aunque C++14 ya le ha alcanzado en casi todos los problemas, una comparación que yo he escrito aquí; otras comparaciones aquí). Sin embargo, por su diseño original, resulta más complejo emplearlo para problemas de paralelización masiva que incluyan GPUs o para implementar paradigmas como orientación a objetos o programación funcional que resultan particularmente útiles, por ejemplo, en el manejo de estructuras complejas de datos, como las que a menudo tenemos en microeconometría.

C++14, en comparación, es un lenguaje que se puede hacer difícil de aprender por su tamaño y versatilidad (más que un lenguaje, es una “federación de lenguajes”) pero que permite las implementaciones más sofisticadas de estructuras de datos y de algoritmos que uno pueda imaginarse. Por ejemplo, C++14 posibilita el manejo muy general de funciones anónimas y la mayoría de las implementaciones de librerías para GPUs trabajan de manera más cómoda en C++.

Mi consejo a los estudiantes de mi clase en Penn que se atreven a aprender uno de estos lenguajes de propósito general es que, a menos que tengan que trabajar con “legacy code” o “legacy coders” en Fortran, aprender C++ es mejor camino, sobre todo si tal esfuerzo se realiza con un libro de texto pensado para gente con intereses numéricos, como este, y no para programadores en general.

C++

Familiarizarse con las ideas básicas de definición de variables, bucles, sentencias condicionales, etc. no es muy difícil y uno puede dejar para más tarde la orientación a objetos y las funciones anónimas. Aunque este esquema de aprendizaje probablemente no sea el mejor para un ingeniero informático, sin embargo, sí que creo que se ajusta bien a las necesidades de muchos economistas.

Effective

Más avanzado a mi me gusta mucho Effective Modern C++: 42 Specific Ways to Improve Your Use of C++11 and C++14 de Scott Meyers, un respetado miembro de la comunidad de C++, por sus explicaciones de técnicas modernas.

C++

Existe también el tratamiento clásico por el creador del lenguaje, The C++ Programming Language (4th Ed.) de Bjarne Stroustrup, con muchas perlas de inteligencia sintáctica, pero yo lo he empleado menos.

Programar en Fortran o en C++ requiere, además, emplear un editor o un entorno de desarrollo integrado, manejar un compilador, un depurador y alguna herramienta de análisis de rendimiento. Hablaré de estos temas en la entrada siguiente para no alargar en exceso esta sección.

Aprender, en todo caso, un lenguaje de propósito general (y, además, compilado) puede ser una dura tarea para muchos que no compense en términos de velocidad o facilidad de manejo. Aprender, por ello, un lenguaje de propósito limitado y que permita tanto interpretación, como compilación y just-in-time (JIT) es una mejor opción para la mayoría de los estudiantes, al menos como primera línea de avance.

Julia

Julia

Durante dos décadas largas, Matlab ha sido el lenguaje de programación más popular en economía. Yo he me pasado más horas con Matlab de las que me gustaría recordar y, dada la enorme cantidad de “legacy code” en mi ordenador, lo más probable es que lo siga haciendo por mucho tiempo. Pero hoy recomiendo a mis estudiantes aprender Julia.

Las razones son sencillas. Primero, Julia tiene una clara ventaja en términos de velocidad gracias a su compilador JIT (más algunos detalles de su diseño). Aunque Matlab también intenta, en sus últimas versiones incorporar esta compilación, la estructura más antigua del lenguaje (y, sospecho, razones internas del código base) complican el obtener las mismas ventajas que consigue Julia.

Segundo, Julia ofrece una rica variedad de estructuras y enfoques producto de su moderno diseño, con un énfasis en el envío múltiple y la programación masiva en paralelo. Matlab se queda muy atrás en muchas de estas categorías. En particular, su toolbox de programación en paralelo promete mucho pero decepciona en la práctica y es casi imposible escribir metaprogramación de calidad con él.

Tercero, Julia es código abierto. Más lejos de la ventaja monetaria (Matlab puede ser embarazosamente caro fuera de las universidades y su clon gratuito, Octave, es muy malo, particularmente en términos de velocidad), el ser código abierto permite crear un ecosistema de usuarios que enriquecerá el lenguaje en el medio plazo y facilita la multiprogramación. “Conectar” Julia con C++ o Python es tremendamente sencillo.

Finalmente, para aquellos que vienen de Matlab, la sintaxis de Julia les resultará muy familiar, pues los programadores del proyecto han intentado copiarla siempre que la misma tuviese sentido y no creara conflictos con los nuevos objetivos del lenguaje. De esta manera los costes de transición de Matlab a Julia puede que sean mucho más bajos que en otros casos de cambio de lenguaje de programación.

El mejor lugar para aprender Julia es la página web del lenguaje, que incluye referencias a libros y videos, y en esta página de Quantitative Economics. Entre los videos existentes existen muchos gratuitos y el lector debería probar varios a ver cuál le gusta más. Entre los de pago, a mi me ha gustado este.

Julia

La desventaja de Julia es que el lenguaje está todavía en evolución y que no existen todos los paquetes o “legacy code” que uno puede fácilmente encontrar en Matlab (aunque ya existen más de 1400 paquetes en Julia).

Una excelente implementación en términos de comodidad de uso es Julia Pro.

R

rstudiosticker

Una alternativa/complemento a Julia para los que trabajan en estadística y econometría es R, un lenguaje que he mencionado mucho en este blog.

Mi recomendación a los estudiantes de doctorado, y el criterio que recomendaría a los departamentos intentando decidir sobre este tema, es que el primer año es un buen momento para aprender tanto Julia como R.

¿Por qué es bueno el bilingüismo (informático)? Primero, porque permite apreciar mejor lo que es esencial de la programación y lo que es meramente accidental. La clave, por ejemplo, es entender qué es una sentencia condicional, no aprender la sintaxis concreta de la misma, que siempre se puede mirar en un libro o memorizar por mera repetición. El tener que mirar cómo se escribe un condicional en dos lenguajes diferentes enseña la idea central de la estructura lógica.

Segundo, porque el aprender varios lenguajes sirve para acostumbrar a los estudiantes que diferentes problemas requieren a menudo diferentes herramientas y que, a lo largo de una vida profesional, es muy probable que tales herramientas cambien y que uno tenga que “reciclarse” y actualizar sus conocimientos varias veces.

eco

R es un lenguaje con una sintaxis algunas veces un poco contra-intuitiva, pero que permite la solución eficiente de muchos problemas en estadística y econometría. Más importante, quizás, es el enorme ecosistema que se ha desarrollado alrededor del mismo. La pieza central del mismo es RStudio, un entorno de desarrollo integrado excelente. Como complementos existen miles de paquetes que permiten la implementación de centenares de procedimientos estadísticos, el control de código, reproductivilidad o la creación de gráficos preciosos.

Uno de estos paquetes es fantástico: Rcpp. Este paquete permite la integración de código en C++ en R de manera simple y transparente (mucho más fácil, por ejemplo, que los archivos Mex en Matlab, que siempre son más penosos de implementar de lo que uno piensa al principio). De esa manera uno puede escribir la mayor parte de su código en R y dejar solo en C++ las tareas más intensivas.

R_02_2016-05-01

Reflejo de esta vibrante comunidad de usuarios es R-bloggers, un agregador de blogs sobre R, que es una de mis primeras visitas en internet cada mañana por la riqueza y variedad de sus contenidos. Sólo con lee R-bloggers de manera regular uno aprende decenas de cosas y se mantiene al día en muchas áreas (el equivalente en Julia, juliabloggers, es mucho menos activo).

Por el lado negativo, R puede ser desesperadamente lento en algunos casos, aunque la incorporación de un JIT en las nuevas versiones, la posibilidad de compilar el código y la facilidad de uso de Rcpp mitigan en gran medida esta desventaja.

Art

Existen muchos libros para aprender R. A mi me gusta mucho The Art of R Programming: A Tour of Statistical Software Design, de Norman Matloff.

advanced

Más avanzado pero escrito por uno de los líderes mundiales de R, Hadley Wickham, es Advanced R. R tiene, por ejemplo, grandes capacidades de abstracción funcional y de orientación a objetos que muchos usuarios no aprovechan correctamente. Wickham explica estas ideas de manera clara y concisa. Del mismo autor (en colaboración con Garrett Grolemund) tenemos R for Data Science: Import, Tidy, Transform, Visualize, and Model Data, que cubre todos los aspectos de manipulación y uso de datos.

tidy

Con respecto a los paquetes como Rcpp o ggplot2 es quizás mejor mirar la documentación directamente: los mismos cambian continuamente y los libros específicos sobre los mismos se quedan a veces anticuados rápidamente.

R es, finalmente, una alternativa muy superior a Stata. No solo R es código abierto (con el considerable ahorro de recursos y la posibilidad de inspeccionar los algoritmos por parte de la comunidad científica) sino que es un lenguaje mucho más poderoso y general. Stata puede parecer atractivo en el corto plazo por su cierta facilidad de acceso pero en el largo plazo limita el salto de los estudiantes a un nivel de programación más avanzado. Consideraciones similares (más las reducidas comunidades de usuarios) eliminan a Gauss, RATs, etc.

Python

Python

Antes he mencionado de pasada Python. Sin embargo, no he recomendado su aprendizaje. No es ello una crítica al lenguaje. Python es un lenguaje intuitivo, elegante, de código abierto y tremendamente útil en muchas aplicaciones (sin ir más lejos, es el lenguaje favorito para interactuar con muchas implementaciones de aprendizaje automático, como TensorFlow). Por ejemplo, es un lenguaje excelente para introducir a los chavales a la programación y siempre se lo recomiendo a mis amigos que me preguntan qué lenguaje deberían aprender sus hijos. Simplemente, por su velocidad (y otro par de detalles que no merece la pena explicar más explicitamente), no es el lenguaje más adecuado para la computación numérica intensiva.

Ibiza

Es verdad que existen herramientas para acelerarlo: pypy o Numba son las que me vienen a la cabeza como más eficientes. Pero emplear estas técnicas en mi experiencia, es como “maquear un Seat Ibiza para rallies”: hace mucho ruido, va más deprisa, pero sigue sin ser un Mercedes. Teniendo Julia (y siendo Julia capaz de emplear cualquier módulo de Python que sea necesario para una aplicación concreta), no creo que sea la manera más adecuada de proceder. En todo caso, si uno quiere aprender Python, un libro ya casi clásico es Think Python: How to Think Like a Computer Scientist (2nd Ed.), de Allen B. Downey.

Python

Y si lo que quiere es optimizar su rendimiento para obtener todo el jugo, una referencia completa es High Performance Python: Practical Performant Programming for Humans de Micha Gorelick y Ian Ozsvald.

Python

Finalmente, para aprender sobre los paquetes como Numpy o Scipy que han ayudado mucho a la popularización de Python, una referencia completa es Numerical Python: A Practical Techniques Approach for Industry de Robert Johansson (cuya página web tiene muchos recursos adicionales).

numpy

Otros Lenguajes

Me gustaría completar esta entrada con una pincelada rápida sobre otros lenguajes. En un proyecto en el que estoy trabajando estos días estamos programando todo en Scala y Spark. Scala es un lenguaje relativamente reciente diseñado para integrar orientación a objetos y programación funcional de una manera más elegante y natural que otras alternativas (como decía anteriormente C++14 permite muchas de estas implementaciones pero más como una “federación” y Haskell o Clojure son excesivamente puros en su enfoque funcional para la mayoría de los usuarios en economía). Además, al correr en la JVM, puede ser muy útil en la industria privada (como explicaba más arriba esto no es, sin embargo, una ventaja clara para computación numérica).

Scala

Yo aprendí Scala con las clases en Coursera. Existe una secuencia de 5 cursos construida alrededor del creador del lenguaje, Martin Odersky. Para los que prefieran un libro, Scala for the Impatient (2nd ed.) de Cay S. Horstmann es un buen punto de partida.

Spark es un entorno de programación distribuida de nueva generación para el tratamiento de grandes masas de datos. Spark está concebido como un sustituto de Hadoop MapReduce. Spark es muy fácil de usar, con un interfaz de programación de alto nivel y es suficientemente flexible para incorporar diferentes tareas (desde un problema de aprendizaje automático a interactuar con SQL). Spark, además, esta diseñado con un objetivo claro de maximizar velocidad (algo tremendamente importante en economía, ya que la estimación de modelos fuerza a la iteración sobre el espacio de parámetros). Spark puede correr computaciones tanto en memoria o en el disco y, en estas últimas, hacerlo de manera mucho más eficiente que MapReduce.

La abstracción central de Spark es el concepto de RDD (resilient distributed dataset), una colección distribuida inmutable de objetos. Todas las tareas en Spark se estructuran alrededor de crear nuevas RDDS, manipular RDDs ya existentes o aplicar operadores en las mismas.

En mi trabajo actual estamos aproximando y estimando funciones de valor de alta dimensionalidad por medio de árboles de regresión y nos encontramos con la necesidad de almacenar grandes matrices de manera eficiente y enviarlas de manera distribuida a varios procesadores. Nuestra experiencia es que Scala y Spark nos han permitido implementar el algoritmo de una manera más rápida y eficiente que las alternativas que teníamos anteriormente. Este curso (que pertenece a la secuencia mencionado anteriormente de Scala) clarifica muchas de estas ideas (aunque lo que nosotros hacemos es un poco diferente).

spark

El libro que yo he empleado es Learning Spark: Lightning-Fast Big Data Analysis de Holden Karau, Andy Konwinski, Patrick Wendell y Matei Zaharia (el principal programador del proyecto que creó Spark).

El último lenguaje que voy a discutir es Mathematica. Mi relación con Mathematica ha sido siempre de amor-odio. Por un lado, es un lenguaje sorprendentemente poderoso y una vez que uno entiende su estructura se pueden hacer cosas maravillosas con él. En varios de mis artículos con Juan Rubio hemos empleado Mathematica de manera extensiva para hacer cosas que de otra manera no hubiéramos sabido resolver. Como tal, siempre tendré un grato recuerdo del lenguaje.

Por otra parte, hay muchas cosas del entorno de Mathematica que son absolutamente insoportables. Primero, el autobombo de su creador, Stephen Wolfram y de la página web de la empresa es bastante cargante (relacionado con ello y ahora menos importante que hace unos años: la empresa quería exprimirte hasta el último dólar, lo que en el largo plazo creo que perjudicó mucho la difusión del lenguaje). Segundo, y más importante, es un lenguaje lleno de peculiaridades, con mensajes de error misteriosos y que requiere saber decir las cosas en “Mathematica” sin acento de otros lenguajes. Siempre me he quedado con las ganas de aprender Mathematica de manera más profunda pero, a la vez, siempre me entra la pereza a la hora de la verdad por los motivos anteriores. En todo caso, el mejor libro es Programming with Mathematica: An Introduction de Paul Wellin

mathematica

Concluyo aquí esta entrada. En la siguiente (y espero final) entrada de esta serie en unas semanas completaré la discusión de herramientas computacionales que se nos quedado encima de la mesa.

Loading...