特征工程易致内存溢出,因全量驻留、高基数one-hot、笛卡尔积爆炸及transformer冗余拷贝;应启用稀疏表示、限制交叉规模、分批拟合与实时内存监控。

因为特征工程常触发全量驻留:一次性读取原始数据、展开稀疏编码、生成笛卡尔组合、复制中间DataFrame,这些操作默认把所有结果塞进内存,而Python不自动流式处理。
为什么pandas.get_dummies会吃光内存
它默认返回完整DataFrame,对10万行×100列分类字段做one-hot,可能生成千万级列,每列都是int8但叠加后远超物理内存。更危险的是,若输入含未预见的高基数类别(如用户ID),get_dummies会为每个唯一值建一列,且不提供截断或哈希选项。
- 避免直接传整个DataFrame:
get_dummies(df[['cat_col']], sparse=True)启用稀疏矩阵(但注意后续运算兼容性) - 改用
sklearn.preprocessing.OneHotEncoder(handle_unknown='ignore', sparse_output=True),它支持fit_transform分批拟合,且输出是scipy.sparse.csr_matrix - 高基数场景强制降维:先用
value_counts()统计频次,只对top-k类别做dummy,其余归为"other"
为什么特征交叉(如pd.merge或itertools.product)突然OOM
笛卡尔积本质是行数相乘。两个各10万行的表交叉,结果100亿行——哪怕每行仅10字节,也要93 GB内存。pandas不检查维度爆炸,merge或product直接开干。
- 永远显式限制交叉范围:用
df1.sample(n=5000)和df2.sample(n=5000)先试算规模 - 避免
itertools.product生成全量列表;改用生成器函数逐对计算并立即写入磁盘或数据库 - 用
pd.concat([df1, df2], axis=1)替代merge做简单横向拼接,跳过索引对齐开销
为什么FeatureUnion或ColumnTransformer在fit时卡死
它们内部会把整个输入X复制多份,分别喂给不同transformer。如果X是10 GB的DataFrame,三个transformer就可能申请30 GB临时内存,且不释放中间副本。
立即学习“Python免费学习笔记(深入)”;
- 确认每个子transformer是否真正需要全量数据:数值列标准化可
partial_fit,文本TF-IDF用HashingVectorizer跳过vocabulary构建 - 禁用冗余拷贝:
ColumnTransformer(transformers, remainder='passthrough', n_jobs=1),避免多进程引发的隐式复制 - 手动拆解流程:先对数值列
StandardScaler().fit_transform(numeric_df),再对文本列TfidfVectorizer(max_features=10000).fit_transform(text_series),最后scipy.sparse.hstack拼接
最易被忽略的是:特征工程代码常被当成“预处理一步”,没人监控内存增长。实际中,df.memory_usage(deep=True).sum()应该插在每步之后,而不仅是开头结尾;一旦某步增长超2倍,就必须切分或换稀疏表示——否则模型训练前就已失败。


















