0Pricing
Machine Learning Academy · 课时

回归指标:MAE、MSE、RMSE 与 R 平方

您将计算回归输出的误差指标,理解 MAE/RMSE 对尺度的依赖,并使用 R 平方这一标准化拟合优度指标

回归指标:MAE、MSE、RMSE 与 R 平方 是 CoddyKit 上的免费 Machine Learning Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Machine Learning Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Machine Learning Academy 课程共包含 4 节课。

本课时的部分内容尚未翻译,以英文显示。

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^2

Quick 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.

常见问题解答

「回归指标:MAE、MSE、RMSE 与 R 平方」课时是免费的吗?

是的 — 「回归指标:MAE、MSE、RMSE 与 R 平方」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Machine Learning Academy 课程的其余内容,请升级到 CoddyKit PRO。 Machine Learning Academy 课程共包含 4 节课。

「回归指标:MAE、MSE、RMSE 与 R 平方」这节课中我会学到什么?

您将计算回归输出的误差指标,理解 MAE/RMSE 对尺度的依赖,并使用 R 平方这一标准化拟合优度指标 你通过在浏览器中直接运行的动手代码来练习 Machine Learning Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Machine Learning Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Machine Learning Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「回归指标:MAE、MSE、RMSE 与 R 平方」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Machine Learning Academy 课中编写并运行代码吗?

能。每节 Machine Learning Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 分类指标:准确率、精确率、召回率与 F1
  2. ROC 曲线与 AUC-ROC
  3. 回归指标:MAE、MSE、RMSE 与 R 平方
  4. 为业务问题选择合适的指标
← 返回 Machine Learning Academy