Métricas de regresión: MAE, MSE, RMSE y R-squared
Calcule métricas de error sobre un resultado de regresión, comprenda la dependencia de escala de MAE/RMSE y utilice R-squared como medida estandarizada de la bondad del ajuste.
Métricas de regresión: MAE, MSE, RMSE y R-squared es una lección gratuita de Machine Learning Academy en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Machine Learning Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Machine Learning Academy incluye 4 lecciones en total.
Partes de esta lección aún no han sido traducidas y se muestran en inglés.
Why Regression Needs Different Metrics
Regression models predict continuous values — house prices, temperatures, sales volumes. Unlike classification, where a prediction is either correct or wrong, regression predictions are almost never exactly right. The question is: how far off is the prediction? Regression metrics quantify the difference between predicted values and actual values. Different metrics weight errors differently: some penalise large errors more than small ones, some are robust to outliers, and some are normalised to be interpretable as a fraction of variance explained. Choosing the right metric depends on the problem's error cost structure.
import numpy as np
y_true = np.array([100, 150, 200, 250, 300], dtype=float)
y_pred = np.array([110, 140, 210, 240, 320], dtype=float)
errors = y_pred - y_true
print('Actual: ', y_true)
print('Predicted:', y_pred)
print('Errors: ', errors) # Some positive, some negative
print('We need metrics that summarise these errors into a single number.')MAE: Mean Absolute Error
MAE = mean(|y_true - y_pred|). Mean Absolute Error computes the average of the absolute differences between predictions and actual values. It is in the same units as the target variable — a house price MAE of $15,000 means predictions are off by $15,000 on average. MAE treats all errors linearly: a prediction that is twice as wrong costs exactly twice as much. MAE is robust to outliers because it does not square errors. It is the recommended metric when the distribution of errors is roughly symmetric and outlier errors should not dominate the aggregate.
import numpy as np
from sklearn.metrics import mean_absolute_error
y_true = np.array([100, 150, 200, 250, 300], dtype=float)
y_pred = np.array([110, 140, 210, 240, 320], dtype=float)
# Manual calculation
mae_manual = np.mean(np.abs(y_true - y_pred))
print('Manual MAE:', mae_manual) # |10|+|10|+|10|+|10|+|20| / 5 = 12
# Sklearn
mae = mean_absolute_error(y_true, y_pred)
print('Sklearn MAE:', mae)
print(f'Interpretation: predictions are off by {mae:.1f} units on average')MSE: Mean Squared Error
MSE = mean((y_true - y_pred)^2). Mean Squared Error squares each error before averaging. This makes MSE sensitive to outliers: a single prediction with error 10 contributes 100 to MSE, while a prediction with error 1 contributes only 1 — outlier errors are amplified quadratically. MSE is the natural loss function for linear regression (minimising MSE gives the ordinary least squares solution). Its units are the square of the target variable (dollars^2 for house prices), making it less interpretable than MAE but mathematically convenient for optimisation.
import numpy as np
from sklearn.metrics import mean_squared_error
y_true = np.array([100, 150, 200, 250, 300], dtype=float)
y_pred = np.array([110, 140, 210, 240, 320], dtype=float)
# Squaring emphasises large errors
errors = y_true - y_pred
print('Squared errors:', errors**2) # 100, 100, 100, 100, 400
mse = mean_squared_error(y_true, y_pred)
print(f'MSE: {mse}') # 160.0
print(f'Units: (target units)^2 -- less interpretable than MAE')
print(f'The large error at last sample contributes 400/5=80 to MSE alone')RMSE: Root Mean Squared Error
RMSE = sqrt(MSE). Root Mean Squared Error brings MSE back to the original units of the target variable (dollars, not dollars^2) by taking the square root. It is the most widely reported regression metric because it is interpretable in the same units as the target while still penalising large errors more than small ones. An RMSE of $20,000 for house prices means the typical error magnitude is $20,000, though outlier errors are weighted more heavily than in MAE. RMSE is always >= MAE for the same predictions; the gap between them increases when outlier errors are present.
import numpy as np
from sklearn.metrics import mean_squared_error
y_true = np.array([100, 150, 200, 250, 300], dtype=float)
y_pred = np.array([110, 140, 210, 240, 320], dtype=float)
mse = mean_squared_error(y_true, y_pred)
rmse = np.sqrt(mse)
print(f'MSE: {mse:.2f} (units: target^2)')
print(f'RMSE: {rmse:.2f} (units: same as target)')
# RMSE always >= MAE
from sklearn.metrics import mean_absolute_error
mae = mean_absolute_error(y_true, y_pred)
print(f'MAE: {mae:.2f}')
print(f'MAE <= RMSE: {mae <= rmse}')MAE vs RMSE: When to Use Which
Choose MAE when: outliers are expected and you do not want them to dominate the metric; you want a metric that is easily interpretable as the average error; errors of different sizes are equally important proportionally. Choose RMSE when: large errors are much more costly than small ones (e.g., predicting power demand — being off by 10x is far more costly than being off by 1x); the loss function used in training is MSE and you want evaluation to match training; variance in predictions matters more than median error. In practice, always report both MAE and RMSE — if RMSE >> MAE, outlier errors dominate; if RMSE ≈ MAE, errors are uniformly distributed.
import numpy as np
from sklearn.metrics import mean_absolute_error, mean_squared_error
# Two prediction sets with same MAE but different RMSE
y_true = np.array([100.0, 200.0, 300.0, 400.0, 500.0])
# Set 1: uniform errors of 10
pred1 = y_true + 10
# Set 2: mostly 0 error, one huge error of 50
pred2 = y_true.copy()
pred2[-1] += 50
pred2[0:4] += 0
for name, pred in [('Uniform errors', pred1), ('One outlier error', pred2)]:
mae = mean_absolute_error(y_true, pred)
rmse = np.sqrt(mean_squared_error(y_true, pred))
print(f'{name}: MAE={mae:.2f}, RMSE={rmse:.2f}')R-Squared: Coefficient of Determination
R^2 = 1 - MSE(model) / Var(y_true). R-squared measures the fraction of variance in the target explained by the model. R^2 = 1.0 means perfect predictions (zero residual variance). R^2 = 0.0 means the model is no better than predicting the mean of y for every sample. R^2 can be negative if the model is worse than the mean baseline. R^2 is scale-independent — a value of 0.85 means the same thing whether the target is house prices or temperatures. This makes it the primary metric for comparing regression models across different problems or scales.
import numpy as np
from sklearn.metrics import r2_score
y_true = np.array([100, 150, 200, 250, 300], dtype=float)
y_pred = np.array([110, 140, 210, 240, 320], dtype=float)
y_mean = np.mean(y_true)
# Manual R^2
ss_res = np.sum((y_true - y_pred)**2) # Residual sum of squares
ss_tot = np.sum((y_true - y_mean)**2) # Total sum of squares
r2_manual = 1 - ss_res / ss_tot
print(f'SS_res (model): {ss_res}')
print(f'SS_tot (mean): {ss_tot}')
print(f'R^2 manual: {r2_manual:.4f}')
print(f'R^2 sklearn: {r2_score(y_true, y_pred):.4f}')Adjusted R-Squared: Penalising Extra Features
Adding more features to a regression model always increases R^2 (or keeps it the same) on training data — even if those features are random noise. Adjusted R^2 corrects for this by penalising the number of features: it decreases when you add a feature that does not improve the model enough to justify the additional complexity. Formula: Adj R^2 = 1 - (1 - R^2) * (n-1) / (n-p-1) where n = samples, p = features. Use adjusted R^2 when comparing models with different numbers of features to avoid selecting overly complex models.
import numpy as np
def adjusted_r2(y_true, y_pred, n_features):
n = len(y_true)
r2 = r2_score(y_true, y_pred)
return 1 - (1 - r2) * (n - 1) / (n - n_features - 1)
from sklearn.metrics import r2_score
from sklearn.linear_model import LinearRegression
import numpy as np
np.random.seed(42)
n = 100
X_2 = np.random.randn(n, 2)
X_10 = np.random.randn(n, 10) # 8 noise features added
y = X_2[:, 0] * 2 + X_2[:, 1] + np.random.randn(n) * 0.5
for X, p in [(X_2, 2), (X_10, 10)]:
pred = LinearRegression().fit(X, y).predict(X)
print(f'p={p}: R^2={r2_score(y,pred):.3f}, Adj R^2={adjusted_r2(y,pred,p):.3f}')MAPE: Mean Absolute Percentage Error
MAPE = 100 * mean(|y_true - y_pred| / |y_true|). Mean Absolute Percentage Error expresses the error as a percentage of the actual value, making it scale-independent and easily interpretable: a MAPE of 5% means predictions are off by 5% of the true value on average. Limitations: MAPE is undefined when actual values are zero (division by zero) and is asymmetric — underpredicting gives higher error than overpredicting by the same amount. Use MAPE for forecasting tasks (sales, demand) where stakeholders understand percentage deviations naturally.
import numpy as np
def mape(y_true, y_pred):
y_true = np.array(y_true, dtype=float)
# Avoid division by zero
mask = y_true != 0
return 100 * np.mean(np.abs((y_true[mask] - np.array(y_pred)[mask]) / y_true[mask]))
y_true = [100, 200, 300, 400, 500]
y_pred = [110, 190, 315, 380, 510]
print(f'MAPE: {mape(y_true, y_pred):.2f}%')
# Asymmetry example
print(f'Over by 50: MAPE = {mape([100],[150]):.1f}%')
print(f'Under by 50: MAPE = {mape([100],[50]):.1f}%')
# Underprediction by 50% gives 50% error; overprediction by 50% also 50% (same amount, asymmetric impact)Computing Regression Metrics with scikit-learn
Scikit-learn provides all major regression metrics in sklearn.metrics. When using cross_val_score, pass scoring='neg_mean_squared_error' (negative because higher is better by convention) and negate the result, or use 'neg_root_mean_squared_error' for direct RMSE. For R^2, use scoring='r2'. Always report multiple metrics: MAE for average absolute error, RMSE to show outlier sensitivity, and R^2 for explained variance. This gives a complete picture of model performance.
from sklearn.linear_model import LinearRegression
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import cross_val_score
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
import numpy as np
X, y = fetch_california_housing(return_X_y=True)
for metric in ['neg_mean_absolute_error', 'neg_root_mean_squared_error', 'r2']:
scores = cross_val_score(LinearRegression(), X, y, cv=5, scoring=metric)
mean_val = scores.mean()
if 'neg' in metric:
mean_val = -mean_val
print(f'{metric.replace("neg_",""):30}: {mean_val:.4f}')Residual Analysis: Diagnosing Model Quality
Beyond summary metrics, residual analysis reveals whether model assumptions are met. Plot residuals (y_true - y_pred) vs predicted values. A good model shows: (1) residuals randomly scattered around zero with no pattern (homoscedastic), (2) no relationship between residual magnitude and predicted value (no heteroscedasticity). Warning signs: a funnel shape (residuals increase with predicted value) suggests the model needs log-transformation; a curved pattern suggests the relationship is non-linear and the model is misspecified. Always do residual analysis before deploying any regression model.
import matplotlib.pyplot as plt
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
X, y = fetch_california_housing(return_X_y=True)
X_tr, X_te, y_tr, y_te = train_test_split(X, y, random_state=42)
model = LinearRegression()
model.fit(X_tr, y_tr)
y_pred = model.predict(X_te)
residuals = y_te - y_pred
plt.figure(figsize=(8, 4))
plt.scatter(y_pred, residuals, alpha=0.3, s=10)
plt.axhline(0, color='red', linestyle='--')
plt.xlabel('Predicted Value')
plt.ylabel('Residual (Actual - Predicted)')
plt.title('Residual Plot')
plt.show()Choosing the Right Regression Metric
A practical guide: use MAE when you want to minimise average absolute error and outliers should not be overemphasised — robust choice for general reporting. Use RMSE when your model minimises MSE during training and you want evaluation to match, or when large errors are particularly costly (demand forecasting, energy prediction). Use R^2 to compare models on the same dataset or explain model quality to non-technical stakeholders as 'percentage of variance explained'. Use MAPE for business forecasting where percentage deviations from actual values are the natural language of stakeholders.
# Metric selection guide
def recommend_metric(has_outliers, need_interpretable_units, compare_across_scales):
if compare_across_scales:
return 'R^2 (scale-independent, 0-1 range)'
elif need_interpretable_units and has_outliers:
return 'MAE (same units as target, robust to outliers)'
elif need_interpretable_units:
return 'RMSE (same units, penalises large errors more)'
else:
return 'MSE (convenient for optimisation, same loss as linear regression)'
print(recommend_metric(True, True, False)) # MAE
print(recommend_metric(False, True, False)) # RMSE
print(recommend_metric(False, False, True)) # R^2Quick Check
Test your understanding of Machine Learning with Python concepts from this lesson.
Lesson Recap
In this lesson you learned: MAE averages absolute errors and is robust to outliers, RMSE squares errors and penalises large deviations more heavily, R^2 measures the fraction of variance explained (0 = mean baseline, 1 = perfect), and the gap between MAE and RMSE reveals outlier error concentration. Next up we explore choosing the right metric for your specific business problem.
Preguntas frecuentes
¿La lección «Métricas de regresión: MAE, MSE, RMSE y R-squared» es gratis?
Sí — el texto completo de «Métricas de regresión: MAE, MSE, RMSE y R-squared» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Machine Learning Academy, actualiza a CoddyKit PRO. El curso de Machine Learning Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Métricas de regresión: MAE, MSE, RMSE y R-squared»?
Calcule métricas de error sobre un resultado de regresión, comprenda la dependencia de escala de MAE/RMSE y utilice R-squared como medida estandarizada de la bondad del ajuste. Practicas Machine Learning Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar Machine Learning Academy?
No se requiere experiencia previa. Machine Learning Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.
¿Cuánto tiempo toma la lección «Métricas de regresión: MAE, MSE, RMSE y R-squared»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de Machine Learning Academy?
Sí. Cada lección de Machine Learning Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Métricas de clasificación: accuracy, precision, recall y F1
- Curvas ROC y AUC-ROC
- Métricas de regresión: MAE, MSE, RMSE y R-squared
- Cómo elegir la métrica adecuada para su problema de negocio