Los modelos lineales suponen que las variables independientes, X
, adoptan una relación lineal con la variable dependiente, Y
. Esta relación puede ser dictada por la siguiente ecuación (Ecuación de una línea recta)
Aquí, X
especifica las variables independientes y β
son los coeficientes que indican un cambio de unidad en Y
para un cambio de unidad en X
. Si este supuesto no se cumple, el rendimiento del modelo puede ser deficiente. Las relaciones lineales pueden evaluarse mediante gráficos de dispersión y gráficos de residuos. Los gráficos de dispersión muestran la relación entre la variable independiente "X" y el objetivo "Y".
Los residuos (Pérdida - error) son la diferencia entre la estimación lineal de Y
utilizando X
y el objetivo real
Los modelos lineales suponen que las variables dependientes X
adoptan una relación lineal con la variable dependiente Y
. Si la suposición no es cierta, el modelo puede mostrar un mal rendimiento. Vamos a visualizar las relaciones lineales entre X
y Y
.
En la siguiente celda importa las siguientes librerías: pandas, numpy, matplotlib, seaborn, y sklearn LinearRegression
import pandas as pd
import numpy as np
# for plotting
import matplotlib.pyplot as plt
import seaborn as sns
# for linear regression
from sklearn.linear_model import LinearRegression
Ahora vamos a importar el conjunto de datos de Boston Houses de skit-learn
. Importa load_boston
de sklearn.datasets
# the dataset for the demo
from sklearn.datasets import load_boston
Asigna a la variable boston_dataset
la instancia load_boston()
boston_dataset = load_boston()
A continuación, creamos el dataframe con las variables independientes, recuerda que puedes accede3r a ellas llamando a boston_dataset.data
y a los nombre de las columnas puedes acceder de la siguiente manera boston_dataset.feature_names
. Asigna este nuevo dataframe a la variable boston
.
boston = pd.DataFrame(boston_dataset.data,
columns=boston_dataset.feature_names)
boston.head()
CRIM | ZN | INDUS | CHAS | NOX | RM | AGE | DIS | RAD | TAX | PTRATIO | B | LSTAT | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0.00632 | 18.0 | 2.31 | 0.0 | 0.538 | 6.575 | 65.2 | 4.0900 | 1.0 | 296.0 | 15.3 | 396.90 | 4.98 |
1 | 0.02731 | 0.0 | 7.07 | 0.0 | 0.469 | 6.421 | 78.9 | 4.9671 | 2.0 | 242.0 | 17.8 | 396.90 | 9.14 |
2 | 0.02729 | 0.0 | 7.07 | 0.0 | 0.469 | 7.185 | 61.1 | 4.9671 | 2.0 | 242.0 | 17.8 | 392.83 | 4.03 |
3 | 0.03237 | 0.0 | 2.18 | 0.0 | 0.458 | 6.998 | 45.8 | 6.0622 | 3.0 | 222.0 | 18.7 | 394.63 | 2.94 |
4 | 0.06905 | 0.0 | 2.18 | 0.0 | 0.458 | 7.147 | 54.2 | 6.0622 | 3.0 | 222.0 | 18.7 | 396.90 | 5.33 |
Para acceder a los valores de y
, lo hacemos de la siguiente manera = boston_dataset.target
. Crea una nueva columna llamada MEDV
con la función que acabamos de mostrar, e imprime de nuevo el dataframe de boston
# add the target
boston['MEDV'] = boston_dataset.target
boston.head()
CRIM | ZN | INDUS | CHAS | NOX | RM | AGE | DIS | RAD | TAX | PTRATIO | B | LSTAT | MEDV | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0.00632 | 18.0 | 2.31 | 0.0 | 0.538 | 6.575 | 65.2 | 4.0900 | 1.0 | 296.0 | 15.3 | 396.90 | 4.98 | 24.0 |
1 | 0.02731 | 0.0 | 7.07 | 0.0 | 0.469 | 6.421 | 78.9 | 4.9671 | 2.0 | 242.0 | 17.8 | 396.90 | 9.14 | 21.6 |
2 | 0.02729 | 0.0 | 7.07 | 0.0 | 0.469 | 7.185 | 61.1 | 4.9671 | 2.0 | 242.0 | 17.8 | 392.83 | 4.03 | 34.7 |
3 | 0.03237 | 0.0 | 2.18 | 0.0 | 0.458 | 6.998 | 45.8 | 6.0622 | 3.0 | 222.0 | 18.7 | 394.63 | 2.94 | 33.4 |
4 | 0.06905 | 0.0 | 2.18 | 0.0 | 0.458 | 7.147 | 54.2 | 6.0622 | 3.0 | 222.0 | 18.7 | 396.90 | 5.33 | 36.2 |
Aquí está la información sobre el conjunto de datos. Familiarícese con las variables antes de continuar con el ejercicio.
El objetivo es predecir el "Valor Medio de la Casa" La columna MEDV
en este conjunto de datos y tenemos variables con características sobre las casas y los barrios. Ejecute la siguiente línea, imprima boston_dataset.DESCR
y revise en detalleel dataset
print(boston_dataset.DESCR)
.. _boston_dataset: Boston house prices dataset --------------------------- **Data Set Characteristics:** :Number of Instances: 506 :Number of Attributes: 13 numeric/categorical predictive. Median Value (attribute 14) is usually the target. :Attribute Information (in order): - CRIM per capita crime rate by town - ZN proportion of residential land zoned for lots over 25,000 sq.ft. - INDUS proportion of non-retail business acres per town - CHAS Charles River dummy variable (= 1 if tract bounds river; 0 otherwise) - NOX nitric oxides concentration (parts per 10 million) - RM average number of rooms per dwelling - AGE proportion of owner-occupied units built prior to 1940 - DIS weighted distances to five Boston employment centres - RAD index of accessibility to radial highways - TAX full-value property-tax rate per $10,000 - PTRATIO pupil-teacher ratio by town - B 1000(Bk - 0.63)^2 where Bk is the proportion of blacks by town - LSTAT % lower status of the population - MEDV Median value of owner-occupied homes in $1000's :Missing Attribute Values: None :Creator: Harrison, D. and Rubinfeld, D.L. This is a copy of UCI ML housing dataset. https://archive.ics.uci.edu/ml/machine-learning-databases/housing/ This dataset was taken from the StatLib library which is maintained at Carnegie Mellon University. The Boston house-price data of Harrison, D. and Rubinfeld, D.L. 'Hedonic prices and the demand for clean air', J. Environ. Economics & Management, vol.5, 81-102, 1978. Used in Belsley, Kuh & Welsch, 'Regression diagnostics ...', Wiley, 1980. N.B. Various transformations are used in the table on pages 244-261 of the latter. The Boston house-price data has been used in many machine learning papers that address regression problems. .. topic:: References - Belsley, Kuh & Welsch, 'Regression diagnostics: Identifying Influential Data and Sources of Collinearity', Wiley, 1980. 244-261. - Quinlan,R. (1993). Combining Instance-Based and Model-Based Learning. In Proceedings on the Tenth International Conference of Machine Learning, 236-243, University of Massachusetts, Amherst. Morgan Kaufmann.
Ahora sabemos que el valor de y
en ese conjunto de datos es MEDV
porque es la variable que queremos predecir, es decir, ¡el precio! Mientras que los valores de x
son todas las demás columnas del conjunto de datos. Los gráficos de dispersión sólo nos permiten comparar dos variables, así que debemos hacer un gráfico de dispersión para cada variable x
. Veamos dos de ellos
Grafica un scatterplot con seaborn que lleve el valor de x
a la columna LSTAT
y el valor de y
a MEDV
sns.lmplot(x="LSTAT", y="MEDV", data=boston, order=1)
<seaborn.axisgrid.FacetGrid at 0x7f02921e5ef0>
Aunque no es perfecta, la relación es bastante lineal. Pero fíjese en que es una relación lineal negativa, ya que a medida que aumenta el LSTAT
, disminuye el precio del MEDV
.
Dibuje ahora la relación entre el CRIM
y el MEDV
.
sns.lmplot(x="CRIM", y="MEDV", data=boston, order=1)
<seaborn.axisgrid.FacetGrid at 0x7f028a0a0a20>
Como ya hemos visto, las relaciones lineales también pueden evaluarse mediante la valoración de los residuos. Los residuos son la diferencia entre el valor estimado (predicho) y el real. Si la relación es lineal, los residuos deberían estar distribuidos normalmente y centrados en torno a cero.
Cree el modelo instanciando LinearRegression()
de scikit learn y asignándolo a la variable linreg
.
linreg = LinearRegression()
Muy bien. Ahora vamos a hacer los pasos del análisis de residuos, y teniendo en cuenta sólo una Variable/Columna = LSTAT
.
En la siguiente celda, siga todos los pasos del entrenamiento del modelo y la predicción del modelo. Para esto ultimo, asigne los resultados de la predicción a la variable pred
# fit the model
linreg.fit(boston['LSTAT'].to_frame(), boston['MEDV'])
LinearRegression()
# make the predictions
pred = linreg.predict(boston['LSTAT'].to_frame())
Calcule ahora los residuos, esto se hace restando la variable objetivo a las predicciones. El resultado asignelo a la variable error
# calculate the residuals
error = boston['MEDV'] - pred
error
0 -5.822595 1 -4.270390 2 3.974858 3 1.639304 4 6.709922 ... 501 -2.966864 502 -5.327393 503 -5.295563 504 -6.397521 505 -15.167452 Name: MEDV, Length: 506, dtype: float64
Ahora realice un scatterplot con matplotlib entre pred
(para X
) y la variable objetivo MEDV
para y
. Esto seria un grafico para comparar los valores predichos contra los valores reales
# plot predicted vs real
plt.scatter(x=pred, y=boston['MEDV'])
plt.xlabel('Predictions')
plt.ylabel('MEDV')
Text(0, 0.5, 'MEDV')
Ahora realice el mismo scatterplot pero entre errors
como eje y
y la columna LSTAT
como x
. Si la relación es lineal, el ruido debe ser aleatorio, centrado en cero, y seguir una distribución normal.
plt.scatter(boston['LSTAT'], error)
plt.ylabel('Residuals')
plt.xlabel('LSTAT')
Text(0.5, 0, 'LSTAT')
Dibuja ahora un histograma con seaborn de los residuos (error
) y con 30
bins. El histograma sigue una distribución gaussiana? Porque?
sns.distplot(error, bins=30)
/home/daniel/Desktop/datacademy_project/notebooks/lib/python3.6/site-packages/seaborn/distributions.py:2551: FutureWarning: `distplot` is a deprecated function and will be removed in a future version. Please adapt your code to use either `displot` (a figure-level function with similar flexibility) or `histplot` (an axes-level function for histograms). warnings.warn(msg, FutureWarning)
<AxesSubplot:xlabel='MEDV', ylabel='Density'>
En este caso concreto, los residuos están centrados en torno a cero, pero no se distribuyen de forma homogénea entre los valores de LSTAT. Los valores de LSTAT más grandes y más pequeños muestran valores residuales más altos. Además, vemos en el histograma que los residuos no adoptan una distribución estrictamente gaussiana.
Tienes un dataset con más columnas para jugar, que tal si pruebas otras y revisas las distribuciones una por una. O que tal si corres un comando que permita dibujar un histograma para todas las caracteristicas, sin necesidad de ir uno por uno? En pandas ya existe, haz una pequeña busqeuda en Google y demuestrale a la comunidad lo que encontraste!