线性回归的目标是找到一个线性函数,使得输入特征与输出目标之间的误差平方和最小。在Python中,最常用的实现方式是通过scikit-learn库的LinearRegression类。这个类基于最小二乘法,内部使用高效的线性代数求解器,适合大多数中小规模数据集。我们先从一个简单的例子开始:假设有一组房屋面积与价格的数据,我们希望训练一个模型,用面积预测价格。

使用scikit-learn训练线性回归模型通常只需要四步:导入模型、创建实例、调用fit方法、查看系数和截距。下面的代码演示了完整过程,数据是手动构造的模拟数据,实际项目中可以替换为CSV文件或数据库读取。
import numpy as np
from sklearn.linear_model import LinearRegression
# 模拟数据:面积(平方米)和价格(万元)
X = np.array([[30], [45], [60], [80], [100], [120], [150]])
y = np.array([80, 110, 145, 180, 220, 260, 320])
# 创建并训练模型
model = LinearRegression()
model.fit(X, y)
# 输出结果
print("斜率(每平方米价格):", model.coef_[0])
print("截距(基础价格):", model.intercept_)
# 预测新面积
new_area = np.array([[90]])
predicted_price = model.predict(new_area)
print(f"90平米的预测价格:{predicted_price[0]:.2f}万元")
线性回归的数学原理与损失函数
线性回归假设因变量y可以通过自变量x的线性组合来表示,即y = β₀ + β₁x₁ + β₂x₂ + ... + βₚxₚ + ε,其中β₀是截距,βᵢ是各特征的系数,ε是随机误差。训练模型的过程就是寻找一组β值,使得预测值与真实值之间的差异尽可能小。最常用的优化目标是均方误差(MSE),定义为所有样本预测误差平方和的平均值。
为什么使用平方误差而不是绝对误差?平方误差对较大的偏差惩罚更重,并且具有连续可导的数学性质,方便使用解析方法求解。对于线性回归,当特征矩阵满足一定条件时,可以直接通过正规方程β = (XᵀX)⁻¹Xᵀy得到闭式解。但scikit-learn的LinearRegression并不是直接用这个公式求逆,而是使用scipy中的最小二乘求解器,例如基于SVD分解的方法,这样在处理特征共线性时更加稳定。
理解损失函数有助于判断模型是否训练合理。如果训练集上的MSE很小但测试集上很大,说明模型过拟合;如果两者都很大,可能是欠拟合或特征选择不当。线性回归本身比较简单,不容易过拟合,但在特征数量接近样本数量时仍然可能出现问题。
scikit-learn与statsmodels的实现差异
scikit-learn的LinearRegression专注于预测,它提供了fit、predict、score等简洁接口,适合集成到机器学习流水线中。而statsmodels库则更偏向统计学分析,它的OLS(普通最小二乘)类在训练后会输出完整的统计检验结果,包括每个系数的标准误、t值、p值、置信区间以及R²、F统计量等。这些信息对于判断自变量是否显著、模型整体是否有效非常有用。
下面使用statsmodels对同样的数据进行建模,可以看出输出内容的差异。注意statsmodels要求显式添加截距项,通常使用add_constant函数。
import statsmodels.api as sm # 添加截距列 X_with_const = sm.add_constant(X) # 拟合OLS模型 ols_model = sm.OLS(y, X_with_const).fit() # 打印详细统计结果 print(ols_model.summary())
从summary输出中可以关注几个关键指标:R-squared越接近1说明拟合越好;coef列显示系数估计值;P>|t|列若小于0.05通常认为该变量显著;Durbin-Watson值用于检测残差自相关,接近2较为理想。对于需要向业务方解释模型含义的场景,statsmodels提供的统计推断非常有价值;而如果只是需要预测结果,scikit-learn更加轻量高效。
两个库也可以结合使用,例如先用scikit-learn进行特征工程和模型选择,再用statsmodels进行最终的系数显著性检验。需要注意的是,两者对输入数据格式的要求略有不同:scikit-learn的X通常是二维数组,即使只有一个特征也要写成(n_samples, 1);statsmodels在添加常数项前也要求同样的二维结构。
线性回归的假设检验与模型诊断
线性回归并不是一个随便套用的模型,它依赖于几个经典假设:线性关系、误差独立同分布、误差服从正态分布、特征之间不存在严重多重共线性。如果这些假设被违背,模型的解释性和预测能力都可能下降。实际操作中,我们可以通过残差图、Q-Q图、VIF(方差膨胀因子)等方法进行诊断。
残差图是将预测值与残差(真实值减预测值)绘制成散点图,如果残差围绕0随机分布且没有明显趋势,说明模型基本合理;如果出现漏斗形状,可能存在异方差;如果出现弯曲,说明线性假设不成立,需要考虑多项式特征或非线性模型。Q-Q图用来检验残差是否服从正态分布,点越接近直线越好。
多重共线性可以通过计算VIF来检测,VIF大于10通常认为存在严重共线性。解决共线性的方法包括删除相关性高的变量、使用岭回归或主成分分析。在Python中,可以使用statsmodels的variance_inflation_factor函数计算每个特征的VIF值。下面是一个简单的示例。
from statsmodels.stats.outliers_influence import variance_inflation_factor
import pandas as pd
# 假设df是包含多个特征的DataFrame
df = pd.DataFrame({
'面积': [30, 45, 60, 80, 100, 120, 150],
'房间数': [1, 1, 2, 2, 3, 3, 4],
'房龄': [10, 8, 5, 4, 2, 1, 0]
})
df_with_const = sm.add_constant(df)
vif_data = pd.DataFrame()
vif_data["特征"] = df_with_const.columns
vif_data["VIF"] = [variance_inflation_factor(df_with_const.values, i) for i in range(df_with_const.shape[1])]
print(vif_data)
当线性回归的假设不满足时,可以考虑对目标变量进行变换(如对数变换),或使用广义线性模型、稳健回归等方法。对于预测任务,有时即使假设不完全满足,只要预测误差在可接受范围内,线性回归仍然可以作为一个简单有效的基线模型。
实际应用中的常见问题与优化技巧
在实际项目中应用线性回归时,特征缩放是一个容易被忽略但影响较大的步骤。虽然最小二乘法理论上不受特征尺度影响,但当使用梯度下降类优化算法时,特征尺度差异过大会导致收敛缓慢。即使scikit-learn的LinearRegression使用解析解,缩放特征也有助于系数解释和正则化。如果使用带正则化的线性回归(如Ridge、Lasso),必须先对特征进行标准化,否则惩罚项会对量纲大的特征不公平。
特征工程对线性回归的效果提升明显。例如,对于非线性关系的数据,可以通过添加多项式特征(如x²、x³)来扩展线性模型的表达能力。scikit-learn的PolynomialFeatures可以自动生成这些组合特征,配合Pipeline可以避免数据泄漏。另外,类别变量需要经过独热编码或标签编码转换为数值形式,缺失值则需要通过填充或删除来处理。
模型评估方面,除了R²和MSE,还可以使用平均绝对误差(MAE)和均方根误差(RMSE),它们对误差的解读更直观。交叉验证能够更可靠地估计模型在新数据上的表现,scikit-learn的cross_val_score可以方便地实现。最后,不要忽视数据可视化,绘制预测值与真实值的散点图往往能发现模型偏差的规律。