Antes de entrenar un modelo, aprendamos sobre el funcionamiento y la API de scikit-learn

In [3]:
import numpy as np 
import pandas as pd
Scikit-learn es la librería más usada de Machine Learning tradicional [Ver ranking de Github](https://github.com/showcases/machine-learning). La librería incluye funcionalidades de:
  • Preprocesamiento de datos en sklearn.preprocessing
  • Algoritmos de Machine Learning en sklearn.linear_model, sklearn.svm, sklearn.ensemble, y muchos más.
  • Evaluación de modelos en sklearn.model_selection y sklearn.metrics
Scikit-learn sigue muy de cerca los resultados de la investigación e implementa los resultados más maduros y probados en sus modulos. La [documentación](http://scikit-learn.org/stable/modules/ensemble.html#forests-of-randomized-trees) extensa muestra como la librería es un compendio de conocimiento en Machine Learning llevado a software
Una estructura de datos esencial en scikit-learn es el Estimator

Para poder escoger el estimator apropiado una excelente guia es el cheatsheet siguiente, hecho por uno de los core-dev de scikit-learn.

Implementemos un modelo simple de regresión primero

In [4]:
X = pd.read_csv('../vol/intermediate_results/X.csv')
In [5]:
y = X['worldwide_gross']
In [6]:
X = X.drop('worldwide_gross',axis=1)
In [9]:
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.4,random_state=1)
In [10]:
print(len(X))
print(len(X_train))
print(len(X_test))
4104
2462
1642
In [11]:
X.head(1)
Out[11]:
production_budget title_year aspect_ratio duration.1 cast_total_facebook_likes budget imdb_score
0 425000000.0 2009.0 1.78 178.0 4834.0 237000000.0 7.9
In [12]:
from sklearn.linear_model import Lasso

model = Lasso()
In [13]:
model.fit(X_train,y_train)
/opt/conda/lib/python3.5/site-packages/sklearn/linear_model/coordinate_descent.py:491: ConvergenceWarning: Objective did not converge. You might want to increase the number of iterations. Fitting data with very small alpha may cause precision problems.
  ConvergenceWarning)
Out[13]:
Lasso(alpha=1.0, copy_X=True, fit_intercept=True, max_iter=1000,
   normalize=False, positive=False, precompute=False, random_state=None,
   selection='cyclic', tol=0.0001, warm_start=False)
In [13]:
predicted = model.predict(X_test)
In [15]:
predicted.shape
Out[15]:
(1642,)
In [19]:
import matplotlib.pyplot as plt
%matplotlib inline

plt.hist([predicted,y_test]);

Evaluemos de forma más fina el comportamiento de nuestro modelo

Los estimadores y las funciones de sklearn vienen con el máximo de argumentos con valores por defecto que suelen ser las mejores opciones si no tenemos algun conocimiento particular el problema. En este caso particular la función estimator.score ya viene con una de las métricas de sklearn.metrics, que es la métrica sklearn.metric.r2_score
El score R2 de una regresión es una de las formas más comunes de entender su poder predictivo. Este mientras más cerca de 1 este, mejor es
Los valores que puede tomar son de -infinito hasta 1. Un score R2 negativo es malo, ya que esto indica que la regresión es peor que si simplemente eligieramos un valor fijo como predicción para todos los puntos, la media.
In [14]:
model.score(X_test,y_test)
Out[14]:
0.6021797062956975

Bastante bien para un primer modelo!

Un buen score R2 es importante para una regresión. Pero no lo es todo. De forma general los scores hay que complementarlos con visualizaciones de los datos ya que una métrica no logra siempre encodear todas las caracteristicas de una distribución de probabilidades. Un ejemplo es el siguiente:

Siempre visualiza tus resultados, aunque tengas un buen score de performance.
In [22]:
residuals = y_test - predicted
In [23]:
plt.scatter(y_test,residuals)
Out[23]:
<matplotlib.collections.PathCollection at 0x7f3f6930fd30>
In [24]:
ap_residuals = np.abs(residuals) / y_test
In [25]:
plt.scatter(y_test,ap_residuals)
Out[25]:
<matplotlib.collections.PathCollection at 0x7f3f6927b048>
In [26]:
lap_residuals = np.log(ap_residuals)
In [28]:
plt.scatter(y_test,lap_residuals)
Out[28]:
<matplotlib.collections.PathCollection at 0x7f3f691be1d0>
In [30]:
plt.hist(lap_residuals,bins=100, normed=1, histtype='step', cumulative=True);
In [32]:
plt.hist(lap_residuals, bins=100, normed=1, histtype='step',cumulative=True);
plt.axis([-2,0,0,1])
np.power(np.exp(1)*np.ones(5),np.linspace(-2,0,5))
Out[32]:
array([ 0.13533528,  0.22313016,  0.36787944,  0.60653066,  1.        ])
In [44]:
plt.scatter(np.arange(8),model.coef_)
Out[44]:
<matplotlib.collections.PathCollection at 0x7f3f68fb8b00>
In [79]:
X = pd.read_csv('../vol/intermediate_results/X.csv')
In [78]:
X = X.drop('gross',axis=1)
In [80]:
X = X.drop('worldwide_gross',axis=1)
In [81]:
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.4)
In [82]:
model = Lasso()
model.fit(X_train,y_train)
Out[82]:
Lasso(alpha=1.0, copy_X=True, fit_intercept=True, max_iter=1000,
   normalize=False, positive=False, precompute=False, random_state=None,
   selection='cyclic', tol=0.0001, warm_start=False)
In [83]:
model.score(X_test,y_test)
Out[83]:
0.87745681705925049
In [87]:
X.columns
Out[87]:
Index(['production_budget', 'title_year', 'aspect_ratio', 'duration.1',
       'cast_total_facebook_likes', 'budget', 'imdb_score', 'gross'],
      dtype='object')
In [92]:
for el in zip(list(X.columns),list(model.coef_)):
    print(el)
('production_budget', 0.76287929242158148)
('title_year', 0.82847598230185637)
('aspect_ratio', 0.3963785144996036)
('duration.1', 1.5849161930072848)
('cast_total_facebook_likes', -218.60395867759215)
('budget', 0.0031745843702155035)
('imdb_score', 4426444.4687358243)
('gross', 2.1308279122355804)