AIC/BIC 模型选择实战:Python 3步实现线性回归与Lasso变量筛选
AIC/BIC 模型选择实战Python 3步实现线性回归与Lasso变量筛选在数据科学和机器学习领域模型选择是一个永恒的话题。面对同一个数据集我们往往可以构建无数个不同的模型但如何从中选出最优的那个这就是AIC赤池信息量准则和BIC贝叶斯信息准则要解决的问题。本文将带你用Python代码实战这两种信息准则从线性回归到Lasso变量筛选一步步掌握模型选择的精髓。1. 理解AIC与BIC不只是数学公式AIC和BIC看似是两个简单的数学公式但它们背后蕴含着深刻的统计思想。让我们先抛开复杂的推导从实际应用的角度来理解它们。**AICAkaike Information Criterion**的计算公式是AIC 2k - 2ln(L)其中k是模型参数数量L是似然函数值。简单来说AIC在评估模型时做了两件事奖励模型对数据的拟合程度通过-2ln(L)项拟合越好值越小惩罚模型的复杂度通过2k项参数越多惩罚越大**BICBayesian Information Criterion**则稍有不同BIC ln(n)k - 2ln(L)这里n是样本量。与AIC相比BIC对模型复杂度的惩罚更重当n≥8时ln(n)2因此BIC倾向于选择更简单的模型。提示在实际应用中我们不需要手动计算这些值Python的统计和机器学习库已经内置了相关功能。重要的是理解它们的比较逻辑——值越小模型相对越好。2. 线性回归中的AIC/BIC实战让我们从一个简单的线性回归例子开始看看如何在Python中计算和比较AIC/BIC值。2.1 准备数据与训练模型首先我们生成一些模拟数据并训练一个线性回归模型import numpy as np from sklearn.datasets import make_regression from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_squared_error # 生成回归数据集 X, y make_regression(n_samples100, n_features5, noise0.1, random_state42) # 训练线性回归模型 model LinearRegression() model.fit(X, y) # 计算预测值和MSE y_pred model.predict(X) mse mean_squared_error(y, y_pred) print(fMSE: {mse:.4f})2.2 计算AIC和BIC虽然scikit-learn没有直接提供AIC/BIC计算但我们可以根据公式实现def calculate_aic(n, mse, k): 计算AIC值 aic n * np.log(mse) 2 * k return aic def calculate_bic(n, mse, k): 计算BIC值 bic n * np.log(mse) k * np.log(n) return bic # 参数数量系数截距 n_features X.shape[1] k n_features 1 # 系数数量加截距项 n len(y) # 计算AIC和BIC aic calculate_aic(n, mse, k) bic calculate_bic(n, mse, k) print(fAIC: {aic:.2f}) print(fBIC: {bic:.2f})2.3 模型比较实战假设我们有几个不同的线性回归模型可能使用了不同的变量组合我们可以计算每个模型的AIC/BIC并进行比较。下面是一个比较三种模型的示例模型特征数量MSEAICBIC模型150.0098-120.34-107.22模型230.0102-123.56-113.45模型320.0115-118.72-111.63从这个比较可以看出虽然模型1的MSE最小但因为参数多AIC/BIC并不是最优模型2在AIC和BIC上都表现最好是平衡拟合与复杂度的最佳选择模型3虽然最简单但拟合损失太大注意在实际项目中我们通常会使用自动化方法如下面介绍的LassoLarsIC来进行这种比较而不是手动计算。3. Lasso回归中的变量筛选Lasso回归是一种自带变量选择功能的线性模型它通过L1正则化可以将某些系数压缩为零。结合AIC/BIC我们可以更智能地选择正则化强度参数α。3.1 使用LassoLarsIC自动选择αscikit-learn提供了LassoLarsIC类可以直接基于AIC或BIC选择最优αfrom sklearn.linear_model import LassoLarsIC import matplotlib.pyplot as plt # 添加一些噪声特征 rng np.random.RandomState(42) X_noisy np.c_[X, rng.randn(X.shape[0], 5)] # 原始5个特征5个噪声特征 # 基于AIC的Lasso model_aic LassoLarsIC(criterionaic, normalizeFalse) model_aic.fit(X_noisy, y) alpha_aic_ model_aic.alpha_ # 基于BIC的Lasso model_bic LassoLarsIC(criterionbic, normalizeFalse) model_bic.fit(X_noisy, y) alpha_bic_ model_bic.alpha_ print(fAIC选择的alpha: {alpha_aic_:.6f}) print(fBIC选择的alpha: {alpha_bic_:.6f})3.2 可视化AIC/BIC选择过程我们可以绘制AIC/BIC随α变化的曲线直观理解选择过程plt.figure() plt.plot(-np.log10(model_aic.alphas_), model_aic.criterion_, b, labelAIC) plt.axvline(-np.log10(alpha_aic_), colorb, linestyle--, labelfAIC选择的alpha: {alpha_aic_:.3f}) plt.plot(-np.log10(model_bic.alphas_), model_bic.criterion_, r, labelBIC) plt.axvline(-np.log10(alpha_bic_), colorr, linestyle--, labelfBIC选择的alpha: {alpha_bic_:.3f}) plt.xlabel(-log(alpha)) plt.ylabel(信息准则值) plt.title(Lasso模型选择AIC vs BIC) plt.legend() plt.show()3.3 结果解读与变量筛选让我们看看两种准则选择的模型有何不同# 获取非零系数的数量 coef_aic model_aic.coef_ coef_bic model_bic.coef_ print(AIC选择的模型) print(f非零系数数量{np.sum(coef_aic ! 0)}) print(f系数值{coef_aic}) print(\nBIC选择的模型) print(f非零系数数量{np.sum(coef_bic ! 0)}) print(f系数值{coef_bic})典型输出可能如下AIC选择的模型 非零系数数量4 系数值[78.2, 32.5, 0.0, 15.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] BIC选择的模型 非零系数数量2 系数值[75.4, 30.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]可以看到AIC选择了包含4个变量的模型BIC选择了更简单的只有2个变量的模型两种方法都成功过滤掉了我们添加的噪声特征4. 高级技巧与注意事项4.1 在小样本情况下的调整当样本量较小时AIC可能会倾向于选择过于复杂的模型。这时可以使用AIC的修正版本AICcdef calculate_aicc(n, mse, k): 计算小样本AICc aic n * np.log(mse) 2 * k aicc aic (2 * k * (k 1)) / (n - k - 1) return aicc4.2 与交叉验证的比较虽然AIC/BIC计算高效但在某些情况下交叉验证可能是更好的选择。下面是使用LassoCV的示例from sklearn.linear_model import LassoCV # 使用交叉验证选择alpha model_cv LassoCV(cv5, random_state42).fit(X_noisy, y) print(f交叉验证选择的alpha: {model_cv.alpha_:.6f}) print(f非零系数数量{np.sum(model_cv.coef_ ! 0)})4.3 不同场景下的选择建议场景推荐方法原因大样本量BICBIC在大样本下更倾向于选择真实模型小样本量AICc修正后的小样本AIC更可靠预测为主AICAIC更注重预测能力模型解释为主BICBIC会选择更简洁的模型计算资源充足交叉验证通常更稳健但计算成本高需要快速结果AIC/BIC计算效率高在实际项目中我通常会同时尝试多种方法比较它们的选择结果。如果不同方法一致选择了相同或相似的模型那么这个结果就更加可靠。