Random Forest - MINE 8

Diana Jiménez

Gabriela Morera

Nicolás Romero

10-04-2025

1. Introducción

¿Por qué Random Forest?

Imagina que quieres predecir si un paciente tiene una enfermedad rara (clase minoritaria).
Si preguntas a un solo médico (árbol de decisión), podría equivocarse.
Pero si consultas a 100 médicos (bosque), cada uno especializado en aspectos distintos, y votan, la predicción será más precisa.

¿Cómo funciona Random Forest?

  • Combina cientos de árboles de decisión entrenados en partes aleatorias de los datos.
  • Cada árbol vota, y:
    • La mayoría gana (clasificación).
    • Se promedia el resultado (regresión).

2. Entendamos mejor como funciona

Analogía del Comité de Expertos

  1. Entrenamiento de “expertos”: Se entrenan muchos árboles con datos ligeramente distintos (muestreo con reemplazo).
  2. Predicción individual: Cada experto realiza su predicción.
  3. Decisión final: Se toma la decisión más votada.

¿Por qué funciona mejor?
Los errores individuales se compensan (como un promedio inteligente).

Aleatoriedad para Robustez

Dos fuentes de aleatoriedad:

  • Bagging: Cada árbol usa un subconjunto aleatorio de filas (muestreo con reemplazo).
  • Feature Randomness: En cada división del árbol, solo se consideran algunas características (ej: √n).

Resultado
Árboles diversos y menos correlacionados → Mayor generalización.

3. Matemáticas Clave (Sin Dolor)

¿Cómo decide un árbol dónde dividir?

Objetivo:
Encontrar la pregunta (umbral de una característica) que mejor separa las clases.

Métrica: Impureza de Gini (más intuitiva que la entropía)

\[ [ Gini = 1 - \sum_{i=1}^{C} (p_i)^2 ] \]

\[ Gini = 1 - (p_{\text{clase A}})^2 - (p_{\text{clase B}})^2 \]

Ejemplos:

  • Si un nodo tiene 50% de cada clase → Gini = 0.5 (máxima impureza).

  • Si un nodo tiene 100% de una clase → Gini = 0 (pureza perfecta).

Ejemplo práctico:

\[ Gini = 1 - (0.7)^2 - (0.3)^2 = \] \[ 1 - 0.49 - 0.09 = 0.42 ] \]

Ganancia de Información

Fórmula:
\[ \text{Ganancia} = Gini_{\text{padre}} - Gini_{\text{hijo}} \]

Interpretación:

  • Si la división reduce la impureza (Gini) → Ganancia alta.

  • El árbol elige la división con máxima ganancia.

4. Balanceo de Clases

El Problema del “Sesgo hacia la Mayoría”

Ejemplo:

  • 990 pacientes sanos vs. 10 enfermos.

  • Un modelo que siempre predice “sano” tendría 99% de precisión, pero sería inútil para detectar la enfermedad.

Soluciones

Opción 1: Pesos de Clases.

Asignar mayor penalización a errores en la clase minoritaria para mejorar el balanceo.

library(randomForest)
# Datos desbalanceados (ejemplo)
data <- data.frame(
  feature = rnorm(1000),
  class = factor(c(rep("sano", 990), rep("enfermo", 10)))
)

# Modelo con pesos
model_1 <- randomForest(
  class ~ .,
  data = data,
  classwt = c("sano" = 1, "enfermo" = 99)  # Peso inverso a la frecuencia
)

Opción 2: Submuestreo (Undersampling)

Entrenar cada árbol con un subconjunto balanceado de datos para evitar el sesgo hacia la mayoría.

model_2 <- randomForest(
  class ~ .,
  data = data,
  sampsize = c("enfermo" = 10, "sano" = 10),  # Mismo número de casos
  replace = TRUE  # Muestreo con reemplazo
)

print(model_1)
## 
## Call:
##  randomForest(formula = class ~ ., data = data, classwt = c(sano = 1,      enfermo = 99)) 
##                Type of random forest: classification
##                      Number of trees: 500
## No. of variables tried at each split: 1
## 
##         OOB estimate of  error rate: 2.2%
## Confusion matrix:
##         enfermo sano class.error
## enfermo       0   10  1.00000000
## sano         12  978  0.01212121

print(model_2)
## 
## Call:
##  randomForest(formula = class ~ ., data = data, sampsize = c(enfermo = 10,      sano = 10), replace = TRUE) 
##                Type of random forest: classification
##                      Number of trees: 500
## No. of variables tried at each split: 1
## 
##         OOB estimate of  error rate: 32.1%
## Confusion matrix:
##         enfermo sano class.error
## enfermo       6    4    0.400000
## sano        317  673    0.320202

library(caret)
confusionMatrix(predict(model_1, data), data$class)
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction enfermo sano
##    enfermo      10    0
##    sano          0  990
##                                      
##                Accuracy : 1          
##                  95% CI : (0.9963, 1)
##     No Information Rate : 0.99       
##     P-Value [Acc > NIR] : 4.317e-05  
##                                      
##                   Kappa : 1          
##                                      
##  Mcnemar's Test P-Value : NA         
##                                      
##             Sensitivity : 1.00       
##             Specificity : 1.00       
##          Pos Pred Value : 1.00       
##          Neg Pred Value : 1.00       
##              Prevalence : 0.01       
##          Detection Rate : 0.01       
##    Detection Prevalence : 0.01       
##       Balanced Accuracy : 1.00       
##                                      
##        'Positive' Class : enfermo    
## 

library(caret)
confusionMatrix(predict(model_2, data), data$class)
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction enfermo sano
##    enfermo      10  314
##    sano          0  676
##                                           
##                Accuracy : 0.686           
##                  95% CI : (0.6562, 0.7147)
##     No Information Rate : 0.99            
##     P-Value [Acc > NIR] : 1               
##                                           
##                   Kappa : 0.0413          
##                                           
##  Mcnemar's Test P-Value : <2e-16          
##                                           
##             Sensitivity : 1.00000         
##             Specificity : 0.68283         
##          Pos Pred Value : 0.03086         
##          Neg Pred Value : 1.00000         
##              Prevalence : 0.01000         
##          Detection Rate : 0.01000         
##    Detection Prevalence : 0.32400         
##       Balanced Accuracy : 0.84141         
##                                           
##        'Positive' Class : enfermo         
## 

5. Ejercicio Práctico

Usaremos los datos del Ames Housing son sacados de kaggle, en estos encontramos los precios de la vivienda en Estados Unidos

##      Order             PID             MS.SubClass      MS.Zoning        
##  Min.   :   1.0   Min.   :5.263e+08   Min.   : 20.00   Length:2930       
##  1st Qu.: 733.2   1st Qu.:5.285e+08   1st Qu.: 20.00   Class :character  
##  Median :1465.5   Median :5.355e+08   Median : 50.00   Mode  :character  
##  Mean   :1465.5   Mean   :7.145e+08   Mean   : 57.39                     
##  3rd Qu.:2197.8   3rd Qu.:9.072e+08   3rd Qu.: 70.00                     
##  Max.   :2930.0   Max.   :1.007e+09   Max.   :190.00                     
##                                                                          
##   Lot.Frontage       Lot.Area         Street             Alley          
##  Min.   : 21.00   Min.   :  1300   Length:2930        Length:2930       
##  1st Qu.: 58.00   1st Qu.:  7440   Class :character   Class :character  
##  Median : 68.00   Median :  9436   Mode  :character   Mode  :character  
##  Mean   : 69.22   Mean   : 10148                                        
##  3rd Qu.: 80.00   3rd Qu.: 11555                                        
##  Max.   :313.00   Max.   :215245                                        
##  NA's   :490                                                            
##   Lot.Shape         Land.Contour        Utilities          Lot.Config       
##  Length:2930        Length:2930        Length:2930        Length:2930       
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##                                                                             
##   Land.Slope        Neighborhood       Condition.1        Condition.2       
##  Length:2930        Length:2930        Length:2930        Length:2930       
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##                                                                             
##   Bldg.Type         House.Style         Overall.Qual     Overall.Cond  
##  Length:2930        Length:2930        Min.   : 1.000   Min.   :1.000  
##  Class :character   Class :character   1st Qu.: 5.000   1st Qu.:5.000  
##  Mode  :character   Mode  :character   Median : 6.000   Median :5.000  
##                                        Mean   : 6.095   Mean   :5.563  
##                                        3rd Qu.: 7.000   3rd Qu.:6.000  
##                                        Max.   :10.000   Max.   :9.000  
##                                                                        
##    Year.Built   Year.Remod.Add  Roof.Style         Roof.Matl        
##  Min.   :1872   Min.   :1950   Length:2930        Length:2930       
##  1st Qu.:1954   1st Qu.:1965   Class :character   Class :character  
##  Median :1973   Median :1993   Mode  :character   Mode  :character  
##  Mean   :1971   Mean   :1984                                        
##  3rd Qu.:2001   3rd Qu.:2004                                        
##  Max.   :2010   Max.   :2010                                        
##                                                                     
##  Exterior.1st       Exterior.2nd       Mas.Vnr.Type        Mas.Vnr.Area   
##  Length:2930        Length:2930        Length:2930        Min.   :   0.0  
##  Class :character   Class :character   Class :character   1st Qu.:   0.0  
##  Mode  :character   Mode  :character   Mode  :character   Median :   0.0  
##                                                           Mean   : 101.9  
##                                                           3rd Qu.: 164.0  
##                                                           Max.   :1600.0  
##                                                           NA's   :23      
##   Exter.Qual         Exter.Cond         Foundation         Bsmt.Qual        
##  Length:2930        Length:2930        Length:2930        Length:2930       
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##                                                                             
##   Bsmt.Cond         Bsmt.Exposure      BsmtFin.Type.1      BsmtFin.SF.1   
##  Length:2930        Length:2930        Length:2930        Min.   :   0.0  
##  Class :character   Class :character   Class :character   1st Qu.:   0.0  
##  Mode  :character   Mode  :character   Mode  :character   Median : 370.0  
##                                                           Mean   : 442.6  
##                                                           3rd Qu.: 734.0  
##                                                           Max.   :5644.0  
##                                                           NA's   :1       
##  BsmtFin.Type.2      BsmtFin.SF.2      Bsmt.Unf.SF     Total.Bsmt.SF 
##  Length:2930        Min.   :   0.00   Min.   :   0.0   Min.   :   0  
##  Class :character   1st Qu.:   0.00   1st Qu.: 219.0   1st Qu.: 793  
##  Mode  :character   Median :   0.00   Median : 466.0   Median : 990  
##                     Mean   :  49.72   Mean   : 559.3   Mean   :1052  
##                     3rd Qu.:   0.00   3rd Qu.: 802.0   3rd Qu.:1302  
##                     Max.   :1526.00   Max.   :2336.0   Max.   :6110  
##                     NA's   :1         NA's   :1        NA's   :1     
##    Heating           Heating.QC        Central.Air         Electrical       
##  Length:2930        Length:2930        Length:2930        Length:2930       
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##                                                                             
##   X1st.Flr.SF      X2nd.Flr.SF     Low.Qual.Fin.SF     Gr.Liv.Area  
##  Min.   : 334.0   Min.   :   0.0   Min.   :   0.000   Min.   : 334  
##  1st Qu.: 876.2   1st Qu.:   0.0   1st Qu.:   0.000   1st Qu.:1126  
##  Median :1084.0   Median :   0.0   Median :   0.000   Median :1442  
##  Mean   :1159.6   Mean   : 335.5   Mean   :   4.677   Mean   :1500  
##  3rd Qu.:1384.0   3rd Qu.: 703.8   3rd Qu.:   0.000   3rd Qu.:1743  
##  Max.   :5095.0   Max.   :2065.0   Max.   :1064.000   Max.   :5642  
##                                                                     
##  Bsmt.Full.Bath   Bsmt.Half.Bath      Full.Bath       Half.Bath     
##  Min.   :0.0000   Min.   :0.00000   Min.   :0.000   Min.   :0.0000  
##  1st Qu.:0.0000   1st Qu.:0.00000   1st Qu.:1.000   1st Qu.:0.0000  
##  Median :0.0000   Median :0.00000   Median :2.000   Median :0.0000  
##  Mean   :0.4314   Mean   :0.06113   Mean   :1.567   Mean   :0.3795  
##  3rd Qu.:1.0000   3rd Qu.:0.00000   3rd Qu.:2.000   3rd Qu.:1.0000  
##  Max.   :3.0000   Max.   :2.00000   Max.   :4.000   Max.   :2.0000  
##  NA's   :2        NA's   :2                                         
##  Bedroom.AbvGr   Kitchen.AbvGr   Kitchen.Qual       TotRms.AbvGrd   
##  Min.   :0.000   Min.   :0.000   Length:2930        Min.   : 2.000  
##  1st Qu.:2.000   1st Qu.:1.000   Class :character   1st Qu.: 5.000  
##  Median :3.000   Median :1.000   Mode  :character   Median : 6.000  
##  Mean   :2.854   Mean   :1.044                      Mean   : 6.443  
##  3rd Qu.:3.000   3rd Qu.:1.000                      3rd Qu.: 7.000  
##  Max.   :8.000   Max.   :3.000                      Max.   :15.000  
##                                                                     
##   Functional          Fireplaces     Fireplace.Qu       Garage.Type       
##  Length:2930        Min.   :0.0000   Length:2930        Length:2930       
##  Class :character   1st Qu.:0.0000   Class :character   Class :character  
##  Mode  :character   Median :1.0000   Mode  :character   Mode  :character  
##                     Mean   :0.5993                                        
##                     3rd Qu.:1.0000                                        
##                     Max.   :4.0000                                        
##                                                                           
##  Garage.Yr.Blt  Garage.Finish       Garage.Cars     Garage.Area    
##  Min.   :1895   Length:2930        Min.   :0.000   Min.   :   0.0  
##  1st Qu.:1960   Class :character   1st Qu.:1.000   1st Qu.: 320.0  
##  Median :1979   Mode  :character   Median :2.000   Median : 480.0  
##  Mean   :1978                      Mean   :1.767   Mean   : 472.8  
##  3rd Qu.:2002                      3rd Qu.:2.000   3rd Qu.: 576.0  
##  Max.   :2207                      Max.   :5.000   Max.   :1488.0  
##  NA's   :159                       NA's   :1       NA's   :1       
##  Garage.Qual        Garage.Cond        Paved.Drive         Wood.Deck.SF    
##  Length:2930        Length:2930        Length:2930        Min.   :   0.00  
##  Class :character   Class :character   Class :character   1st Qu.:   0.00  
##  Mode  :character   Mode  :character   Mode  :character   Median :   0.00  
##                                                           Mean   :  93.75  
##                                                           3rd Qu.: 168.00  
##                                                           Max.   :1424.00  
##                                                                            
##  Open.Porch.SF    Enclosed.Porch     X3Ssn.Porch       Screen.Porch
##  Min.   :  0.00   Min.   :   0.00   Min.   :  0.000   Min.   :  0  
##  1st Qu.:  0.00   1st Qu.:   0.00   1st Qu.:  0.000   1st Qu.:  0  
##  Median : 27.00   Median :   0.00   Median :  0.000   Median :  0  
##  Mean   : 47.53   Mean   :  23.01   Mean   :  2.592   Mean   : 16  
##  3rd Qu.: 70.00   3rd Qu.:   0.00   3rd Qu.:  0.000   3rd Qu.:  0  
##  Max.   :742.00   Max.   :1012.00   Max.   :508.000   Max.   :576  
##                                                                    
##    Pool.Area         Pool.QC             Fence           Misc.Feature      
##  Min.   :  0.000   Length:2930        Length:2930        Length:2930       
##  1st Qu.:  0.000   Class :character   Class :character   Class :character  
##  Median :  0.000   Mode  :character   Mode  :character   Mode  :character  
##  Mean   :  2.243                                                           
##  3rd Qu.:  0.000                                                           
##  Max.   :800.000                                                           
##                                                                            
##     Misc.Val           Mo.Sold          Yr.Sold      Sale.Type        
##  Min.   :    0.00   Min.   : 1.000   Min.   :2006   Length:2930       
##  1st Qu.:    0.00   1st Qu.: 4.000   1st Qu.:2007   Class :character  
##  Median :    0.00   Median : 6.000   Median :2008   Mode  :character  
##  Mean   :   50.63   Mean   : 6.216   Mean   :2008                     
##  3rd Qu.:    0.00   3rd Qu.: 8.000   3rd Qu.:2009                     
##  Max.   :17000.00   Max.   :12.000   Max.   :2010                     
##                                                                       
##  Sale.Condition       SalePrice     
##  Length:2930        Min.   : 12789  
##  Class :character   1st Qu.:129500  
##  Mode  :character   Median :160000  
##                     Mean   :180796  
##                     3rd Qu.:213500  
##                     Max.   :755000  
## 

Preprocesamiento

  • Eliminación de columnas irrelevantes:

Identificamos columnas que no aportan información predictiva. Eliminamos identificadores como “Order” y “PID”

  • Imputación de valores faltantes:

Variables numéricas: reemplazamos NA con la mediana Variables categóricas: reemplazamos NA con la moda

  • Eliminación de columnas sin variabilidad:

Eliminamos columnas categóricas con un solo nivel

# Limpieza y preprocesamiento de datos.
# La siguiente función calcula la moda de una variable categórica.
# Esto es útil para imputar valores faltantes en columnas categóricas.
Mode <- function(x) {
  ux <- unique(x)  # Obtiene valores únicos.
  ux[which.max(tabulate(match(x, ux)))]  # Retorna el valor más frecuente.
}

# Eliminar columnas irrelevantes.
irrelevant_cols <- c("Order", "PID")  # Identificamos columnas no útiles para el modelo.
ames_data <- ames_data %>%
  select(-any_of(irrelevant_cols))  # Excluimos estas columnas.

# Imputar valores faltantes para columnas numéricas y categóricas.
ames_data <- ames_data %>%
  mutate(across(where(is.numeric), ~ ifelse(is.na(.), median(., na.rm = TRUE), .))) %>%
  mutate(across(where(is.character), ~ ifelse(is.na(.), Mode(.), .)))
# Ahora, los datos están listos para el modelado.
Mode <- function(x) {
  ux <- unique(x)
  ux[which.max(tabulate(match(x, ux)))]
}

# Eliminar columnas irrelevantes solo si existen
irrelevant_cols <- c("Order", "PID")
ames_data <- ames_data %>%
  select(-any_of(irrelevant_cols))

# Imputar valores faltantes
ames_data <- ames_data %>%
  mutate(across(where(is.numeric), ~ ifelse(is.na(.), median(., na.rm = TRUE), .))) %>%
  mutate(across(where(is.character), ~ ifelse(is.na(.), Mode(.), .)))

# Eliminar columnas categóricas con un solo nivel
single_level_cols <- names(Filter(function(x) length(unique(x)) == 1, ames_data))
ames_data <- ames_data %>% select(-all_of(single_level_cols))

Preparación de Datos

  • Conversión a factores:

Las variables categóricas se convierten explícitamente a factores. Necesario para que R las trate correctamente

  • División de datos:

Separamos características (X) y precio de venta (y) 80% para entrenamiento, 20% para prueba. Usamos createDataPartition para una división estratificada

  • Manejo adicional de valores faltantes:

Eliminamos columnas con demasiados valores NA. Incluye “Alley”, “Fireplace.Qu”, “Pool.QC”, “Fence”, “Misc.Feature”

# Convertir variables categóricas a factores explícitamente
ames_data <- ames_data %>%
  mutate(across(where(is.character), as.factor))

# Separar características (X) y etiqueta objetivo (y)
X <- ames_data %>% select(-SalePrice)
y <- ames_data$SalePrice

# Dividir los datos en conjuntos de entrenamiento y prueba
set.seed(120224)
train_index <- createDataPartition(y, p = 0.8, list = FALSE)
train_data <- X[train_index, ]
test_data <- X[-train_index, ]
train_labels <- y[train_index]
test_labels <- y[-train_index]

# Eliminar columnas con demasiados valores NA en train_data y test_data
columns_to_remove <- c("Alley", "Fireplace.Qu", "Pool.QC", "Fence", "Misc.Feature")
train_data <- train_data %>% select(-all_of(columns_to_remove))
test_data <- test_data %>% select(-all_of(columns_to_remove))

Hiperparámetros en Random Forest

  • mtry: Número de variables consideradas en cada división.

Recomendación general: √p para regresión (donde p = número de predictores) Probamos valores: 2, 4, 6, 8

  • ntree: Número de árboles en el bosque.

Más árboles = mejor estabilidad, pero mayor costo computacional Probamos valores: 50, 100, 200

  • Búsqueda en grid:

Evaluamos todas las combinaciones posibles Seleccionamos la que maximiza la correlación entre predicciones y valores reales

library(randomForest)

# Manejo de valores faltantes
ames_data <- ames_data %>%
  mutate(across(where(is.numeric), ~ ifelse(is.na(.), median(., na.rm = TRUE), .))) %>%
  mutate(across(where(is.character), ~ ifelse(is.na(.), as.character(getmode(.)), .)))

ames_data <- ames_data %>% select(-c(Alley, Pool.QC, Fence, Misc.Feature))

ames_data <- ames_data[complete.cases(ames_data), ]

# Función auxiliar para calcular la moda
getmode <- function(v) {
  uniqv <- unique(v)
  uniqv[which.max(tabulate(match(v, uniqv)))]
}

# Dividir los datos en entrenamiento y prueba
set.seed(20241124)
train_indices <- sample(1:nrow(ames_data), 0.8 * nrow(ames_data))
train_data <- ames_data[train_indices, ]
test_data <- ames_data[-train_indices, ]

# Definir grid de hiperparámetros
rf_grid <- expand.grid(
  mtry = c(2, 4, 6, 8),
  ntree = c(50, 100, 200)
)

# Iterar sobre combinaciones
rf_results <- data.frame()
for (i in 1:nrow(rf_grid)) {
  set.seed(20241124)
  rf_model <- randomForest(
    SalePrice ~ .,
    data = train_data,
    mtry = rf_grid$mtry[i],
    ntree = rf_grid$ntree[i]
  )
  
  preds <- predict(rf_model, test_data)
  acc <- cor(preds, test_data$SalePrice, use = "complete.obs") # Calcular correlación
  rf_results <- rbind(rf_results, cbind(rf_grid[i, ], correlation = acc))
}

# Mejor combinación
best_rf_combination <- rf_results[which.max(rf_results$correlation), ]
print(best_rf_combination)
##   mtry ntree correlation
## 8    8   100   0.9256744

Interpretación del Mejor Modelo Random Forest para Precios de Viviendas

Análisis de Predicciones vs Valores Reales

  • Alta correlación positiva: El valor de correlación de 0.926 (aproximadamente 93%) indica que el modelo tiene un excelente poder predictivo. Esto significa que las predicciones del modelo Random Forest siguen muy de cerca los valores reales de los precios de las viviendas.

  • Número de variables por división (mtry=8): El modelo funciona mejor considerando 8 variables aleatorias en cada división de los árboles. Esto permite suficiente aleatoriedad para evitar sobreajuste mientras mantiene poder predictivo.

  • Número de árboles (ntree=100): Un bosque de 100 árboles es suficiente para este conjunto de datos. Añadir más árboles no mejoraría significativamente el rendimiento, lo que indica un buen equilibrio entre precisión y eficiencia computacional.

Interpretación del Modelo Random Forest para Precios de Viviendas

# Entrenar modelo con los mejores hiperparámetros
best_rf_model <- randomForest(
  SalePrice ~ .,
  data = train_data,
  mtry = best_rf_combination$mtry,
  ntree = best_rf_combination$ntree
)

# Predecir en conjunto de prueba
predictions <- predict(best_rf_model, test_data)

# Crear dataframe para visualización
results_df <- data.frame(
  Actual = test_data$SalePrice,
  Predicted = predictions
)

  • Ajuste general: En el gráfico de dispersión se observa que la mayoría de los puntos se agrupan cerca de la línea diagonal roja (línea de predicción perfecta), lo que confirma visualmente la alta correlación estadística.

  • Mejor rendimiento en el rango medio: El modelo predice con mayor precisión las viviendas de precio medio (entre $150,000 y $300,000), donde los puntos están más concentrados alrededor de la línea diagonal.

  • Ligera subpredicción en viviendas de alto valor: Para viviendas con precios reales superiores a $400,000, el modelo tiende a subestimar ligeramente el precio, como se observa por los puntos que aparecen por debajo de la línea diagonal en esa región.

  • Casos atípicos: Se observan algunos valores atípicos donde la predicción difiere considerablemente del valor real, especialmente en los extremos del rango de precios. Estos podrían representar propiedades con características únicas no capturadas adecuadamente por el modelo.

Muchas gracias