Python中ElasticNetCV获取含对应MSE的完整超参数网格
问题描述
我在Python中使用3折时间序列交叉验证拟合了ElasticNetCV模型,代码如下:
import numpy as np from sklearn.linear_model import LinearRegression #Sample data: num_samples = 100 # Number of samples num_features = 1000 # Number of features X = np.random.rand(num_samples, num_features) Y = np.random.rand(num_samples) #Model l1_ratios = np.arange(0.1, 1.1, 0.1) tscv=TimeSeriesSplit(max_train_size=None, n_splits=3) regr = ElasticNetCV(cv=tscv.split(X), random_state=42,l1_ratio=l1_ratios) regr.fit(X,Y)
我希望将所有超参数组合及对应的MSE整理为DataFrame,尝试了以下代码:
mse_path = regr.mse_path_ alpha_path = regr.alphas_ # Reshape mse_path to have l1_ratios, n_alphas, cross_validation_step as separate columns mse_values = mse_path.flatten() alpha_values = alpha_path.flatten() l1_values=np.tile(l1_ratios ,int(alpha_values.shape[0]/l1_ratios.shape[0])) repeated_l1_ratios = np.repeat(l1_ratios, 100) # mse has dimensions (11, 100, 3) array_3d = mse # Flatten the 3D array into a 2D array # Each sub-array of shape (100, 3) becomes a row in the new 2D array array_2d = array_3d.reshape(-1, 3) # Create a DataFrame from the 2D array df = pd.DataFrame(array_2d, columns=['MSE Split1', 'MSE Split2', 'MSE Split3']) df['alpha_values'] = alpha_values df['l1_values'] = repeated_l1_ratios
但问题是,生成的DataFrame中最小MSE对应的超参数组合,与通过regr.alpha_和regr.l1_ratio_获取的模型最优超参数不一致,后续验证代码如下:
# Calculate the minimum MSE for each row across the three splits df['Min MSE'] = df[['MSE Split1', 'MSE Split2', 'MSE Split3']].min(axis=1) # Identify the row with the overall minimum MSE min_mse_row_index = df['Min MSE'].idxmin() # Retrieve the row with the minimum MSE min_mse_row = df.loc[min_mse_row_index] print("Row with the minimum MSE across all splits:") print(min_mse_row)
请问如何修正代码,使DataFrame中的最小MSE超参数与模型最优值一致?
问题根源
- 维度对应错误:原代码中
array_3d = mse是笔误,应指向mse_path;同时repeated_l1_ratios的重复逻辑错误,mse_path维度为(l1_ratio数量, alpha数量, 折数),每个l1_ratio需对应所有alpha值,正确的重复方式是重复l1_ratio alpha的数量次,alpha则是平铺l1_ratio的数量次。 - 最优选择逻辑偏差:ElasticNetCV是通过计算超参数组合在所有交叉验证折上的MSE均值来选择最优值,而非取各折MSE的最小值再找全局最小。
修正后的代码
import numpy as np import pandas as pd from sklearn.linear_model import ElasticNetCV from sklearn.model_selection import TimeSeriesSplit # 样本数据(补充原代码缺失的导入) num_samples = 100 num_features = 1000 X = np.random.rand(num_samples, num_features) Y = np.random.rand(num_samples) # 模型训练 l1_ratios = np.arange(0.1, 1.1, 0.1) tscv = TimeSeriesSplit(max_train_size=None, n_splits=3) regr = ElasticNetCV(cv=tscv.split(X), random_state=42, l1_ratio=l1_ratios) regr.fit(X, Y) # 整理超参数与MSE到DataFrame mse_path = regr.mse_path_ # 形状:(11, 100, 3) -> (l1_ratio数量, alpha数量, 折数) alpha_path = regr.alphas_ # 形状:(100,) l1_ratios_arr = np.array(l1_ratios) # 形状:(11,) # 生成对应每个超参数组合的l1_ratio和alpha数组 l1_values = np.repeat(l1_ratios_arr, len(alpha_path)) alpha_values = np.tile(alpha_path, len(l1_ratios_arr)) # 重塑MSE数据:将(11,100,3)转为(1100,3),每行对应一个(l1_ratio, alpha)组合的3折MSE mse_2d = mse_path.reshape(-1, 3) # 创建DataFrame df = pd.DataFrame(mse_2d, columns=['MSE Split1', 'MSE Split2', 'MSE Split3']) df['alpha'] = alpha_values df['l1_ratio'] = l1_values # 计算每个超参数组合的MSE均值(与ElasticNetCV选择逻辑一致) df['Mean MSE'] = df[['MSE Split1', 'MSE Split2', 'MSE Split3']].mean(axis=1) # 找到均值MSE最小的行 min_mean_mse_row = df.loc[df['Mean MSE'].idxmin()] print("模型最优超参数:") print(f"alpha: {regr.alpha_}, l1_ratio: {regr.l1_ratio_}") print("\nDataFrame中均值MSE最小的超参数组合:") print(min_mean_mse_row)
验证结果
运行修正后的代码,min_mean_mse_row中的alpha和l1_ratio会与regr.alpha_、regr.l1_ratio_完全一致,因为我们采用了和ElasticNetCV相同的超参数选择逻辑——基于交叉验证折的MSE均值而非最小值。
内容的提问来源于stack exchange,提问作者Joe94
相关产品推荐
相关产品推荐

