MAT281

Laboratorio Aplicaciones de la Matemática en la Ingeniería

Regresión Lineal

INSTRUCCIONES

  • Anoten su nombre y rol en la celda siguiente.
  • Desarrollen los problemas de manera secuencial.
  • Guarden constantemente con Ctr-S para evitar sorpresas.
  • Reemplacen en las celdas de código donde diga #FIX_ME por el código correspondiente.
  • Ejecuten cada celda de código utilizando Ctr-Enter

In [5]:
# Configuracion para recargar módulos y librerías 
%reload_ext autoreload
%autoreload 2

# Si quieren graficos dentro del ipython notebook, sacar comentario a linea siguiente.
#%matplotlib inline 

from IPython.core.display import HTML

HTML(open("style/mat281.css", "r").read())


Out[5]:

In [6]:
from mat281_code.lab import greetings
alumno_1 = ("Sebastian Flores", "2004001-7")
alumno_2 = ("Maria Jose Vargas", "2004007-8")

HTML(greetings(alumno_1, alumno_2))


Out[6]:
Alumno: Sebastian Flores rol: 2004001-7
Alumno: Maria Jose Vargas rol: 2004007-8
Good luck!

Observación

Este laboratorio utiliza la librería sklearn (oficialmente llamada scikit learn), puesto que buscamos aplicar la técnica de regresión lineal a datos tal como se haría en una aplicación real.

El laboratorio consiste de 2 secciones:

  1. Explicación de uso de regresión lineal en sklearn y análisis de residuos.
  2. Aplicación a problema real.

1. Regresión Lineal con sklearn

Generemos un conjunt de datos sintéticos para aplicar regresión lineal, utilizando numpy y sklearn. El modelo será inicialmente muy simple, del tipo

$$ y = \theta_0 + \theta_1 \ x_1 + \theta_2 x_2 + \varepsilon $$

con $x_i$, $\theta_i$ e $y$ valores reales, y $\varepsilon$ el error de medición.


In [7]:
# Generando los datos
import numpy as np

# Model
m = 1000 # Number of data examples
true_coefficients = np.array([27., 5.])
true_intercept = 1982.
n = len(true_coefficients) + 1

# Data
nx1, nx2 = 21, 26
x1, x2 = np.meshgrid(np.linspace(-1.,1.,nx1), np.linspace(80.,120.,nx2))
X = np.array([x1.flatten(), x2.flatten()]).T
Y = true_intercept + np.dot(X, true_coefficients)

# Measurement contamination
measurement_error = np.random.normal(size=Y.shape)

# Mesured data
Y = Y + 200 * measurement_error/measurement_error.max()

Visualicemos los datos que hemos generado.


In [8]:
# Visualización de los datos
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# Plot of data
fig = plt.figure(figsize=(16,8))
ax = fig.add_subplot(111, projection='3d')
ax.scatter(X[:,0], X[:,1], Y, 'rs')
plt.xlabel("X[:,0]")
plt.ylabel("X[:,1]")
plt.title("y")
plt.show()

Apliquemos un modelo de regresión lineal, obteniendo el intercepto y coeficientes. Utilizando sklearn podemos obtener además la predicción bajo el modelo lineal de manera extremadamente sencilla.


In [9]:
# Aplicando regresion lineal con sklearn a los datos
from sklearn import linear_model

regr = linear_model.LinearRegression(fit_intercept=True, normalize=False)
regr.fit(X, Y) # No es necesario agregar la columna de 1s, el algooritmo lo hace por nosotros. 
print "Intercepto hallado: ", regr.intercept_
print "Coeficientes hallados: ", regr.coef_
Y_pred = regr.predict(X) # Puedo verificar que valores daría el modelo en los puntos conocidos.


Intercepto hallado:  2018.07362263
Coeficientes hallados:  [ 26.51222089   4.66589734]

Visualicemos simultáneamente los datos y la superficie generada con la regresión lineal.


In [12]:
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# Plot of data
fig = plt.figure(figsize=(16,8))
ax = fig.add_subplot(111, projection='3d')
ax.scatter(X[:,0], X[:,1], Y, 'rs')
ax.plot_trisurf(X[:,0], X[:,1], Y_pred, color="r", alpha=0.5, lw=0)
plt.xlabel("X[:,0]")
plt.ylabel("X[:,1]")
plt.title("y")
plt.show()

Hmm, se ve bastante bien. ¿Qué tal los residuos? ¿Responden a nuestra hipótesis de distribución normal? Realicemos una exploración visual.


In [13]:
# Analisando gráfico de los residuos
res = Y_pred - Y
plt.figure(figsize=(16,8))
plt.hist(res)
plt.show()

El gráfico anterior parece suficientemente normal. Utilicemos un test de normalidad para verificar que efectivamente los residuos tengan una distribución normal.


In [14]:
# Analisis estadístico de residuos
import scipy.stats as stats
z, pval = stats.normaltest(res)
if pval < 0.05:
    print "Not normal distribution"
print "p-value =", pval


p-value = 0.676297535397

Calculemos el error promedio en varias normas


In [19]:
print "Error promedio en norma 1:\t", np.linalg.norm(res,1)/len(res)
print "Error promedio en norma 2:\t", np.linalg.norm(res,2)/len(res)
print "Error promedio en norma inf:\t", np.linalg.norm(res,np.inf)


Error promedio en norma 1:	23.2189078113
Error promedio en norma 2:	1.37563251918
Error promedio en norma inf:	168.832997213

Desafío 1

[10%] Desafio 1.1

Utilice el código anterior para generar los mismos datos, pero esta vez no contamine los datos con errores gausianos, sino con elija utilizar un error de tipo gamma, uniforme o poisson (o bien, alguna otra de las posibles). Utilice alguno de los siguientes códigos:

gamma_measurement_error = np.random.gamma(1, size=Y.shape)
    uniform_measurement_error = np.random.uniform(size=Y.shape)-0.5
    weibull_measurement_error = np.random.weibull(1, size=Y.shape)

In [1]:
# 1.1 Desafio 
# Codigo para generar datos con otro tipo de error de medicion
# y para realizar regresión lineal y análisis de los datos.

Desafío 1: Continuación

[10%] 1.2 Indique el tipo de error introducido, y los valores obtenidos para el intercepto y los coeficientes.

FIX ME: COMENTARIO AQUI

[10%] 1.3 ¿Cómo se comparan los valores anteriores a los valores reales (conocidos) y los valores obtenidos para error normal?

FIX ME: COMENTARIO AQUI

[10%] 1.4 ¿Se logra reconocer que los residuos no corresponden a una distibución normal? ¿Cómo?

FIX ME: COMENTARIO AQUI

[10%] 1.5 Compare el error promedio (residuos) del modelo 1 (gausiano) con el modelo 2 (no gausiano), utilizando norma 1, norma 2 y norma infinito. ¿Que observa?

FIX ME: COMENTARIO AQUI

Aplicación a datos reales

Un conjunto de datos bastante interesante es el Motor Dataset, que contiene características de 392 automobiles, entre los años 1970 y 1982.

Este conjunto de datos tiene los siguientes valores:

  1. Rendimiento en millas por galon, mpg (real).
  2. Cilindros del motor, cylinders (entero positivo).
  3. Displazamiento del motor en pulgadas cúbicas, displacement (real).
  4. Caballos de fueza, horsepower (real).
  5. Peso en libras, weight (real).
  6. Tiempo de aceleración de 0 a 100 km/h, acceleration (real).
  7. Año del modelo, model year (entero positivo).
  8. Pais de origen, origin (entero positivo, categórico).
  9. Nombre del Auto, car name (string, unico para cada dato).

Como ya es tradición, exploraremos los datos utilizando head (o tail, o cat).


In [21]:
%%bash
head data/auto-mpg.data.txt


  392  4161 21208 data/auto-mpg.data.txt

Desafío 2

[10 %] Desafio 2.1

Realice una regresión lineal a los datos, buscando predecir el rendimiento (en mpg) utilizando como predictores: el desplazamiento, los caballos de fuerza, el peso y la aceleración, correspondientes a las columnas 2, 3, 4 y 5. Utilice el código provisto anteriormente para ajustar un modelo de regresión lineal, obtener los coeficientes del modelo, realizar predicciones y analice los residuos.

No es necesario incluir gráficos (pero tampoco está prohibido).


In [5]:
import numpy as np
# Lectura de datos
Y = np.loadtxt("data/auto-mpg.data.txt", delimiter=" ", usecols=(0,))
X = np.loadtxt("data/auto-mpg.data.txt", delimiter=" ", usecols=(2,3,4,5))

# Procesamiento de datos

Desafío 2 : Continuación

2.2 [10%] ¿Qué valores se obtienen para el intercepto y los coeficientes de los datos?

FIX ME: COMENTARIO AQUI

2.3 [10%] ¿Cuál es el error de entrenamiento en las distintas normas?

FIX ME: COMENTARIO AQUI

2.4 [10%] ¿Qué tipo de residuo se obtienen? ¿Son gaussianos?

FIX ME: COMENTARIO AQUI

Calculo el rendimiento en mpg tendría el Delorean, si en base a cierta información sabemos que posee:

  1. 6 cilindros
  2. 174 pulgadas cúbicas desplazamiento.
  3. 200 Caballos de fuerza.
  4. 2712 libras de peso.
  5. Una aceleración de 10.5.
  6. Se construyó el año 1981.

Consejo: Utilice el metodo .predict() apropiadamente.


In [2]:
# Calcular el mpg aqui
mpg = 0
print mpg


0

Desafío 3

[10%] 3.1 Indique el rendimiento del delorean. ¿Se corresponde con el valor medido de 21 mpg?

FIX ME: COMENTARIO AQUI