5. Modelado de datos#
5.1. Introducción#
Ya hemos visto algunas técnicas cualitativas. Veamos brevemente un resumen de las técnicas cuantitativas que podemos utilizar para entender los datos:
Tomado de: Choosing a good chart.
Si bien, las técnicas revisadas nos dan un importante entendimiento de los datos, no son suficientes para poder realizar un análisis más profundo. Para ello, es necesario realizar un proceso de modelado. El modelado de datos es un proceso de análisis de datos que busca descubrir patrones y relaciones entre variables. El modelado de datos es una parte fundamental del análisis de datos y es la base para la construcción de modelos de aprendizaje automático (machine learning).
Primero, entendamos en que campo del conocimiento se encuentra el modelado de datos. El modelado de datos es un proceso que se encuentra en el campo de la estadística. La estadística es una rama de las matemáticas que se encarga de recolectar, organizar, analizar e interpretar datos. Sin embargo, en épocas más recientes se ha desarrollado un campo de conocimiento que se encarga de realizar análisis de datos a gran escala. Este campo de conocimiento es el análisis de datos (data analytics). El cual es un proceso que se encarga de recolectar, organizar, analizar e interpretar datos a gran escala. El análisis de datos es un proceso que se encuentra en el campo de la ciencia de datos (data science). La ciencia de datos es un campo de conocimiento que se encarga de recolectar, organizar, analizar e interpretar datos a gran escala utilizando técnicas de estadística, matemáticas, programación y visualización de datos.
Tomado de: Medium.
¿Qué es un modelo?
Un modelo es una forma de representar la realidad. También se suele decir que un modelo es una abstracción de la realidad, una representación simplificada de la realidad o una representación de la realidad que nos permite entenderla mejor y predecir lo que pasará.
Algunos ejemplos de modelos.#
Uno de los modelos más simples que podemos encontrar es el del tiro parabólico:
Si ponemos algunas de estas variables en un modelo matemático, obtenemos la siguiente ecuación:
Donde \(y\) es la altura, \(x\) es la distancia y \(a\), \(b\) y \(c\) son constantes.
En éste caso, tanto \(x\) como \(y\) se les conoce como variables y \(a\), \(b\) y \(c\) como parámetros.
Éste tipo de modelos se los conoce como modelos matemáticos.
Por otro lado, tenemos modelos estocásticos o estadísticos. Un clásico ejemplo es el modelo de regresión lineal.
Datos: https://www.kaggle.com/competitions/house-prices-advanced-regression-techniques/data
(Por ahora no nos preocupemos por el código)
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from scipy import stats
from sklearn.preprocessing import LabelEncoder
sns.set()
# leer datos
df = pd.read_csv('https://raw.githubusercontent.com/alejo-acosta/pmdb-material/master/data/house-train.csv')
# variables categóricas y numéricas
cat_vars = [i for i in df.columns if i not in df._get_numeric_data().columns]
num_vars = [i for i in df.columns if i not in cat_vars]
# eliminar outliers
lista_variables_outliers = ['SalePrice', 'OverallQual', 'GrLivArea', 'GarageCars', 'GarageArea', 'TotalBsmtSF',]
df = df[(np.abs(stats.zscore(df[lista_variables_outliers])) < 3).all(axis=1)]
df.shape
(1420, 81)
df.corr(numeric_only=True)
Id | MSSubClass | LotFrontage | LotArea | OverallQual | OverallCond | YearBuilt | YearRemodAdd | MasVnrArea | BsmtFinSF1 | ... | WoodDeckSF | OpenPorchSF | EnclosedPorch | 3SsnPorch | ScreenPorch | PoolArea | MiscVal | MoSold | YrSold | SalePrice | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Id | 1.000000 | 0.009621 | -0.021551 | -0.038818 | -0.029113 | 0.012741 | -0.017785 | -0.020428 | -0.060695 | -0.017975 | ... | -0.040320 | -0.006093 | 0.013044 | -0.047429 | 0.008419 | 0.058125 | -0.007117 | 0.026235 | 0.001594 | -0.028339 |
MSSubClass | 0.009621 | 1.000000 | -0.416096 | -0.149659 | 0.047990 | -0.070054 | 0.042037 | 0.045069 | 0.039232 | -0.067868 | ... | -0.014463 | -0.002367 | -0.013658 | -0.044716 | -0.028726 | 0.003860 | -0.007569 | -0.011168 | -0.016375 | -0.083061 |
LotFrontage | -0.021551 | -0.416096 | 1.000000 | 0.388814 | 0.200827 | -0.047492 | 0.114217 | 0.068135 | 0.145392 | 0.119650 | ... | 0.073115 | 0.107991 | -0.009496 | 0.080022 | 0.045194 | 0.019435 | 0.003201 | 0.030580 | 0.012295 | 0.359398 |
LotArea | -0.038818 | -0.149659 | 0.388814 | 1.000000 | 0.068681 | 0.001046 | 0.002335 | -0.003509 | 0.052459 | 0.159139 | ... | 0.152759 | 0.057198 | -0.021991 | 0.023672 | 0.031435 | 0.021404 | 0.040562 | 0.012069 | -0.011880 | 0.258683 |
OverallQual | -0.029113 | 0.047990 | 0.200827 | 0.068681 | 1.000000 | -0.109772 | 0.580568 | 0.540272 | 0.352730 | 0.172550 | ... | 0.220549 | 0.279620 | -0.126313 | 0.038104 | 0.052519 | 0.006848 | -0.027982 | 0.078137 | -0.023864 | 0.799280 |
OverallCond | 0.012741 | -0.070054 | -0.047492 | 0.001046 | -0.109772 | 1.000000 | -0.374825 | 0.072095 | -0.130476 | -0.023991 | ... | -0.002377 | -0.033548 | 0.082156 | 0.024903 | 0.042494 | 0.023986 | 0.070653 | -0.010055 | 0.049796 | -0.087776 |
YearBuilt | -0.017785 | 0.042037 | 0.114217 | 0.002335 | 0.580568 | -0.374825 | 1.000000 | 0.592912 | 0.299861 | 0.229749 | ... | 0.219863 | 0.178678 | -0.397671 | 0.033396 | -0.044684 | 0.003906 | -0.033263 | 0.010397 | -0.020457 | 0.573975 |
YearRemodAdd | -0.020428 | 0.045069 | 0.068135 | -0.003509 | 0.540272 | 0.072095 | 0.592912 | 1.000000 | 0.150106 | 0.101205 | ... | 0.199823 | 0.213640 | -0.200636 | 0.047964 | -0.045501 | -0.012309 | -0.007571 | 0.022569 | 0.036678 | 0.536000 |
MasVnrArea | -0.060695 | 0.039232 | 0.145392 | 0.052459 | 0.352730 | -0.130476 | 0.299861 | 0.150106 | 1.000000 | 0.209497 | ... | 0.129064 | 0.101776 | -0.105213 | 0.027028 | 0.073498 | -0.009980 | -0.028369 | 0.008098 | -0.011092 | 0.411393 |
BsmtFinSF1 | -0.017975 | -0.067868 | 0.119650 | 0.159139 | 0.172550 | -0.023991 | 0.229749 | 0.101205 | 0.209497 | 1.000000 | ... | 0.188428 | 0.055745 | -0.117118 | 0.034551 | 0.077734 | 0.004319 | 0.008649 | 0.007750 | 0.014777 | 0.361936 |
BsmtFinSF2 | -0.002119 | -0.064314 | 0.054036 | 0.119265 | -0.062201 | 0.041951 | -0.051028 | -0.068865 | -0.070000 | -0.055476 | ... | 0.079780 | 0.010126 | 0.032677 | -0.030548 | 0.087752 | 0.048532 | 0.004949 | -0.017885 | 0.029258 | -0.004782 |
BsmtUnfSF | -0.004376 | -0.140139 | 0.132860 | -0.006170 | 0.298336 | -0.150174 | 0.147230 | 0.172410 | 0.088732 | -0.556108 | ... | -0.018743 | 0.120542 | -0.001686 | 0.023617 | -0.020835 | -0.023278 | -0.023710 | 0.035132 | -0.046325 | 0.203526 |
TotalBsmtSF | -0.025231 | -0.257936 | 0.298392 | 0.215313 | 0.495435 | -0.176979 | 0.392141 | 0.274034 | 0.296382 | 0.432061 | ... | 0.216169 | 0.199957 | -0.114643 | 0.050981 | 0.097589 | -0.001018 | -0.015211 | 0.040307 | -0.023750 | 0.617726 |
1stFlrSF | 0.002358 | -0.270611 | 0.391584 | 0.261491 | 0.412187 | -0.152869 | 0.268802 | 0.211890 | 0.268363 | 0.354437 | ... | 0.207521 | 0.157426 | -0.076616 | 0.070864 | 0.099181 | 0.033485 | -0.017420 | 0.060635 | -0.016423 | 0.582620 |
2ndFlrSF | 0.008105 | 0.312220 | 0.036506 | 0.014764 | 0.266113 | 0.013541 | 0.013189 | 0.124694 | 0.131514 | -0.202605 | ... | 0.068724 | 0.205234 | 0.063990 | -0.022363 | 0.026488 | 0.017861 | 0.020223 | 0.044142 | -0.020806 | 0.278211 |
LowQualFinSF | -0.028965 | 0.019915 | 0.013293 | -0.013412 | -0.067973 | -0.002074 | -0.159068 | -0.078560 | -0.066142 | -0.071264 | ... | -0.009141 | -0.011815 | 0.021783 | -0.002475 | -0.030601 | -0.005983 | -0.002403 | -0.007274 | -0.006814 | -0.073286 |
GrLivArea | 0.006457 | 0.082398 | 0.334468 | 0.211128 | 0.551004 | -0.104043 | 0.201318 | 0.267980 | 0.317642 | 0.076961 | ... | 0.219971 | 0.306794 | 0.002492 | 0.033151 | 0.096793 | 0.041273 | 0.005066 | 0.085897 | -0.032220 | 0.691209 |
BsmtFullBath | -0.001711 | 0.008962 | 0.067987 | 0.140862 | 0.090223 | -0.038879 | 0.175190 | 0.110922 | 0.068172 | 0.656567 | ... | 0.166353 | 0.050259 | -0.058286 | 0.001497 | 0.028851 | 0.028969 | -0.021615 | -0.019680 | 0.066400 | 0.236344 |
BsmtHalfBath | -0.017148 | -0.004664 | -0.021548 | 0.047681 | -0.045921 | 0.122609 | -0.033810 | -0.010625 | 0.025148 | 0.074985 | ... | 0.041759 | -0.020402 | -0.033970 | 0.035424 | 0.036250 | -0.012719 | -0.007345 | 0.041146 | -0.042068 | -0.026790 |
FullBath | 0.006626 | 0.140909 | 0.170096 | 0.101439 | 0.524377 | -0.218522 | 0.475003 | 0.427316 | 0.228160 | 0.012828 | ... | 0.161755 | 0.252857 | -0.127915 | 0.040883 | -0.019599 | 0.016623 | -0.011155 | 0.061471 | -0.018573 | 0.546787 |
HalfBath | 0.000273 | 0.185976 | 0.035798 | -0.002604 | 0.259677 | -0.060213 | 0.238869 | 0.175231 | 0.184638 | -0.024091 | ... | 0.097891 | 0.185443 | -0.088322 | -0.003450 | 0.068306 | 0.009909 | 0.003110 | -0.007947 | -0.008693 | 0.281715 |
BedroomAbvGr | 0.038200 | -0.048734 | 0.280617 | 0.114899 | 0.080345 | -0.006355 | -0.068586 | -0.055707 | 0.100239 | -0.125564 | ... | 0.032887 | 0.094782 | 0.034854 | -0.024037 | 0.038099 | 0.056840 | 0.009966 | 0.053140 | -0.034735 | 0.158195 |
KitchenAbvGr | 0.003275 | 0.276212 | 0.003380 | -0.013736 | -0.189654 | -0.095969 | -0.171663 | -0.150560 | -0.029590 | -0.080001 | ... | -0.086811 | -0.072016 | 0.040097 | -0.025103 | -0.051614 | -0.011210 | 0.062736 | 0.029288 | 0.034102 | -0.148215 |
TotRmsAbvGrd | 0.031595 | 0.035387 | 0.328658 | 0.152459 | 0.368019 | -0.074965 | 0.079134 | 0.157212 | 0.220394 | -0.048975 | ... | 0.139871 | 0.204335 | 0.008516 | -0.001100 | 0.037482 | 0.039611 | 0.031503 | 0.054779 | -0.038087 | 0.479828 |
Fireplaces | -0.022740 | -0.042442 | 0.227041 | 0.254272 | 0.364492 | -0.028427 | 0.136065 | 0.089521 | 0.214064 | 0.218873 | ... | 0.187765 | 0.154158 | -0.022783 | 0.014772 | 0.183224 | 0.050838 | 0.004596 | 0.060390 | -0.025094 | 0.461168 |
GarageYrBlt | -0.000074 | 0.095978 | 0.051941 | -0.043868 | 0.546837 | -0.329106 | 0.832099 | 0.639424 | 0.228677 | 0.129871 | ... | 0.216942 | 0.213881 | -0.291563 | 0.026456 | -0.084927 | -0.010657 | -0.031689 | 0.008548 | -0.005883 | 0.516885 |
GarageCars | 0.015540 | -0.035639 | 0.272450 | 0.129896 | 0.582251 | -0.196437 | 0.540309 | 0.407866 | 0.331647 | 0.194047 | ... | 0.203547 | 0.198684 | -0.154294 | 0.041379 | 0.042242 | 0.001903 | -0.043091 | 0.043633 | -0.041658 | 0.652158 |
GarageArea | 0.012252 | -0.097686 | 0.296419 | 0.138271 | 0.541277 | -0.158334 | 0.488148 | 0.360740 | 0.328004 | 0.241241 | ... | 0.205364 | 0.216287 | -0.130040 | 0.043492 | 0.046672 | -0.001890 | -0.028263 | 0.041233 | -0.030865 | 0.639583 |
WoodDeckSF | -0.040320 | -0.014463 | 0.073115 | 0.152759 | 0.220549 | -0.002377 | 0.219863 | 0.199823 | 0.129064 | 0.188428 | ... | 1.000000 | 0.043225 | -0.127230 | -0.031436 | -0.075754 | 0.084728 | -0.007540 | 0.028682 | 0.020772 | 0.324090 |
OpenPorchSF | -0.006093 | -0.002367 | 0.107991 | 0.057198 | 0.279620 | -0.033548 | 0.178678 | 0.213640 | 0.101776 | 0.055745 | ... | 0.043225 | 1.000000 | -0.090668 | -0.003648 | 0.062485 | 0.039329 | -0.017168 | 0.081898 | -0.053504 | 0.325225 |
EnclosedPorch | 0.013044 | -0.013658 | -0.009496 | -0.021991 | -0.126313 | 0.082156 | -0.397671 | -0.200636 | -0.105213 | -0.117118 | ... | -0.127230 | -0.090668 | 1.000000 | -0.038650 | -0.083756 | -0.019341 | 0.019319 | -0.024462 | 0.000857 | -0.148736 |
3SsnPorch | -0.047429 | -0.044716 | 0.080022 | 0.023672 | 0.038104 | 0.024903 | 0.033396 | 0.047964 | 0.027028 | 0.034551 | ... | -0.031436 | -0.003648 | -0.038650 | 1.000000 | -0.031800 | -0.006217 | 0.000159 | 0.028936 | 0.018794 | 0.064986 |
ScreenPorch | 0.008419 | -0.028726 | 0.045194 | 0.031435 | 0.052519 | 0.042494 | -0.044684 | -0.045501 | 0.073498 | 0.077734 | ... | -0.075754 | 0.062485 | -0.083756 | -0.031800 | 1.000000 | 0.074155 | 0.033554 | 0.029660 | 0.009544 | 0.098910 |
PoolArea | 0.058125 | 0.003860 | 0.019435 | 0.021404 | 0.006848 | 0.023986 | 0.003906 | -0.012309 | -0.009980 | 0.004319 | ... | 0.084728 | 0.039329 | -0.019341 | -0.006217 | 0.074155 | 1.000000 | 0.039211 | -0.012007 | -0.053643 | 0.036755 |
MiscVal | -0.007117 | -0.007569 | 0.003201 | 0.040562 | -0.027982 | 0.070653 | -0.033263 | -0.007571 | -0.028369 | 0.008649 | ... | -0.007540 | -0.017168 | 0.019319 | 0.000159 | 0.033554 | 0.039211 | 1.000000 | -0.007846 | 0.004789 | -0.016619 |
MoSold | 0.026235 | -0.011168 | 0.030580 | 0.012069 | 0.078137 | -0.010055 | 0.010397 | 0.022569 | 0.008098 | 0.007750 | ... | 0.028682 | 0.081898 | -0.024462 | 0.028936 | 0.029660 | -0.012007 | -0.007846 | 1.000000 | -0.149396 | 0.082498 |
YrSold | 0.001594 | -0.016375 | 0.012295 | -0.011880 | -0.023864 | 0.049796 | -0.020457 | 0.036678 | -0.011092 | 0.014777 | ... | 0.020772 | -0.053504 | 0.000857 | 0.018794 | 0.009544 | -0.053643 | 0.004789 | -0.149396 | 1.000000 | -0.029777 |
SalePrice | -0.028339 | -0.083061 | 0.359398 | 0.258683 | 0.799280 | -0.087776 | 0.573975 | 0.536000 | 0.411393 | 0.361936 | ... | 0.324090 | 0.325225 | -0.148736 | 0.064986 | 0.098910 | 0.036755 | -0.016619 | 0.082498 | -0.029777 | 1.000000 |
38 rows × 38 columns
corr = df[num_vars].corr()[['SalePrice']].sort_values(by='SalePrice', ascending=False)
corr = corr.style.background_gradient(cmap='coolwarm')
corr
SalePrice | |
---|---|
SalePrice | 1.000000 |
OverallQual | 0.799280 |
GrLivArea | 0.691209 |
GarageCars | 0.652158 |
GarageArea | 0.639583 |
TotalBsmtSF | 0.617726 |
1stFlrSF | 0.582620 |
YearBuilt | 0.573975 |
FullBath | 0.546787 |
YearRemodAdd | 0.536000 |
GarageYrBlt | 0.516885 |
TotRmsAbvGrd | 0.479828 |
Fireplaces | 0.461168 |
MasVnrArea | 0.411393 |
BsmtFinSF1 | 0.361936 |
LotFrontage | 0.359398 |
OpenPorchSF | 0.325225 |
WoodDeckSF | 0.324090 |
HalfBath | 0.281715 |
2ndFlrSF | 0.278211 |
LotArea | 0.258683 |
BsmtFullBath | 0.236344 |
BsmtUnfSF | 0.203526 |
BedroomAbvGr | 0.158195 |
ScreenPorch | 0.098910 |
MoSold | 0.082498 |
3SsnPorch | 0.064986 |
PoolArea | 0.036755 |
BsmtFinSF2 | -0.004782 |
MiscVal | -0.016619 |
BsmtHalfBath | -0.026790 |
Id | -0.028339 |
YrSold | -0.029777 |
LowQualFinSF | -0.073286 |
MSSubClass | -0.083061 |
OverallCond | -0.087776 |
KitchenAbvGr | -0.148215 |
EnclosedPorch | -0.148736 |
sns.regplot(x='GrLivArea', y='SalePrice', data=df, scatter_kws={'alpha':0.7, 'edgecolor':'none'}, marker='.', line_kws={'color':'darkorange'})
plt.show()
No podemos predecir con exactitud el valor de \(y\) a partir de \(x\), pero podemos predecir un intervalo de valores en los que se encontrará \(y\) con cierta probabilidad. Por ejemplo, podemos decir que con un 95% de probabilidad, dado un valor determinado de \(x=1000\), \(y\) se encontrará entre \(75000 y \)125000.
El gráfico es una representación cualitativa del modelo, pero el modelo en sí tomaría la forma de la siguiente ecuación:
Donde \(y\) es el precio de la vivienda en dólares, \(x\) es el área de construcción en pies cuadrados y \(a\) y \(b\) son las constantes o parámetros del modelo.
5.2. Modelos de regresión básicos#
sns.regplot(x='GrLivArea', y='SalePrice', data=df, scatter_kws={'alpha':0.7, 'edgecolor':'none'}, marker='.', line_kws={'color':'darkorange'})
plt.xlim(0, 3000)
plt.show()
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
y = df['SalePrice']
X = df[['GrLivArea']]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
lr = LinearRegression()
lr.fit(X_train, y_train)
print('Intercept: ', lr.intercept_)
print('Coef: ', lr.coef_)
Intercept: 25506.75033248376
Coef: [101.46531224]
\(Precio = 100 [\frac{USD}{Área}] * Metros\_cuadrados [Área] + 27000[USD]\)
La más simple:
La regresión lineal, no necesariamente tiene que tener una sola variable independiente. Puede tener más de una variable independiente. Por ejemplo, podemos tener un modelo de regresión lineal con dos variables independientes:
Además, las variables independiente pueden tener ciertas transformaciones. Por ejemplo, podemos tener un modelo de regresión lineal con una variable independiente que es el cuadrado de otra variable independiente:
Tomado de: Tax Foundation.
¿Qué ecuación matemática podría representar el gráfico anterior?
(1) $\(y = ax^2 + bx + c\)\( (2) \)\(y = bx + c\)$
def plot_order(order=1, fit_reg=False, extended=False):
x = np.linspace(0, 20, 19)
def func(x):
return x*np.sin(x)+x
y = func(x)
import warnings
params = {'scatter_kws':{'alpha':1, 'edgecolor':'none'},
'marker':'o', 'line_kws':{'color':'darkorange'},
'ci':0, 'x':x, 'y':y}
warnings.filterwarnings('ignore')
fit = np.polyfit(x, y, order)
fit_fn = np.poly1d(fit)
if extended: xline = np.linspace(-5,25,100)
else: xline = np.linspace(0,20,100)
fig = plt.figure(figsize=(8, 5))
if fit_reg:
plt.plot(x, y, 'bo', xline, fit_fn(xline), '--r')
sns.regplot(order=order, **params, fit_reg=False)
plt.axvspan(-1, 21, color='grey', alpha=0.2)
plt.xlim(-5, 25)
plt.ylim(-10, 50)
plt.show()
from ipywidgets import interact
interact(plot_order, order=(1, 20, 1))
plt.show()
Overfitting: es un problema que se presenta cuando el modelo se ajusta demasiado a los datos de entrenamiento. En otras palabras, el modelo se ajusta demasiado a los datos que tiene disponible y no generaliza bien a nuevos datos.
5.2.1. Ejemplo regresión lineal#
corr
SalePrice | |
---|---|
SalePrice | 1.000000 |
OverallQual | 0.799280 |
GrLivArea | 0.691209 |
GarageCars | 0.652158 |
GarageArea | 0.639583 |
TotalBsmtSF | 0.617726 |
1stFlrSF | 0.582620 |
YearBuilt | 0.573975 |
FullBath | 0.546787 |
YearRemodAdd | 0.536000 |
GarageYrBlt | 0.516885 |
TotRmsAbvGrd | 0.479828 |
Fireplaces | 0.461168 |
MasVnrArea | 0.411393 |
BsmtFinSF1 | 0.361936 |
LotFrontage | 0.359398 |
OpenPorchSF | 0.325225 |
WoodDeckSF | 0.324090 |
HalfBath | 0.281715 |
2ndFlrSF | 0.278211 |
LotArea | 0.258683 |
BsmtFullBath | 0.236344 |
BsmtUnfSF | 0.203526 |
BedroomAbvGr | 0.158195 |
ScreenPorch | 0.098910 |
MoSold | 0.082498 |
3SsnPorch | 0.064986 |
PoolArea | 0.036755 |
BsmtFinSF2 | -0.004782 |
MiscVal | -0.016619 |
BsmtHalfBath | -0.026790 |
Id | -0.028339 |
YrSold | -0.029777 |
LowQualFinSF | -0.073286 |
MSSubClass | -0.083061 |
OverallCond | -0.087776 |
KitchenAbvGr | -0.148215 |
EnclosedPorch | -0.148736 |
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
y = df['SalePrice']
X = df[['GrLivArea']]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
El modelo teórico sería de la siguiente forma:
Lo que buscamos son los parámetros \(a\), \(b\) y \(c\). Donde \(a\) es el coeficiente de la variable \(x_1\), \(b\) es el coeficiente de la variable \(x_2\) y \(c\) es el intercepto.
Para ello, utilizaremos el método de mínimos cuadrados. El método de mínimos cuadrados es un método que busca minimizar la suma de los errores al cuadrado. En otras palabras, busca minimizar la suma de las diferencias entre los valores reales y los valores predichos al cuadrado.
modelo_rl = LinearRegression()
modelo_rl.fit(X_train, y_train)
LinearRegression()In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
LinearRegression()
Podemos obtener un score de nuestro modelo, que indica que tan bien se ajusta a un set de datos. En éste caso siempre se debe obtener el score frente a los datos de prueba (test data).
modelo_rl.score(X_test, y_test)
0.46011963176263837
Para obtener el intercepto y los coeficientes del modelo:
modelo_rl.intercept_
25506.75033248376
modelo_rl.coef_
array([101.46531224])
Podemos hacer predicciones del modelo utilizando el método predict para comparar el valor predicho con el valor real.
pred = modelo_rl.predict(X_test)
y_test_df = pd.DataFrame(y_test)
y_test_df['pred'] = pred
y_test_df
SalePrice | pred | |
---|---|---|
51 | 114500 | 144829.957532 |
295 | 142500 | 127276.458514 |
700 | 312500 | 208144.312373 |
1033 | 230000 | 193330.376785 |
377 | 340000 | 275720.210328 |
... | ... | ... |
1328 | 256000 | 308797.902120 |
360 | 156000 | 118043.115100 |
1337 | 52500 | 95822.211718 |
1450 | 136000 | 207332.589875 |
566 | 325000 | 279575.892193 |
284 rows × 2 columns
También podemos ingresar valores de cada variable independiente para obtener un valor predicho.
modelo_rl.predict([[2000]])
array([228437.374822])
5.2.2. Variables categóricas#
Es una variable que puede tomar un número limitado de valores. Por ejemplo, el género de una persona puede ser masculino o femenino. Otra variable categórica puede ser el color de un auto, el cual puede ser rojo, azul o verde.
Las variables categóricas se pueden dividir en dos tipos: ordinales y nominales.
Las variables categóricas ordinales son aquellas que tienen un orden. Por ejemplo, el nivel de educación de una persona puede ser primaria, secundaria, universitaria o posgrado. En éste caso, el nivel de educación tiene un orden, ya que una persona con educación universitaria tiene más educación que una persona con educación secundaria.
Las variables categóricas nominales son aquellas que no tienen un orden. Por ejemplo, el color de un auto puede ser rojo, azul o verde. En éste caso, el color de un auto no tiene un orden, ya que no podemos decir que el color rojo es mayor o menor que el color azul.
Hay dos formas de representar las variables categóricas:
La primera forma es utilizando números. Por ejemplo, podemos representar el género de una persona con 0 para masculino y 1 para femenino. O podemos representar el color de un auto con 0 para rojo, 1 para azul y 2 para verde.
La segunda forma es utilizando variables dummies. Una variable dummy es una variable que toma el valor de 0 o 1. Por ejemplo, podemos representar el género de una persona con dos variables dummies: una variable dummy para masculino y otra variable dummy para femenino. En éste caso, la variable dummy para masculino toma el valor de 1 cuando el género de la persona es masculino y 0 cuando el género de la persona es femenino. Por otro lado, la variable dummy para femenino toma el valor de 1 cuando el género de la persona es femenino y 0 cuando el género de la persona es masculino. De ésta forma, podemos representar el género de una persona con dos variables dummies: una variable dummy para masculino y otra variable dummy para femenino.
df['OverallQual'].value_counts().sort_index()
2 3
3 19
4 115
5 397
6 373
7 317
8 156
9 36
10 4
Name: OverallQual, dtype: int64
df
Id | MSSubClass | MSZoning | LotFrontage | LotArea | Street | Alley | LotShape | LandContour | Utilities | ... | PoolArea | PoolQC | Fence | MiscFeature | MiscVal | MoSold | YrSold | SaleType | SaleCondition | SalePrice | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 60 | RL | 65.0 | 8450 | Pave | NaN | Reg | Lvl | AllPub | ... | 0 | NaN | NaN | NaN | 0 | 2 | 2008 | WD | Normal | 208500 |
1 | 2 | 20 | RL | 80.0 | 9600 | Pave | NaN | Reg | Lvl | AllPub | ... | 0 | NaN | NaN | NaN | 0 | 5 | 2007 | WD | Normal | 181500 |
2 | 3 | 60 | RL | 68.0 | 11250 | Pave | NaN | IR1 | Lvl | AllPub | ... | 0 | NaN | NaN | NaN | 0 | 9 | 2008 | WD | Normal | 223500 |
3 | 4 | 70 | RL | 60.0 | 9550 | Pave | NaN | IR1 | Lvl | AllPub | ... | 0 | NaN | NaN | NaN | 0 | 2 | 2006 | WD | Abnorml | 140000 |
4 | 5 | 60 | RL | 84.0 | 14260 | Pave | NaN | IR1 | Lvl | AllPub | ... | 0 | NaN | NaN | NaN | 0 | 12 | 2008 | WD | Normal | 250000 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
1455 | 1456 | 60 | RL | 62.0 | 7917 | Pave | NaN | Reg | Lvl | AllPub | ... | 0 | NaN | NaN | NaN | 0 | 8 | 2007 | WD | Normal | 175000 |
1456 | 1457 | 20 | RL | 85.0 | 13175 | Pave | NaN | Reg | Lvl | AllPub | ... | 0 | NaN | MnPrv | NaN | 0 | 2 | 2010 | WD | Normal | 210000 |
1457 | 1458 | 70 | RL | 66.0 | 9042 | Pave | NaN | Reg | Lvl | AllPub | ... | 0 | NaN | GdPrv | Shed | 2500 | 5 | 2010 | WD | Normal | 266500 |
1458 | 1459 | 20 | RL | 68.0 | 9717 | Pave | NaN | Reg | Lvl | AllPub | ... | 0 | NaN | NaN | NaN | 0 | 4 | 2010 | WD | Normal | 142125 |
1459 | 1460 | 20 | RL | 75.0 | 9937 | Pave | NaN | Reg | Lvl | AllPub | ... | 0 | NaN | NaN | NaN | 0 | 6 | 2008 | WD | Normal | 147500 |
1420 rows × 81 columns
df2 = pd.get_dummies(df, columns=['OverallQual'], drop_first=True )
df2
Id | MSSubClass | MSZoning | LotFrontage | LotArea | Street | Alley | LotShape | LandContour | Utilities | ... | SaleCondition | SalePrice | OverallQual_3 | OverallQual_4 | OverallQual_5 | OverallQual_6 | OverallQual_7 | OverallQual_8 | OverallQual_9 | OverallQual_10 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 60 | RL | 65.0 | 8450 | Pave | NaN | Reg | Lvl | AllPub | ... | Normal | 208500 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
1 | 2 | 20 | RL | 80.0 | 9600 | Pave | NaN | Reg | Lvl | AllPub | ... | Normal | 181500 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
2 | 3 | 60 | RL | 68.0 | 11250 | Pave | NaN | IR1 | Lvl | AllPub | ... | Normal | 223500 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
3 | 4 | 70 | RL | 60.0 | 9550 | Pave | NaN | IR1 | Lvl | AllPub | ... | Abnorml | 140000 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
4 | 5 | 60 | RL | 84.0 | 14260 | Pave | NaN | IR1 | Lvl | AllPub | ... | Normal | 250000 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
1455 | 1456 | 60 | RL | 62.0 | 7917 | Pave | NaN | Reg | Lvl | AllPub | ... | Normal | 175000 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
1456 | 1457 | 20 | RL | 85.0 | 13175 | Pave | NaN | Reg | Lvl | AllPub | ... | Normal | 210000 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
1457 | 1458 | 70 | RL | 66.0 | 9042 | Pave | NaN | Reg | Lvl | AllPub | ... | Normal | 266500 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
1458 | 1459 | 20 | RL | 68.0 | 9717 | Pave | NaN | Reg | Lvl | AllPub | ... | Normal | 142125 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
1459 | 1460 | 20 | RL | 75.0 | 9937 | Pave | NaN | Reg | Lvl | AllPub | ... | Normal | 147500 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
1420 rows × 88 columns
y = df2['SalePrice']
X = df2[['OverallQual_3', 'OverallQual_4', 'OverallQual_5', 'OverallQual_6', 'OverallQual_7', 'OverallQual_8', 'OverallQual_9', 'OverallQual_10']]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
modelo2 = LinearRegression()
modelo2.fit(X_train, y_train)
LinearRegression()In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
LinearRegression()
X.columns
Index(['OverallQual_3', 'OverallQual_4', 'OverallQual_5', 'OverallQual_6',
'OverallQual_7', 'OverallQual_8', 'OverallQual_9', 'OverallQual_10'],
dtype='object')
modelo2.intercept_
51770.333333332936
plt.bar(X.columns, modelo2.coef_+modelo2.intercept_)
plt.xticks(rotation=90)
plt.show()
5.3. Los distintos tipos de modelos#
Existe una infinidad de modelos. Sin embargo, podemos clasificarlos en tres grandes grupos de acuerdo al siguiente diagrama:
Tomado de: Abdul Rahid.
En general, un proyecto en ciencia de datos sigue el siguiente flujo:
Definir el problema y mirar el panorama general.
Obtener los datos.
Explorar los datos para obtener información general y estadística descriptiva.
Preparación y limpieza de los datos.
4.1. Separación de los datos en entrenamiento y prueba (cross-validation).Exploración y selección de modelos.
Afinar los modelos (hiperparámetros).
Interpretación del modelo.
Presentación de la solución.
Desplegar, monitorear y mantener el sistema.
5.4. Aprendizaje supervisado#
Los modelos de aprendizaje supervisado son aquellos que utilizan datos etiquetados para entrenar el modelo. En otras palabras, el modelo aprende a partir de casos en los cuales tenemos las variables independientes (x) y también tenemos las variables (y). Por ejemplo, si queremos entrenar un modelo para que reconozca imágenes de perros, necesitamos tener un set de datos de imágenes de perros etiquetadas como perros y otro set de datos de imágenes de gatos etiquetadas como gatos. De ésta forma, el modelo aprende a reconocer las imágenes de perros y gatos.
Es similar a tener un profesor que nos dice si lo que estamos haciendo está bien o mal. Por ejemplo, si estamos aprendiendo a sumar, el profesor nos dice si la suma que hicimos está bien o mal. De ésta forma, aprendemos a sumar.
¿Qué tipo de modelos de aprendizaje supervisado conocen?
Tomado de: Analyst Prep.
5.4.1. Modelos de regresión#
Un modelo de regresión es un modelo que busca predecir un valor numérico (variable continua). Por ejemplo, el precio de una vivienda, el precio de una acción, la cantidad de ventas de un producto, etc.
5.4.2. Modelos de clasificación#
Un modelo de clasificación es un modelo que busca predecir una clase (variable categórica). Por ejemplo, si una imagen es un perro o un gato, si un correo electrónico es spam o no, si un tumor es benigno o maligno, si una hogar es pobre o no, etc.
5.4.3. Árboles de decisión y bosques aleatorios#
Un árbol de decisión es un modelo de aprendizaje supervisado que utiliza un árbol para predecir una clase (variable categórica) o un valor numérico (variable continua). Un árbol de decisión es un modelo que se puede utilizar tanto para clasificación como para regresión.
Tomado de: Wikipedia.
df3 = df.copy()
encoders = {}
for col in cat_vars:
le = LabelEncoder()
encoders[col] = le
df3[col] = le.fit_transform(df[col])
# decition tree classifier on OverallQual
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
perdidos = df3.isna().sum()
y = df3['OverallQual']
x = df3[[i for i in df3.columns if i not in ['OverallQual', 'SalePrice'] and perdidos[i] == 0]]
X_train, X_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=42)
dt = DecisionTreeClassifier()
dt.fit(X_train, y_train)
DecisionTreeClassifier()In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
DecisionTreeClassifier()
# plot tree
from sklearn.tree import plot_tree
fig = plt.figure(figsize=(40, 15), dpi=150)
plot_tree(dt, feature_names=x.columns, class_names=['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'], filled=True, fontsize=7)
plt.show()
# Matríz de confusión
from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay, accuracy_score
y_pred = dt.predict(X_test)
cmatrix_tc = confusion_matrix(y_test, y_pred)
cmatrix_tc
array([[ 0, 0, 1, 0, 0, 0, 0, 0, 0],
[ 0, 0, 0, 2, 0, 0, 0, 0, 0],
[ 0, 0, 12, 15, 2, 1, 0, 0, 0],
[ 0, 1, 11, 37, 25, 1, 1, 0, 0],
[ 0, 0, 6, 14, 47, 11, 1, 0, 0],
[ 0, 0, 2, 5, 11, 31, 15, 1, 0],
[ 0, 0, 0, 1, 2, 5, 16, 2, 0],
[ 0, 0, 0, 0, 0, 1, 1, 2, 0],
[ 0, 0, 0, 0, 0, 0, 0, 1, 0]])
lista_acc = []
for i in range(2,150):
dt = DecisionTreeClassifier(max_depth=i)
dt.fit(X_train, y_train)
y_pred = dt.predict(X_test)
acc = accuracy_score(y_test, y_pred)
lista_acc.append(acc)
plt.plot(range(2,150), lista_acc)
[<matplotlib.lines.Line2D at 0x7f0c1c6455a0>]
# Mostrar la matríz de confusión
cmap = sns.diverging_palette(200, 100, as_cmap=True)
sns.heatmap(cmatrix_tc, annot=True, cmap=cmap, fmt='d', cbar=False)
plt.xlabel('Predicted')
plt.ylabel('True')
# Calcular la exactitud (accuracy)
from sklearn.metrics import accuracy_score
acc = accuracy_score(y_test, y_pred)
print('Exactitud: ', f'{acc:.2%}')
Exactitud: 48.94%
# Same but with a random forest
from sklearn.ensemble import RandomForestClassifier
rf = RandomForestClassifier(max_depth=3)
rf.fit(X_train, y_train)
y_pred = rf.predict(X_test)
cmatrix_rf = confusion_matrix(y_test, y_pred)
# Mostrar la matríz de confusión
sns.heatmap(cmatrix_rf, annot=True, cmap=cmap, fmt='d', cbar=False)
plt.xlabel('Predicted')
plt.ylabel('True')
Text(46.25, 0.5, 'True')
El gráfico se vería de la siguiente forma:
Tomado de: Stack Overflow.
En este punto, los diagramas se vuelven muy complejos por lo que no siempre es una buena idea graficarlos.
5.4.5 Forecast con series de tiempo#
Las series de tiempo son un tipo de datos que se caracterizan por tener una secuencia de datos ordenados en el tiempo. Por ejemplo, el precio de una acción, la cantidad de ventas de un producto, la cantidad de visitas a un sitio web, etc.
En ocasiones, es posible predecir el futuro de una serie de tiempo utilizando sus valores en el pasado. A éste proceso se lo conoce como time series forecast.
Es un modelo de regresión porque busca predecir un valor numérico (variable continua). Se puede expresar aproximadamente de la siguiente forma:
air = pd.read_csv('https://raw.githubusercontent.com/alejo-acosta/pmdb-material/master/data/AirPassengers.csv').rename(columns={'#Passengers':'passengers', 'Month':'month'})
air['month'] = pd.to_datetime(air['month'])
air.set_index('month', inplace=True)
air.interpolate(method='linear', inplace=True)
air.plot()
plt.show()
Hay muchas maneras de realizar un time series forecast. Una de las más simples es utilizando el método de promedio móvil. El método de promedio móvil es un método que busca predecir el valor de una serie de tiempo utilizando el promedio de los valores anteriores. Por ejemplo, si queremos predecir el valor de una serie de tiempo en el tiempo \(t+1\), podemos utilizar el promedio de los valores de la serie de tiempo en los tiempos \(t\), \(t-1\) y \(t-2\).
# moving average of passengers
air.plot()
air['passengers'].rolling(12).mean().plot()
plt.show()
Éste acercamiento tiene sus limitaciones, ya que no toma en cuenta la tendencia de la serie de tiempo. Por ejemplo, si la serie de tiempo tiene una tendencia creciente, el método de promedio móvil no va a tomar en cuenta ésta tendencia.
Otra forma es usar un modelo autoregresivo. Un modelo autoregresivo es un modelo que busca predecir el valor de una serie de tiempo utilizando los valores anteriores de la misma serie de tiempo. Por ejemplo, si queremos predecir el valor de una serie de tiempo en el tiempo \(t+1\), podemos utilizar los valores de la serie de tiempo en los tiempos \(t\), \(t-1\) y \(t-2\).
# sarima model on oil
from statsmodels.tsa.statespace.sarimax import SARIMAX
from statsmodels.tsa.seasonal import seasonal_decompose
decomposition = seasonal_decompose(air, model='additive', period=12)
decomposition.plot()
oil = pd.read_csv('https://raw.githubusercontent.com/alejo-acosta/curso-python-ciee/main/data/oil.csv')
oil['date'] = oil['date'].astype('datetime64[ns]')
oil.set_index('date', inplace=True)
oil.interpolate(method='linear', inplace=True)
oil.interpolate(method='bfill', inplace=True)
oil.plot()
<Axes: xlabel='date'>
decomposition = seasonal_decompose(oil, model='additive', period=12)
decomposition.plot()
# autoarima forecast
from pmdarima import auto_arima
model = auto_arima(air, m=12, seasonal=True, trace=True)
model.summary()
Performing stepwise search to minimize aic
ARIMA(2,1,2)(1,1,1)[12] : AIC=1020.048, Time=1.06 sec
ARIMA(0,1,0)(0,1,0)[12] : AIC=1031.508, Time=0.02 sec
ARIMA(1,1,0)(1,1,0)[12] : AIC=1020.393, Time=0.08 sec
ARIMA(0,1,1)(0,1,1)[12] : AIC=1021.003, Time=0.13 sec
ARIMA(2,1,2)(0,1,1)[12] : AIC=1019.935, Time=0.48 sec
ARIMA(2,1,2)(0,1,0)[12] : AIC=1019.290, Time=0.13 sec
ARIMA(2,1,2)(1,1,0)[12] : AIC=1019.546, Time=0.48 sec
ARIMA(1,1,2)(0,1,0)[12] : AIC=1024.160, Time=0.08 sec
ARIMA(2,1,1)(0,1,0)[12] : AIC=1017.847, Time=0.11 sec
ARIMA(2,1,1)(1,1,0)[12] : AIC=1017.914, Time=0.41 sec
ARIMA(2,1,1)(0,1,1)[12] : AIC=1018.359, Time=0.43 sec
ARIMA(2,1,1)(1,1,1)[12] : AIC=1018.248, Time=0.85 sec
ARIMA(1,1,1)(0,1,0)[12] : AIC=1022.393, Time=0.06 sec
ARIMA(2,1,0)(0,1,0)[12] : AIC=1022.393, Time=0.04 sec
ARIMA(3,1,1)(0,1,0)[12] : AIC=1019.084, Time=0.12 sec
ARIMA(1,1,0)(0,1,0)[12] : AIC=1020.393, Time=0.04 sec
ARIMA(3,1,0)(0,1,0)[12] : AIC=1023.666, Time=0.05 sec
ARIMA(3,1,2)(0,1,0)[12] : AIC=1021.083, Time=0.19 sec
ARIMA(2,1,1)(0,1,0)[12] intercept : AIC=inf, Time=0.28 sec
Best model: ARIMA(2,1,1)(0,1,0)[12]
Total fit time: 5.066 seconds
Dep. Variable: | y | No. Observations: | 144 |
---|---|---|---|
Model: | SARIMAX(2, 1, 1)x(0, 1, [], 12) | Log Likelihood | -504.923 |
Date: | Thu, 25 Jan 2024 | AIC | 1017.847 |
Time: | 19:45:36 | BIC | 1029.348 |
Sample: | 01-01-1949 | HQIC | 1022.520 |
- 12-01-1960 | |||
Covariance Type: | opg |
coef | std err | z | P>|z| | [0.025 | 0.975] | |
---|---|---|---|---|---|---|
ar.L1 | 0.5960 | 0.085 | 6.987 | 0.000 | 0.429 | 0.763 |
ar.L2 | 0.2143 | 0.091 | 2.343 | 0.019 | 0.035 | 0.394 |
ma.L1 | -0.9819 | 0.038 | -25.601 | 0.000 | -1.057 | -0.907 |
sigma2 | 129.3133 | 14.556 | 8.884 | 0.000 | 100.783 | 157.844 |
Ljung-Box (L1) (Q): | 0.00 | Jarque-Bera (JB): | 7.68 |
---|---|---|---|
Prob(Q): | 0.98 | Prob(JB): | 0.02 |
Heteroskedasticity (H): | 2.33 | Skew: | -0.01 |
Prob(H) (two-sided): | 0.01 | Kurtosis: | 4.19 |
Warnings:
[1] Covariance matrix calculated using the outer product of gradients (complex-step).
forecast, ci = model.predict(n_periods=60, return_conf_int=True)
forecast = pd.DataFrame(forecast, columns=['forecast'])
ci = pd.DataFrame(ci, columns=['lower', 'upper'])
ci.index = forecast.index
df_plot = pd.concat([air, forecast, ci], axis=1)
fig, ax = plt.subplots(figsize=(12, 5), dpi=150)
df_plot[['passengers', 'forecast']].plot(ax=ax)
plt.fill_between(df_plot.index, df_plot['lower'], df_plot['upper'], alpha=0.3, color='grey')
plt.show()
5.5. Aprendizaje no supervisado#
El aprendizaje no supervisado es aquel que utiliza datos no etiquetados para entrenar el modelo. En otras palabras, el modelo aprende a partir de casos en los cuales solo tenemos las variables independientes (x) pero no tenemos las variables (y).
5.5.1. Clústering#
El clustéring es un modelo que busca agrupar los datos en grupos (clústers) de acuerdo a su similitud. Por ejemplo, podemos tener un set de datos de viviendas y queremos agruparlas en grupos de acuerdo a sus características. De ésta forma, podemos tener un grupo de viviendas grandes, un grupo de viviendas pequeñas, un grupo de viviendas con piscina, etc.
Existen diversos algoritmos para clusterizar los datos, el más común es k-means.
k-means es un algoritmo que busca agrupar los datos en k grupos (clústers) de acuerdo a su similitud.
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
vars1 = ['GrLivArea', 'LotArea']
# remove atypical values form vars 1
df1 = df[vars1]
df1 = df1[(np.abs(stats.zscore(df1)) < 2).all(axis=1)]
df1 = df1.sample(frac=0.5, random_state=42)
# standardize
scaler = StandardScaler()
df1 = scaler.fit_transform(df1)
df1 = pd.DataFrame(df1, columns=vars1)
# kmeans
kmeans = KMeans(n_clusters=5)
kmeans.fit(df1)
df1['cluster'] = kmeans.predict(df1)
# plot
sns.scatterplot(x='GrLivArea', y='LotArea', data=df1, hue='cluster', palette='Set2')
plt.scatter(kmeans.cluster_centers_[:,0], kmeans.cluster_centers_[:,1], marker='x', s=100, c='r')
plt.show()
inertia = []
for i in range(1, 20):
kmeans = KMeans(n_clusters=i)
kmeans.fit(df1)
inertia.append(kmeans.inertia_)
plt.plot(range(1, 20), inertia)
plt.xticks(range(1, 20))
plt.show()
# summary of clusters
X.groupby('cluster').mean().plot(kind='scatter', x='GrLivArea', y='SalePrice')
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
Cell In[51], line 2
1 # summary of clusters
----> 2 X.groupby('cluster').mean().plot(kind='scatter', x='GrLivArea', y='SalePrice')
File ~/.local/lib/python3.10/site-packages/pandas/core/frame.py:8402, in DataFrame.groupby(self, by, axis, level, as_index, sort, group_keys, squeeze, observed, dropna)
8399 raise TypeError("You have to supply one of 'by' and 'level'")
8400 axis = self._get_axis_number(axis)
-> 8402 return DataFrameGroupBy(
8403 obj=self,
8404 keys=by,
8405 axis=axis,
8406 level=level,
8407 as_index=as_index,
8408 sort=sort,
8409 group_keys=group_keys,
8410 squeeze=squeeze,
8411 observed=observed,
8412 dropna=dropna,
8413 )
File ~/.local/lib/python3.10/site-packages/pandas/core/groupby/groupby.py:965, in GroupBy.__init__(self, obj, keys, axis, level, grouper, exclusions, selection, as_index, sort, group_keys, squeeze, observed, mutated, dropna)
962 if grouper is None:
963 from pandas.core.groupby.grouper import get_grouper
--> 965 grouper, exclusions, obj = get_grouper(
966 obj,
967 keys,
968 axis=axis,
969 level=level,
970 sort=sort,
971 observed=observed,
972 mutated=self.mutated,
973 dropna=self.dropna,
974 )
976 self.obj = obj
977 self.axis = obj._get_axis_number(axis)
File ~/.local/lib/python3.10/site-packages/pandas/core/groupby/grouper.py:888, in get_grouper(obj, key, axis, level, sort, observed, mutated, validate, dropna)
886 in_axis, level, gpr = False, gpr, None
887 else:
--> 888 raise KeyError(gpr)
889 elif isinstance(gpr, Grouper) and gpr.key is not None:
890 # Add key to exclusions
891 exclusions.add(gpr.key)
KeyError: 'cluster'
5.4.2. Reducción dimensional#
La reducción dimensional es un modelo que busca reducir la cantidad de variables independientes (x) de un set de datos. Por ejemplo, podemos tener un set de datos de viviendas con 100 variables independientes (x) y queremos reducirlo a 10 variables independientes (x). De ésta forma, podemos reducir la complejidad del modelo y hacerlo más eficiente.
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
df.shape
(1420, 81)
df3.shape
(1420, 81)
x = df3.dropna().copy()
x.drop(['SalePrice'], axis=1, inplace=True)
cols = x.columns
scaler = StandardScaler()
x = scaler.fit_transform(x)
df3
Id | MSSubClass | MSZoning | LotFrontage | LotArea | Street | Alley | LotShape | LandContour | Utilities | ... | PoolArea | PoolQC | Fence | MiscFeature | MiscVal | MoSold | YrSold | SaleType | SaleCondition | SalePrice | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 60 | 3 | 65.0 | 8450 | 1 | 2 | 3 | 3 | 0 | ... | 0 | 2 | 4 | 4 | 0 | 2 | 2008 | 8 | 4 | 208500 |
1 | 2 | 20 | 3 | 80.0 | 9600 | 1 | 2 | 3 | 3 | 0 | ... | 0 | 2 | 4 | 4 | 0 | 5 | 2007 | 8 | 4 | 181500 |
2 | 3 | 60 | 3 | 68.0 | 11250 | 1 | 2 | 0 | 3 | 0 | ... | 0 | 2 | 4 | 4 | 0 | 9 | 2008 | 8 | 4 | 223500 |
3 | 4 | 70 | 3 | 60.0 | 9550 | 1 | 2 | 0 | 3 | 0 | ... | 0 | 2 | 4 | 4 | 0 | 2 | 2006 | 8 | 0 | 140000 |
4 | 5 | 60 | 3 | 84.0 | 14260 | 1 | 2 | 0 | 3 | 0 | ... | 0 | 2 | 4 | 4 | 0 | 12 | 2008 | 8 | 4 | 250000 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
1455 | 1456 | 60 | 3 | 62.0 | 7917 | 1 | 2 | 3 | 3 | 0 | ... | 0 | 2 | 4 | 4 | 0 | 8 | 2007 | 8 | 4 | 175000 |
1456 | 1457 | 20 | 3 | 85.0 | 13175 | 1 | 2 | 3 | 3 | 0 | ... | 0 | 2 | 2 | 4 | 0 | 2 | 2010 | 8 | 4 | 210000 |
1457 | 1458 | 70 | 3 | 66.0 | 9042 | 1 | 2 | 3 | 3 | 0 | ... | 0 | 2 | 0 | 2 | 2500 | 5 | 2010 | 8 | 4 | 266500 |
1458 | 1459 | 20 | 3 | 68.0 | 9717 | 1 | 2 | 3 | 3 | 0 | ... | 0 | 2 | 4 | 4 | 0 | 4 | 2010 | 8 | 4 | 142125 |
1459 | 1460 | 20 | 3 | 75.0 | 9937 | 1 | 2 | 3 | 3 | 0 | ... | 0 | 2 | 4 | 4 | 0 | 6 | 2008 | 8 | 4 | 147500 |
1420 rows × 81 columns
x = pd.DataFrame(x, columns=cols)
# modelo
from sklearn.decomposition import PCA
pca = PCA()
pca.fit(x)
PCA()In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
PCA()
# plot components
fig, ax = plt.subplots(figsize=(7, 7), dpi=200)
ax.scatter(pca.components_[0], pca.components_[1])
for i in range(len(x.columns)):
ax.annotate(x.columns[i], (pca.components_[0][i], pca.components_[1][i]), fontsize=5, color='black')
plt.show()
# more components and elbow method
pca = PCA(15)
pca.fit(x)
fig, ax = plt.subplots()
ax.plot(range(1, len(pca.explained_variance_ratio_)+1), pca.explained_variance_ratio_)
plt.xlabel('Component')
plt.ylabel('Explained variance ratio')
plt.xticks(range(1, len(pca.explained_variance_ratio_)+1))
plt.show()
df_pca = pd.DataFrame(pca.components_, columns=x.columns)
df_pca.T
0 | 1 | |
---|---|---|
Id | -0.007768 | 0.005235 |
MSSubClass | -0.007593 | 0.110742 |
MSZoning | -0.090735 | 0.012530 |
LotFrontage | 0.097947 | 0.013606 |
LotArea | 0.051548 | -0.016905 |
... | ... | ... |
MiscVal | -0.020495 | -0.005653 |
MoSold | 0.025686 | 0.035335 |
YrSold | -0.008703 | -0.026769 |
SaleType | -0.016246 | -0.002790 |
SaleCondition | 0.077129 | 0.024580 |
80 rows × 2 columns
precio = cantidad + calidad