<jupyter_start><jupyter_text>**Predicción de precios de casas en USA**Información de las columnas:* 'Avg. Area Income': Ingresos medios de los residentes de la ciudad donde se encuentra la casa.* 'Avg. Area House Age': Edad media de las casas de la misma ciudad* 'Avg. Area Number of Rooms': Media de habitaciones por casa en la misma ciudad* 'Avg. Area Number of Bedrooms': Media de nº de habitaciones en las casas de su ciudad* 'Area Population': Población de la ciudad* 'Price': Precio de venta de la casa* 'Address': Dirección de la casa<jupyter_code># Importamos las librerías básicas:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style('whitegrid')
# Cargamos los datos, y comprobamos sus valores y características básicas:
USA_Housing = pd.read_csv('data/USA_Housing.csv')
USA_Housing.head()
USA_Housing.info()
USA_Housing.describe()
# El método describe es muy útil para sacar estadísticas que resuman la tendencia central, la dispersión y la forma de las distribuciones<jupyter_output><empty_output><jupyter_text>**Exploratory Data Analysis** (EDA)**Visualizando el correlograma**Explorando tipos de relación en todo el conjunto de datos:<jupyter_code>sns.pairplot(USA_Housing);<jupyter_output><empty_output><jupyter_text>**Distribución del precio de las casas en USA**<jupyter_code># Vemos cómo se distribuye el precio, y comprobamos que sigue una distribución normal:

sns.distplot(USA_Housing['Price']);
# Para observar las relaciones lineales, sacamos la matriz de correlación:
USA_Housing.corr()<jupyter_output><empty_output><jupyter_text>**Visualización de la relación lineal de todas las variables contra todas**<jupyter_code>sns.heatmap(USA_Housing.corr(),
           annot=True);<jupyter_output><empty_output><jupyter_text>**Entrenando el modelo de regresión**Lo primero que tendremos que hacer será dividir nuestro dataset los datos que podemos utilizar para entrenar el modelo (en la matriz ``X``) y la etiqueta que queremos predecir (variable ``y``), que en este caso será la columna 'Price'.Por otra parte, dado que la columna 'Address' solo aporta información de texto, pasaremos de ella y la aliminaremos del dataset. Matrices X e Y<jupyter_code># Para ayudarnos a la otra de separar las columnas, las mostramos:
USA_Housing.columns<jupyter_output><empty_output><jupyter_text>La intención será encontrar un modelo tal que:y = a + b1*X1 + b2*X2 + ... + bn*Xn<jupyter_code># Columnas de las que extraer los patrones (features):
X = USA_Housing[['Avg. Area Income', 'Avg. Area House Age', 'Avg. Area Number of Rooms',
                 'Avg. Area Number of Bedrooms', 'Area Population']]
# Columna a predecir (Target)
y = USA_Housing['Price']
X
y<jupyter_output><empty_output><jupyter_text>Por lo general, esta es la notación que se suele utilizar: ``X`` para la matriz de features, e ``y`` para el vector a predecir  **Entrenando el modelo**Ahora que hemos explorado un poco los datos, vamos a dividirlos en conjuntos de train (entrenamiento) y test (prueba), ya que si entrenamos con todos los datos, tal y como hemos visto en clase, no sólo nos quedaremos sin datos para probar cómo es su desempeño sino que se ajustará demasiado a los datos y no podrá generalizar bien<jupyter_code>from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state = 42)
print("Total features shape:", X.shape)
print("Total train features shape:", X_train.shape)
print("Total test features shape:", X_test.shape)
print("Total train target shape:", y_train.shape)
print("Total test target shape:", y_test.shape)
# Importamos el algoritmo Linear Regression Algorithm
from sklearn.linear_model import LinearRegression
# Creamos el objeto para implmentar el algoritmo:
lr = LinearRegression()
# Entrenamos con los datos del modelo:
lr.fit(X_train, y_train)<jupyter_output><empty_output><jupyter_text>**Evaluación del modelo**Ahora ya tenemos entrenado el modelo. ¿Qué significa esto? Pues que ya hemos calculado los coeficientes ($b_i$) de nuestra regresión lineal. En base a ellos, podemos evaluar el modelo: y = a + $b_0X_0$ + $b_1X_1$ + ... $b_nX_n$<jupyter_code># En primer lugar, podemos ver el punto de corte con el eje X (donde X=0):
lr.intercept_
# Y después los coeficientes:
lr.coef_<jupyter_output><empty_output><jupyter_text>**Interpretando los coeficientes:**  - Si mantenemos el resto de variables fijas, un incremento en 1 unidad de la variable **Avg. Area Income** supone un **incremento de \$21.61**.  - Si mantenemos el resto de variables fijas, un incremento en 1 unidad de la variable **Avg. Area House Age** supone un **incremento \$165221.11**.  - Si mantenemos el resto de variables fijas, un incremento en 1 unidad de la variable **Avg. Area Number of Rooms** is associated with an **increase of \$121405.37**.  - Si mantenemos el resto de variables fijas, un incremento en 1 unidad de la variable **Avg. Area Number of Bedrooms** is associated with an **increase of \$1318.71**.  - Si mantenemos el resto de variables fijas, un incremento en 1 unidad de la variable **Area Population** is associated with an **increase of \$15.22**.<jupyter_code>pd.DataFrame(lr.coef_,
             X.columns,
             columns=['Coefficent'])<jupyter_output><empty_output><jupyter_text>**Ha llegado el momento: vamos a predecir**Ahora vamos a probar nuestro modelo, para lo que realizaremos las predicciones sobre los datos de test:<jupyter_code>X_test
predictions = lr.predict(X_test)
predictions
sns.scatterplot(predictions, y_test
               );
X_test.columns
new_homes = np.array([[100000.0, 20.0, 8.0, 4.0, 100000.0],
                     [200000.0, 40.0, 16.0, 8.0, 110000.0]])
new_homes
lr.predict(new_homes)<jupyter_output><empty_output><jupyter_text>**Histograma de residuos**Tras utilizar nuestro modelo, es hora de comprobar algunas cuestiones técnicas que nos permitan conocer información sobre su desempeño. Una de las que hemos visto es el estudio de la distribución de los residuos, que en caso de presentar aleatoriedad (cosa que se deriva de una distribución normal) nos hará suponer que sí existe una relación lieal entre la variable target y las variables de entrada:<jupyter_code>sns.distplot((y_test - predictions),
            bins=50);<jupyter_output><empty_output><jupyter_text>**Sacando las métricas:**Una vez hemos visto cómo se comporta nuestro modelo, es hora de medirlo, ¿cómo de bueno es? Para ello, utilizaremos las métricas más empleadas, que son las que hemos visto en clase):- **MAE** es la media del error.- **MSE** es más utilizada que MAE, porque castiga los errores más grandes, lo que es muy útil de cara a obtener buenos resultados en el mundo real.- **RMSE** es la medida más extendida para la evaluación de un modelo, pues es interpretable en unidades de la variable que estamos prediciendo (target).Estas métricas reciben el nombre de función de costes (o *loss function* en inglés), porque buscan minimizar el error.Vamos a calcularlas para nuestro modelo:<jupyter_code>from sklearn import metrics
print("MAE:", metrics.mean_absolute_error(y_test, predictions))
print("MSE:", metrics.mean_squared_error(y_test, predictions))
print("RMSE:", np.sqrt(metrics.mean_squared_error(y_test, predictions)))
lr.score(X_train, y_train)# Esto nos calcula el R^2
lr.score(X_test, y_test)
USA_Housing['Price'].describe()<jupyter_output><empty_output><jupyter_text>Además del LinearRegressor de sklearn, podemos generar una regresión lineal con la librería ``statsmodels``, que además nos da un estudio de ciertos parámetros para evaluar si estamos ante una buena solución o debemos pensar en otros algoritmos:<jupyter_code>import statsmodels.api as sm

X2 = sm.add_constant(X_train)
est = sm.OLS(y_train, X2)
est2 = est.fit()
print(est2.summary())<jupyter_output>OLS Regression Results                            
==============================================================================
Dep. Variable:                  Price   R-squared:                       0.919
Model:                            OLS   Adj. R-squared:                  0.919
Method:                 Least Squares   F-statistic:                     7960.
Date:                Fri, 22 Jan 2021   Prob (F-statistic):               0.00
Time:                        14:11:48   Log-Likelihood:                -45311.
No. Observations:                3500   AIC:                         9.063e+04
Df Residuals:                    3494   BIC:                         9.067e+04
Df Model:                           5                                         
Covariance Type:            nonrobust                                         
================================================================================================
                                  [...]<jupyter_text>EJERCICIOSi te has fijado, el p-valor de alguna variables es mayor que el umbral de 0.05, por lo que nos planteamos si, en base a lo que hemos visto en clase deberíamos quitarlo. Para ello, no tenemos mejor forma que comprobarlo realizando la simulación. Crea un modelo de regresión lineal que reciba todas menos esa columna y obtén las métricas de tus predicciones. Compáralas con lo que nos daba antes. ¿Hemos mejorado algo?<jupyter_code>X = USA_Housing[['Avg. Area Income', 'Avg. Area House Age', 'Avg. Area Number of Rooms', 'Area Population']]
y = USA_Housing['Price']

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state = 42)
lr = LinearRegression()
lr.fit(X_train, y_train)

predictions = lr.predict(X_test)

print("MAE:", metrics.mean_absolute_error(y_test, predictions))
print("MSE:", metrics.mean_squared_error(y_test, predictions))
print("RMSE:", np.sqrt(metrics.mean_squared_error(y_test, predictions)))
lr.score(X_test, y_test)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1034763163244562, 'fraction_numerical': 0.016060174832282986, 'mean_word_length': 4.244669509594883, 'pattern_counts': {'":': 0, '<': 56, '<?xml version=': 0, '>': 56, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '14', 'dir': 'jupyter-structured-clean-dedup', 'id': '261272', 'license': 'MIT', 'n_tokens_mistral': 3317, 'n_tokens_neox': 3154, 'n_words': 1110, 'path': 'Bloque 3 - Machine Learning/01_Supervisado/1-Linear Regression/01_RESU_Regresión_lineal_USA_House.ipynb', 'repo_name': 'franciscocanon-thebridge/bootcamp_thebridge_PTSep20', 'size': '9838'}