跳至主要内容

Python 中的线性回归:预测建模全指南

学习如何使用 NumPy、statsmodels 和 scikit-learn 在 Python 中执行线性回归。
· 9分钟 阅读

使用 AI 探索

Python 拥有包括 NumPy、statsmodels 和 scikit-learn 在内的丰富生态,已经成为数据科学家的首选语言。它的易用性与灵活性,使其既适合理解线性回归的理论基础,也适合在真实场景中加以实现。

在本指南中,我将带您系统了解 Python 中的线性回归。我们将先定义什么是线性回归,以及它为何重要。接着深入其工作机制,探讨背后的方程与假设。您将学习如何使用多种 Python 库来执行线性回归:从用 NumPy 手动计算,到用 scikit-learn 流水线式实现。我们会涵盖简单与多元线性回归,并向您展示如何评估模型并提升其表现。

什么是线性回归?

线性回归是一种统计方法,用于建模因变量(目标)与一个或多个自变量(预测变量)之间的关系。其目标是找到能够最好描述这种关系的线性方程。

线性回归广泛用于预测建模、推断统计以及理解数据中的关系。其应用包括销售预测、风险评估,以及分析不同变量对目标结果的影响。

什么是简单线性回归?

对于简单线性回归,其形式是在二维空间中的一条直线;对于多元线性回归(有两个自变量),关系在三维空间中表现为一个平面;若自变量更多,方程描述的则是高维空间中的超平面。

让我们从一个简单线性回归模型开始,正如我所说,它只有一个预测变量。其表示为如下方程:

simple linear regression formula

其中:

  • y 为因变量,
  • x 为自变量,
  • B0 为截距,
  • B1 为自变量的系数(斜率),
  • 为误差项。

什么是多元线性回归?

与之相对,多元线性回归将这一概念扩展到包含多个预测变量:

multiple linear regression formula

其中:

  • 0 为截距,
  • x1、x2,...,xn 为预测变量,
  • 1、2,...,n 为与各预测变量对应的系数,
  • 为误差项。

线性回归的运行机制

要理解线性回归如何工作,我们来拆解其关键组成部分。

线性模型方程

上文我们已经看到了线性回归在单个与多个预测变量下的方程。但现在,让我谈谈这些方程的一个重要方面。

线性回归中的“线性”,指的是模型的函数形式,而不一定是数据的形状。具体而言,它意味着:

  1. 模型在参数上是线性的。也就是说,每个预测变量都乘以一个系数并相加。
  2. 因变量与预测变量之间的关系是可加的,即每个预测变量的变化对因变量的影响是一致的。
  3. 对参数不进行指数、变量间相乘或非线性变换。

普通最小二乘(OLS)方法

为确定最佳拟合直线,线性回归使用普通最小二乘(OLS)方法。OLS 会最小化误差平方和:

OLS 使误差平方和最小化:

这可确保模型对 B0 和 B1 给出尽可能好的估计。

线性回归的假设

要使线性回归产生可靠结果,需要满足一些假设:

  1. 线性性:自变量与因变量之间应为线性关系。
  2. 误差独立性:残差(误差)之间不应相关。
  3. 方差齐性(同方差性):各取值范围内残差的散布应保持一致。
  4. 残差正态性:残差应服从正态分布。

验证这些假设可确保我们的模型既可靠又有效。比如,若变量之间并非线性关系,模型的预测可能不准确。 如果存在异方差,置信区间可能会失真。

在 Python 中进行线性回归的多种方式

在 Python 中可以用不同方法实现线性回归。我将带您了解三种常见方式:用 NumPy 进行手动计算、用 statsmodels 进行详细统计建模、以及用 scikit-learn 进行简洁的机器学习实现。

手动计算方法(NumPy)

对于简单线性回归(一个预测变量),您可以使用NumPy手动计算回归参数。这首先需要计算自变量与因变量的均值。然后我们计算斜率(B0):

得到斜率后,我们可以确定截距(B1):

import numpy as np

# Sample data
x = np.array([1, 2, 3, 4, 5])
y = np.array([2, 4, 5, 4, 5])

# Compute means
x_mean = np.mean(x)
y_mean = np.mean(y)

# Compute slope (B1)
B1 = np.sum((x - x_mean) * (y - y_mean)) / np.sum((x - x_mean) ** 2)

# Compute intercept (B0)
B0 = y_mean - B1 * x_mean

print(f"Slope (B1): {B1}")
print(f"Intercept (B0): {B0}")

# Predicting values
y_pred = B0 + B1 * x
print("Predicted values:", y_pred)

如果您想简化流程,NumPy 还提供了内置函数 np.polyfit(),只需一行代码即可完成线性回归。

# Example of NumPy's polyfit
np.polyfit(x, y, 1)  # 1 stands for the degree of the polynomial (linear)

这种方法有助于理解简单线性回归背后的数学,但在大数据集上并不实用,数值精度较低,且不适用于多元回归问题。

使用统计库(statsmodels)

更高效的做法是使用statsmodels,这是一个提供统计模型与分析工具的库。

使用 Statsmodels 拟合普通最小二乘(OLS)模型的步骤:

  1. 准备数据:确保自变量的结构正确。

  2. 添加常数项:用于表示方程中的截距。

  3. 拟合模型:使用 statsmodels 的 OLS() 来估计回归参数。

  4. 分析结果:.summary() 函数提供详细的模型信息,包括系数、p 值和 R 方等。

import numpy as np
import statsmodels.api as sm

# Sample data
x = np.array([1, 2, 3, 4, 5])
y = np.array([2, 4, 5, 4, 5])

# Add constant for intercept term
X = sm.add_constant(x)

# Fit OLS model
model = sm.OLS(y, X).fit()

# Print summary
print(model.summary())

使用机器学习库(scikit-learn)

scikit-learn 因其简洁、可扩展且易与其他机器学习工具集成而被广泛使用。它通过 LinearRegression 类提供了一种简单高效的线性回归方法。

  1. 导入库并加载数据集。

  2. 重塑预测变量形状(若为单变量回归)。

  3. 创建模型实例,使用 LinearRegression()。

  4. 拟合模型至训练数据。

  5. 获取模型参数:.coeff_ 返回斜率,.intercept_ 返回截距。

import numpy as np
from sklearn.linear_model import LinearRegression

# Sample data
x = np.array([1, 2, 3, 4, 5]).reshape(-1, 1)  # Reshape for scikit-learn
y = np.array([2, 4, 5, 4, 5])

# Create model instance
model = LinearRegression()

# Fit the model
model.fit(x, y)

# Get model parameters
print(f"Slope (B1): {model.coef_[0]}")
print(f"Intercept (B0): {model.intercept_}")

# Predict values
y_pred = model.predict(x)
print("Predicted values:", y_pred)

其他重要方法

除了 NumPy、statsmodels 与 scikit-learn,还有多种 Python 库提供回归功能:

  • Pandas:适用于探索性数据分析和快速趋势建模。
  • SciPy:包含可用于回归分析的统计函数。
  • TensorFlow 与 PyTorch:虽以深度学习为主,也能有效处理线性回归任务。

每种方法都有其优势,取决于您的回归任务复杂度。

在 Python 中进行单变量或多变量的线性回归

线性回归既能处理简单关系,也能应对复杂关系。本节我们将探讨如何使用 Python 实现单一预测变量(简单)与多个预测变量(多元)的线性回归。

Python 中的简单线性回归

在 Python 中进行简单线性回归,我们遵循以下步骤:

步骤 1:计算相关系数

相关系数衡量 x 与 y 之间关系的强度。我们可用 NumPy 计算:

import numpy as np

# Sample data
x = np.array([1, 2, 3, 4, 5])  # Independent variable
y = np.array([2, 4, 5, 4, 5])  # Dependent variable

correlation = np.corrcoef(x, y)[0, 1]
print("Correlation:", correlation)

步骤 2:计算斜率与截距

斜率 B1 的计算如下:

beta_1 = correlation * (np.std(y) / np.std(x))

您可能注意到,这个公式看起来与之前那个略有不同——早先我们通过将 与 y 的偏差乘积求和,再除以 的偏差平方和来得到斜率。现在这种使用相关系数与标准差的方法,虽形式不同,但实则等价。通过对先前的方程进行变形,我们可以将斜率表示为 与 与 的标准差之比的乘积,从而在代数上与前式等价。

接下来是截距:

beta_0 = np.mean(y) - beta_1 * np.mean(x)

步骤 3:用计算得到的参数进行预测

有了系数后,我们可以得到预测值。

y_pred = beta_0 + beta_1 * x

依次走过这些步骤,有助于在使用 scikit-learn 等库之前,先理解其底层计算。

Python 中的多元线性回归

多元线性回归将简单线性回归的思想扩展到用多个自变量来建模因变量之间的关系。这样我们就能分析更加复杂的数据集,在这些数据集中,单一预测变量不足以解释因变量的变化。

在 Python 中执行多元线性回归时,我们通常使用矩阵代数来计算使残差平方和最小化的系数。一种常见的系数计算公式被称为正规方程(normal equation):

其中:

  • X 为自变量矩阵(包含一列全 1 以表示截距),
  • y 为因变量取值的向量。
  • XT 为矩阵 X 的转置。
  • (XTX)-1 为 XTX 的逆矩阵。

该方程给出了使误差平方和最小的最优系数取值。

下面是一个使用 Python 进行多元线性回归的示例,利用 NumPy 完成矩阵运算:

import numpy as np

# Sample data: two predictors and one dependent variable
X = np.array([[1, 1], [1, 2], [2, 2], [2, 3]])  # Independent variables
y = np.array([6, 8, 9, 11])  # Dependent variable

# Add a column of ones to include the intercept in the model
X = np.column_stack((np.ones(X.shape[0]), X))

# Calculate beta coefficients using the normal equation
beta = np.linalg.inv(X.T @ X) @ X.T @ y
print("Coefficients:", beta)

当预测变量彼此独立时,这种方法效果良好,但如果预测变量高度相关,矩阵求逆会变得不稳定。因此,像 scikit-learn 这样的库采用更为数值稳定的基于QR 分解的方法来计算回归系数。因此,尽管我们可以用正规方程计算系数,但当我们使用 scikitlearn 的 LinearRegression() 函数时,底层实际在进行 QR 分解。

处理多重共线性

现在正是提及多元线性回归中一个常见问题的好时机。多重共线性是指两个或多个自变量高度相关,导致难以区分它们各自的影响。这会使系数估计不稳定。为了检测并缓解多重共线性,您可以计算方差膨胀因子(VIF)。您也可以移除高度相关的变量,或使用如岭回归与套索回归等正则化技术。

Python 中的线性回归模型诊断与评估

在构建好线性回归模型之后,下一步是评估其表现,并验证其是否满足底层假设。这可确保预测的可靠性,并帮助您发现潜在改进点。

残差分析

残差分析是线性回归诊断的核心部分。它有助于检查线性回归的假设并识别任何违背之处。理想情况下,残差应在零附近随机散布、无明显模式。在这里,残差图与 Q-Q 图等可视化工具就派上用场了:

  1. 残差图: 将残差与预测值(或自变量)作散点图,有助于检查模型是否遗漏了某些关系。理想情况下,图中应呈随机分布、无清晰模式,表明模型较好地捕捉了线性关系。
  2. Q-Q 图(分位数-分位数图): Q-Q 图用于评估残差是否服从正态分布。为保证线性回归的有效性,残差应近似正态。若 Q-Q 图上点基本落在一条直线上,则表明正态性较好。

在 Python 中,我们可以使用 matplotlib、seaborn 和 statsmodels 等库轻松绘制这些图。

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import statsmodels.api as sm

# Sample data and linear regression model
X = np.array([[1, 1], [1, 2], [2, 2], [2, 3]])  # Independent variables
y = np.array([6, 8, 9, 11])  # Dependent variable

# Add an intercept term
X = sm.add_constant(X)

# Fit the linear regression model
model = sm.OLS(y, X).fit()

# Get the residuals
residuals = model.resid

# 1. Residual Plot
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1)
plt.scatter(model.fittedvalues, residuals)
plt.axhline(y=0, color='r', linestyle='--')
plt.xlabel('Fitted Values')
plt.ylabel('Residuals')
plt.title('Residual Plot')

# 2. Q-Q Plot
plt.subplot(1, 2, 2)
sm.qqplot(residuals, line ='45', ax=plt.gca())
plt.title('Q-Q Plot')

plt.tight_layout()
plt.show()

评估指标

除了可视化分析,定量指标对于评估线性回归模型对数据的拟合程度也至关重要。常见关键指标包括:

  1. R 方(R²): 表示因变量方差中有多少可以被自变量解释。R² 越接近 1,说明模型解释的方差比例越大;越接近 0,则说明拟合较差。
  2. 调整后的 R 方: 对 R² 进行基于预测变量数量的调整,便于比较不同预测变量数量的模型。
  3. 均方根误差(RMSE): 以因变量相同的单位衡量模型预测误差的平均幅度。RMSE 越低,预测性能越好。
  4. 平均绝对误差(MAE): 衡量预测误差的平均绝对值,与 RMSE 不同的是它对大误差的惩罚不那么重。由于单位与因变量一致,也更易解释。

这些指标可以通过 statsmodels 或 scikit-learn 在 Python 中轻松计算:

from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
import numpy as np

# Make predictions using the model
y_pred = model.predict(X)

# R-squared
r_squared = r2_score(y, y_pred)
print("R-squared:", r_squared)

# Adjusted R-squared (calculated manually)
n = len(y)  # number of data points
p = X.shape[1] - 1  # number of predictors (excluding intercept)
adj_r_squared = 1 - (1 - r_squared) * (n - 1) / (n - p - 1)
print("Adjusted R-squared:", adj_r_squared)

# RMSE
rmse = np.sqrt(mean_squared_error(y, y_pred))
print("Root Mean Squared Error (RMSE):", rmse)

# MAE
mae = mean_absolute_error(y, y_pred)
print("Mean Absolute Error (MAE):", mae)

通过评估这些指标,您可以了解模型的准确性、拟合优度,以及模型对新数据的泛化能力。

提升您的回归模型

在评估线性回归模型之后,下一步是探索提升其表现的方法。一种常见做法是进行特征变换,以应对非线性关系,帮助模型更好地捕捉数据中的潜在模式。

特征变换

请记住,在线性回归中,模型假设自变量(预测变量)与因变量之间是线性关系。然而,许多真实世界的数据集都包含非线性关系,简单线性模型可能难以很好拟合。通过应用对数或平方根等特征变换,有时可以改善模型表现。

对数变换

当某个特征表现出指数式增长或取值很大且为正时常用。例如,将高度偏态的收入数据(少数极高收入主导)进行变换,可使分布更接近正态。

import numpy as np
df['log_income'] = np.log(df['income'] + 1)  # +1 to avoid log(0)

平方根变换

适用于呈二次关系的特征。例如,表示计数(如网站访问次数)的特征,进行平方根变换可能会受益。

df['sqrt_visits'] = np.sqrt(df['visits'])

通过变换这些特征,您在帮助模型更好地捕捉先前被线性方法遗漏的关系。关键在于测试不同的变换并观察其对模型表现的影响。这并非一刀切的方法,需要经验性测试。

归一化与标准化

除特征变换外,理解归一化与标准化对回归模型的影响也很重要,尤其当您处理的特征具有不同单位或量纲时。归一化将特征缩放到某一范围(通常为 [0, 1])。标准化则将特征缩放为均值为 0、标准差为 1。

当您拥有多个预测变量时,对数据进行归一化或标准化有助于更有意义地解释系数。也就是说,它有助于展示每个预测变量相对于其他预测变量对因变量的贡献程度。当预测变量量纲不同,这一点尤其有用。

结语

要深入理解线性回归,需持续实践与探索。为加深认识,建议进一步学习如何处理多重共线性、异方差,以及岭回归与套索回归等正则化技术。强化对QR 分解与方差膨胀因子的理解,也能提升模型诊断能力。此外,理解归一化与标准化的差异,有助于做出更好的特征缩放决策。

Samuel Shaibu

作者

Samuel Shaibu

资深数据从业者与写作者,热衷于帮助有志于数据领域的专业人士成长与精进。

主题