如何实现MobileNetV2、DenseNet121、InceptionResNetV2的Stacking集成
Stacking集成CNN模型完整实现步骤
你原有直接用全量数据集训练所有基模型再生成元特征的逻辑会导致严重过拟合,必须用Out-of-Fold (OOF) 交叉验证方式生成元特征避免数据泄露,具体实现如下:
1 数据集拆分
首先把原始数据拆分为训练集和独立测试集,测试集仅用于最终效果评估,不参与任何模型训练:
from sklearn.model_selection import train_test_split import numpy as np # 拆分比例8:2,固定随机种子保证可复现 x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=42, stratify=y) # 把one-hot标签转成类别标签,方便后续元模型训练 y_train_label = np.argmax(y_train, axis=1) y_test_label = np.argmax(y_test, axis=1) # 匹配你原有每个模型的训练batch size batch_size_dict = { 'Mobile_V2': 10, 'Res_V2': 16, 'Dense_121': 16 }
2 生成基模型的OOF元训练特征
用K折交叉验证,对每个基模型在每一折的训练子集上训练,对验证子集做预测,所有验证集的预测结果拼接就是该基模型的元特征:
from sklearn.model_selection import KFold # 定义5折交叉验证 kf = KFold(n_splits=5, shuffle=True, random_state=42) n_models = len(estimators_model) # 元训练集特征形状:(训练集样本数, 模型数*类别数) 本次场景为(800,6) meta_train = np.zeros((x_train.shape[0], n_models * 2)) for model_idx, (model_name, model) in enumerate(estimators_model): print(f"处理基模型:{model_name}") for fold, (train_idx, val_idx) in enumerate(kf.split(x_train)): # 取当前折的训练和验证数据 x_tr, x_val = x_train[train_idx], x_train[val_idx] y_tr = y_train[train_idx] # 训练当前基模型,和你原有训练参数保持一致 model.compile(optimizer='adam',loss='categorical_crossentropy', metrics=['accuracy','AUC']) model.fit(x_tr, y_tr, epochs=10, batch_size=batch_size_dict[model_name], callbacks=[c1,c3], verbose=1) # 生成验证集预测结果,存入元训练集 val_pred = model.predict(x_val, verbose=0) meta_train[val_idx, model_idx*2 : (model_idx+1)*2] = val_pred
3 生成测试集的元特征
用训练完成的所有基模型分别对独立测试集做预测,结果拼接为元测试特征:
# 元测试集特征形状:(测试集样本数, 模型数*类别数) 本次场景为(200,6) meta_test = np.zeros((x_test.shape[0], n_models * 2)) for model_idx, (model_name, model) in enumerate(estimators_model): test_pred = model.predict(x_test, verbose=0) meta_test[:, model_idx*2 : (model_idx+1)*2] = test_pred
4 训练元模型并评估
选择简单模型作为元学习器即可避免过拟合,二分类场景推荐逻辑回归:
from sklearn.linear_model import LogisticRegression from sklearn.metrics import accuracy_score, roc_auc_score # 初始化元模型 meta_model = LogisticRegression(random_state=42) # 用元训练集训练元模型 meta_model.fit(meta_train, y_train_label) # 测试集预测 y_pred = meta_model.predict(meta_test) y_pred_proba = meta_model.predict_proba(meta_test)[:, 1] # 输出评估指标 print(f"集成模型准确率:{accuracy_score(y_test_label, y_pred):.4f}") print(f"集成模型AUC:{roc_auc_score(y_test_label, y_pred_proba):.4f}")
可选优化方向
- 元模型可替换为轻量全连接神经网络、XGBoost/LightGBM等树模型进一步提升效果
- 可将原始图像的低级特征与元特征拼接后喂给元模型,保留更多原始输入信息
- 数据量较小时可将5折交叉验证调整为10折,降低结果方差
内容的提问来源于stack exchange,提问作者Guilherme Moutinho
相关产品推荐
相关产品推荐

