训练大型数据集模型时出现MemoryError的解决方法咨询
解决高维数据集训练Ridge回归的内存不足问题
核心问题分析
你的数据集属于宽数据集(1217个样本,123万+特征),内存爆炸的核心原因是OneHotEncoder(sparse=False)强制生成了稠密矩阵——1217×1230748的稠密矩阵仅float64格式就占用11.2GB,即使转float32仍需5.6GB,再加上交叉验证的多份数据副本、并行训练的额外内存占用,直接超出了内存上限。
实用解决方案
1. 改用稀疏矩阵(最有效、最直接)
OneHotEncoder默认生成稀疏矩阵(sparse=True),仅存储非零值,能大幅降低内存占用(类别特征的one-hot编码中非零值占比极低)。修改代码如下:
# 去掉sparse=False,使用默认的稀疏矩阵输出 encoder = make_column_transformer( (OneHotEncoder(handle_unknown='ignore'), ['remainder__ID_FINCA', 'remainder__ID_ZONA', 'remainder__ID_ESTACION', 'remainder__modeWinddirectiondiscrete', 'remainder__Phase']) )
同时注意:Ridge的部分求解器不支持稀疏矩阵,需在参数中过滤掉svd和cholesky:
parameters = { 'modelo__alpha': np.logspace(-4, 4, 9, endpoint=True), 'modelo__max_iter': [1000, 3000, 5000, 10000, 15000], 'modelo__solver': ['lsqr', 'sparse_cg', 'sag', 'saga'] # 仅保留支持稀疏矩阵的求解器 }
2. 特征降维(适配宽数据集)
由于特征数远大于样本数(123万 vs 1217),可以在预处理流程中加入降维步骤,用TruncatedSVD将高维特征压缩到低维(比如200-500维),大幅减少内存占用:
from sklearn.decomposition import TruncatedSVD # 修改预处理Pipeline,加入降维步骤 preprocessing = make_pipeline(drop, encoder, TruncatedSVD(n_components=500, random_state=0))
注:TruncatedSVD支持稀疏矩阵输入,可与稀疏矩阵方案兼容。
3. 优化交叉验证与并行配置
- 降低并行数:
n_jobs=4会复制4份数据集到内存,可改为n_jobs=1,以训练速度换取内存空间; - 减少交叉验证强度:将
RepeatedKFold(n_splits=5, n_repeats=5)改为n_repeats=2,减少训练轮次; - 缩减参数搜索次数:
n_iter=20改为n_iter=10,减少模型训练的总次数。
4. 增量训练(分块处理数据)
如果上述方法仍无法解决,可使用SGDRegressor替代Ridge——SGD支持增量训练(partial_fit),可以分块加载数据训练,等价于带L2正则的线性回归(即Ridge):
from sklearn.linear_model import SGDRegressor # 替换Ridge为SGDRegressor,配置参数模拟Ridge pipe = Pipeline([ ('preprocessing', preprocessing), ('modelo', SGDRegressor(loss='squared_error', penalty='l2', random_state=0)) ]) # 调整参数搜索范围(SGD的alpha与Ridge的alpha含义不同,需按1/n_samples缩放) parameters = { 'modelo__alpha': np.logspace(-7, 1, 9, endpoint=True), 'modelo__max_iter': [1000, 3000, 5000], 'modelo__learning_rate': ['constant', 'optimal', 'invscaling'] } # 示例:手动分块加载数据并增量训练 def chunk_generator(X, y, chunk_size=200): for i in range(0, len(X), chunk_size): yield X[i:i+chunk_size], y[i:i+chunk_size] for chunk_X, chunk_y in chunk_generator(X_Train, y_Train): pipe.named_steps['modelo'].partial_fit(chunk_X, chunk_y)
5. 进一步压缩数据类型
若已使用稀疏矩阵,还可尝试将特征矩阵的 dtype 设为float32(稀疏矩阵支持指定数据类型):
encoder = make_column_transformer( (OneHotEncoder(handle_unknown='ignore', dtype=np.float32), ['remainder__ID_FINCA', 'remainder__ID_ZONA', 'remainder__ID_ESTACION', 'remainder__modeWinddirectiondiscrete', 'remainder__Phase']) )
内容的提问来源于stack exchange,提问作者Pablo Moreira Garcia
相关产品推荐
相关产品推荐

