Review: Google Machine Learning Crash Course

Desde el comienzo Google fue un pionero en el uso de metodologías de machine learning para recopilar, ordenar y extraer sentido de las grandes cantidades de datos que generan. Trabajar para Google es una de las posiciones más buscadas en el mundo. Como una de las empresas más poderosas del globo, se dan el gusto de emplear lo mejor de lo mejor en todos los campos. Por ejemplo, cuando decidieron implementar el uso de Python como tercer lenguaje de programación (solo usaban C y Java hasta entonces) contrataron a Guido Van Rossum, ¡el dictador benévolo de por vida y creador de Python! Obviamente, tienen algunos de los mejores cerebros del mundo trabajando en cualquier cosa que tenga que ver con data.

Ahora bien, no todo el mundo en Google es un Data Scientist, y muchas veces un ingeniero querrá utilizar en su programa un poco de machine learning, no mucho, y seguir adelante con otros temas. Para tal fin Google tiene un programa llamada el Google Machine Learning Crash Course, un curso rápido para aprender aprendizaje automatizado, lo necesario para implementarlo sin destinar años de estudios.

En este blog, analizamos qué tan efectivo es el programa.

Los Temas de Hoy

Los temas de hoy son cinco:

  1. ¿Qué es exactamente el Google Machine Learning Crash Course?
  2. ¿Cómo funciona y cuantas materias son?
  3. ¿Quiénes son los profesores?
  4. ¿Cuánto cuesta? Y finalmente,
  5. ¿Vale la pena?

Qué es el Google Machine Learning Crash Course

El Google Machine Learning Crash Course es un curso rápido para aprender aprendizaje automatizado de acuerdo con el estilo de Google. Esto es muy importante, ya que no es un curso de ciencia de datos, ni de estadística. Tampoco está diseñado para mi o para ti, sino para los ingenieros de Google que están acostumbrados al lenguaje de Google y la manera de trabajar de Google. En inglés, crash course es un curso rápido y de emergencia, algo para transformar a un novato en un operador de una disciplina en el menor tiempo posible. La idea principal del curso es tomar ingenieros que saben mucho de programación, y que quieren implementar un poco de código de aprendizaje automatizado en sus programas, por ejemplo, para un sistema de recomendación o un algoritmo de clasificación. Esto pesa mucho en los materiales finales, ya que nunca se alejan mucho del propósito en mente.

Cómo Funciona y Cuántas Materias Son

No puedo hablar de materias, pero si puedo hablar de temas. Todo el curso convive en un sitio web manejado por Google, donde ahora se agregaron otros cursos adicionales y complementarios de Preparación de Datos, Clustering, Problem Framing, etc. Cada tema incluye una sección de videos producidos por el staff de Google explicando la teoría, y amplias páginas de teoría adicional para los que quieren tomar notas.

“Siendo el nerd que soy, comencé el curso manteniendo notas prolijas. Al comienzo pensé que estaba arruinando un cuaderno nuevo, pero ahora me doy cuenta de que quizás no me alcance para cuando haya terminado los cursos adicionales.”

Nota del Editor

El curso comienza con los prerrequisitos de como plantear un problema de aprendizaje automatizado, que debe ser un reto para los ingenieros que salta de AGILE y SCRUM al método científico. Luego comienza desde el punto focal de todo lo que hace Google: Gradient Descent.

Hagamos un alto. El descenso de gradiente es una técnica sofisticada de minimizar una función con una o más dimensiones, ajustando los pesos de sus clasificadores que por lo general se encuentran en forma de tensores. Cuando el problema tiene más de dos dimensiones, la función puede tener más de un punto bajo que haga difícil que gradient descent ubique el mínimo. Google se apoya mucho en su librería de TensorFlow para desdoblar los hiperplanos hasta llegar a un punto donde la función se mantiene y un problema que no parece lineal se resuelve con un discriminante lineal.

A partir de aquí, la teoría avanza explicando como aplicar tensores a la resolución de problemas lineales, que es una función de pérdida, como aplicar generalización, y el uso de juegos de datos de entrenamiento, validación y test.

“Tengo que confesar que, en esto, Google tiene la explicación más sencilla de CROSS VALIDATION. Quizás porque es practica sin tanta teoría.”

Nota del Editor

Para explicar resolución de problemas sin solución lineal aparente, el curso introduce el concepto de FEATURE CROSSES. Luego sale de los problemas de resolución lineal a otros más avanzados y toca la teoría y práctica de regresión logística, clasificadores, redes neuronales, y embeddings.

No hay muchos exámenes o pruebas, pero con cada tema mayor se incluye un ejercicio completo de entrenamiento de datos y creación de un modelo final en Python. Para tal fin Google usa el sistema de Google Colaboration, que por lo que entiendo es la implementación de Google de Jupyter Notebooks pero con 1,000 veces más velocidad. Todos los problemas se resuelven usando TensorFlow, redes neuronales, y tensores.

De hecho, otro tipo de ejercicio permite resolver problemas de redes neuronales de forma visual, tratando de crear clasificadores que minimicen una función de pérdida. Al manipular todos los hiper parámetros, incluyendo el número de capas y cuantas neuronas por capa, se entiende bien el concepto de redes neuronales y qué es cada cosa (y porqué se aplica…)

Los Profesores

Todos los videos los explican varios de los ingenieros de Google que se turnan con los temas. Sin ser profesores profesionales, se notan que todos son genios, que todos explican los temas muy bien, pero que a la vez ninguno entra profundo en las lecturas. Ningún video se pasa de diez minutos.

Una mención especial va para Peter Norvic, que en el 2001 se unió a Google como Director de Machine Learning, ¡antes que nadie hablara de machine learning!

El Costo del Programa

La buena noticia, el curso es totalmente gratis. Para la cantidad de cosas que se aprende y la teoría detrás, es imposible no decir que es espectacular.

Finalmente, ¿Vale la Pena?

Un curso de Google de Machine Learning gratis lleno de contenidos y me preguntan si vale la pena? ¡Por supuesto que vale la pena! En mi caso especial, es increíble la cantidad de temas que no me habían quedado claros en otros cursos que se explicaban en tres minutos en este curso. Cosas como cross validation, gradient descent, la importancia de la función de pérdida, y la ingeniería de los cruces de aprendices (feature cross en inglés). Solo por eso vale la pena.

Habiendo dicho esto, hay algunos puntos que debo aclarar.

  1. No es un curso de machine learning, es un curso de TensorFlow: todos los problemas, ya sea de regresión, clasificación, recomendación, todos se resuelven con redes neuronales en TensorFlow. Esto no es malo, ya que aprender TensorFlow y redes neuronales es muy valioso. Sin embargo, no es un curso para empezar o tomarlo solo. Me parece mejor comenzar con regresión lineal, regresión multivariable, y después ver los temas comunes como arboles de decisión y clasificación, K-Means, Random Forest, series de tiempo, etc.
  2. No es un curso de TensorFlow, es un curso rápido de machine learning: no me contradigo. Aprender TensorFlow lleva tiempo, el manual en línea es gigante, totalmente gigante. Y por muchos ejemplos que se incluyan en los apuntes de Colab, lo que se enseña es la punta del iceberg, lo mínimo necesario para que un programa funcione. Aprender TensorFlow bien involucra horas largas de leer, estudiar y programar.
  3. No es un curso de programación: Hay que saber Python, y no cualquier Python sino el Python 3.0 con todas las librerías modernas que le gusta a Google. Si, lo admito, yo uso la versión 2.7 todavía. Pero si alguien llega hasta aquí y no sabe Python, no se si vale la pena seguir hasta que no se tenga un buen control del lenguaje.
  4. Las librerías de TensorFlow están desactualizadas: los ejemplos en Colab se aseguran de importar la versión correcta de TensorFlow para que el código funcione. Pero las librerías nuevas de TensorFlow ya cambiaron, y lo que debió ser un ajuste mínimo en las llamadas a las funciones para probar los programas localmente se convirtió en una pelea con bibliotecas depreciadas y poco apoyo para hacer los cambios. Uno debe tener mucha paciencia con los ejemplos y hacerlos en Colab, o tomarse el tiempo para reescribir todo de nuevo y que funcione…

Consideraciones Finales

Cuando busqué otros videos de YouTube sobre el curso, me sorprendió que todos lo describen como algo rápido, para terminar en una hora o menos. No se si seré yo, pero a mí me tomó cuatro semanas y cerca de cuarenta páginas de apuntes (y sin mentir, cerca de 72 horas de estudio). Esto sin contar los cursos complementarios y la necesidad de buscar temas adicionales. Por ejemplo, TensorFlow parece al principio un simple proceso de tensores, matrices que ajustan pesos de una ecuación para minimizar la función de pérdida. Pero no fue hasta que por buscar de más encontré una explicación de Deep Neural Networks donde habla de como se desdoblan los hiperplanos hasta encontrar una transformación donde la función es continua y se puede resolver con gradient descent ya que es derivable. Aquí entra el concepto de homomorfismos y como las funciones con propiedades biyectivas continúan siendo continuas y derivables en otros planos. La matemática se pone complicada ya en este punto, salimos de la estadística que es mi zona de confort para entrar en el cálculo. Pero es cuando a uno el cerebro le hace clic y entiende que TensorFlow es más, que la parte del Flow es la increíble transformación visual de los planos donde funciones que en dos dimensiones parecen nudos o manifolds tiene continuidad y no se tocan en múltiples dimensiones o hiperplanos.

Yo recomiendo altamente este curso, pero no lo hagan de primera instancia, sino que atáquenlo cuando tengan una buena base de que significa el entrenamiento de datos, y como se hace en instancias más sencillas para ir incrementando el nivel de especialización.

Musings on Stacked Machine Learning Models

I recently worked with 3 machine learning models for FOREX prediction. One was ARIMA, the next multivariable linear regression, and the last one a stacked model that used the outputs of the first two as learners for input.

Here are the results from each:

While the regression model has an R2 value of 0.9714, the ARIMA beat it with a far better R2 value of 0.9976. That did not strike me odd, as in econometric time series analysis usually proves far more precise. But the stacked model only fared slightly better with an R2 value of 0.9978. I was expecting a little more precision out of the stacked model as it should have preprocessed and worked out the wrinkles and inefficiencies of the first two.

The topic of study is the TRM, Colombia’s official exchange rate for the US dollar. Economists and financiers have been trying to predict FOREX values since ever (or at least a very long time…) I was not looking for a break-through formula, but just something that would improve our company’s cost accounting accuracy and our ability to hedge currency volatility through forwards.

But I digress. The musing here is the additional overhead of the stacked model vs. a simple ARIMA forecast (using the excellent library by Robert Hyndmann here.) The accuracy is welcomed because when dealing with money every bit of a penny counts. But the production model is complicated at least. In my company, there is no such thing as a machine learning production model. Our IT staff is A+, but not very math-savvy. Any machine learning code is done by me, with little hope of moving it to production (and in my company it makes sense, we are small.) If a bigger enterprise how much more precision is worth the cost of additional computing cycles? The application of machine learning to ARIMA is not necessarily complicated. But having to run multiple models to ensemble does require additional computing power.

In a practical world, the difference between models is only 0.002. If the TRM is at 3,450 pesos to a dollar, the difference is 0.69 cents per dollar or 690,000 pesos in a one-million-dollar contract. That is the equivalent of 200 US dollars in one-million, which is money none the less but not a lot.

There is no right or wrong here. Since I cannot deploy my fancy algorithms to production I have not an easy way of estimating costs. But the musing is still interesting, and the simplicity of the model formulation has an incredible amount of complexity when brought to life.

Short Notes on Boosting

Introduction

The following notes are from the COURSERA Practical Machine Learning course and are intended to help others understand the concepts and code behind the math. The basic idea behind boosting is to take lots of possibly weak predictors, then weigh them and add them up, thus getting a stronger one. We could see two clear steps:

  1. Start with a set of classifiers (h1, h2, …, hn). For example, these could be all possible trees, all possible regressions, etc.
  2. Create a classifier that combines classification functions

Several things we want to obtain with this process:

  • The goal is to minimize error (on the training set)
  • Iteratively, select one h at each step
  • Calculate weights based on errors
  • Up weight missed classifications and select next h

The most famous boosting algorithm is ADAboost.

Boosting in R

Boosting in R can be used with any subset of classifiers. One large subclass of boosting is gradient boosting. R has multiple libraries for boosting. The differences include the choice of basic classification function and combination rules.

  • gbm: boosting with trees
  • mboost: model based boosting
  • ada: statistical boosting based on additive logistic regression
  • gamBoost: for boosting generalized additive models

Most of these are already included in the caret package, making the implementation relatively easy.

Boosting Example

For our boosting example, we will use the ISLR package and the Wage data set included. The idea here is to try to predict wage based on the many other predictors included.

# Create training and testing sets 
wage <- subset(Wage, select = -c(logwage)) 
inTrain <- createDataPartition(y = wage$wage, p = 0.7, list = FALSE) 
training <- wage[inTrain, ] 
testing <- wage[-inTrain, ] 

Now that we have our data we can create training and testing sets. For the problem at hand, there is no pre-processing of the data necessary, but for other types of prediction models, such as regression, some pre-processing is required for non-numerical values or variables with no variability because of the predominance of zero values.

# Create training and testing sets 
wage <- subset(Wage, select = -c(logwage)) 
inTrain <- createDataPartition(y = wage$wage, p = 0.7, list = FALSE) 
training <- wage[inTrain, ]  
testing <- wage[-inTrain, ]

Fitting a boosting model in R using the caret package is very easy. The syntax is much like any other for training a data set, just include the option method = “gbm” in the option line.

# Fit a model using boosting
modFit <- train(wage ~ ., method = "gbm", data = training, verbose = FALSE)
print(modFit)
## Stochastic Gradient Boosting 
## 
## 2102 samples
##   10 predictor
## 
## No pre-processing
## Resampling: Bootstrapped (25 reps) 
## Summary of sample sizes: 2102, 2102, 2102, 2102, 2102, 2102, ... 
## Resampling results across tuning parameters:
## 
##   interaction.depth  n.trees  RMSE      Rsquared 
##   1                   50      34.39326  0.3213741
##   1                  100      33.85476  0.3322011
##   1                  150      33.79401  0.3341418
##   2                   50      33.85892  0.3324366
##   2                  100      33.77240  0.3351736
##   2                  150      33.87053  0.3330873
##   3                   50      33.73768  0.3365461
##   3                  100      33.89518  0.3324402
##   3                  150      34.09446  0.3263083
## 
## Tuning parameter 'shrinkage' was held constant at a value of 0.1
## 
## Tuning parameter 'n.minobsinnode' was held constant at a value of 10
## RMSE was used to select the optimal model using  the smallest value.
## The final values used for the model were n.trees = 50, interaction.depth
##  = 3, shrinkage = 0.1 and n.minobsinnode = 10.

Word of caution, boosting takes a little more of processing time in some computers, so you might have to wait a few seconds for the function to return the model object. If you run this code yourself you will see multiple warning messages related to the non-processing of the data previous to the exercise (not necessary for this simple example.) If you look closely, you will see that the function chose a Stochastic Gradient Boosting model, 2102 samples and 10 predictors. Mind you, there is a difference between observations in the training set and the final boosting model since it has resampled from our training set with bootstrap (25 reps.) The output says the summary of sample sizes is 2102, so we will keep that in mind when we try to cross-validate and test the model.

Testing the Model

Remember boosting resampled the training data set, so now it has fewer observations than in the original. Thus it is hard to cross-validate with the same data (length of vectors are not the same!) What we will do now is use the testing data to plot real wage data from the test set against the wage prediction from our model using the test data. These are numerical outcomes, a little harder to see on a confusion matrix but more visible in a plot.

qplot(y = predict(modFit, testing), x = wage, data = testing, ylab = "Prediction of Wage", xlab = "Wage")

If you look at the plot, our model seems to capture quite well those lower-bound wages, but there is a group of higher-wages that seem to fall out of our prediction capacity. We can see a quick rundown of our wage prediction ranges and real wages using the cut function.

predWage <- cut(predict(modFit, testing), 5)
realWage <- cut(testing$wage, 5)

summary(predWage)
## (67.3,88.9]  (88.9,110]   (110,132]   (132,153]   (153,175] 
##         143         372         220         103          60
summary(realWage)
## (20.7,76.6]  (76.6,132]   (132,188]   (188,244]   (244,300] 
##         128         564         164          12          30

While the real wages vary from 19.8 to 319.0, our prediction only ranges from 61.1 to 169.0. This is concentrated in the second and third subsets of real wages.

Conclusion

Despite having some problem with higher salaries, we clearly saw from the plot a good amount of prediction power between real wages and estimations. What is clear is the power of boosting taking rather weak predictors and incrementing their capacity through resampling for much more accurate prediction power.