Two-stage stacking where Ridge regression on OHE+scaled features produces OOF predictions fed as an extra feature to XGBoost, letting the tree model correct non-linear residuals on top of captured linear patterns.
Scanned 9/12/2026
Install to Claude Code
npx -y skills add wenmin-wu/ds-skills --skill ridge-xgb-stacking --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Ridge Xgb Stacking?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/wenmin-wu-ridge-xgb-stacking)More formats (shields.io, HTML) on the badges page.
---
name: tabular-ridge-xgb-stacking
description: >
Two-stage stacking where Ridge regression on OHE+scaled features produces OOF predictions fed as an extra feature to XGBoost, letting the tree model correct non-linear residuals on top of captured linear patterns.
---
# Ridge-XGBoost Stacking
## Overview
Stage 1 fits a Ridge regression on one-hot encoded, scaled features to cheaply capture linear relationships. Its out-of-fold (OOF) predictions become an additional feature for Stage 2, where XGBoost trains on all original features plus the Ridge OOF column. XGBoost focuses on correcting non-linear residuals rather than re-learning linear signals. Both stages share the same CV splits for consistency.
## Quick Start
```python
from sklearn.linear_model import Ridge
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.model_selection import StratifiedKFold
import xgboost as xgb
import numpy as np
kf = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
ridge_oof = np.zeros(len(X_train))
ridge_test = np.zeros(len(X_test))
# Stage 1: Ridge OOF
ohe = OneHotEncoder(sparse_output=False, handle_unknown='ignore')
X_ohe = ohe.fit_transform(X_train[cat_cols])
X_test_ohe = ohe.transform(X_test[cat_cols])
X_combined = np.hstack([StandardScaler().fit_transform(X_train[num_cols]), X_ohe])
for tr_idx, val_idx in kf.split(X_train, y_train):
scaler = StandardScaler()
X_tr = scaler.fit_transform(X_combined[tr_idx])
X_val = scaler.transform(X_combined[val_idx])
ridge = Ridge(alpha=10)
ridge.fit(X_tr, y_train.iloc[tr_idx])
ridge_oof[val_idx] = ridge.predict(X_val)
ridge_test += ridge.predict(scaler.transform(
np.hstack([StandardScaler().fit_transform(X_test[num_cols]), X_test_ohe])
)) / kf.n_splits
# Stage 2: XGBoost with ridge_oof feature
X_train['ridge_oof'] = ridge_oof
X_test['ridge_oof'] = ridge_test
xgb_model = xgb.XGBClassifier(n_estimators=1000, learning_rate=0.05,
max_depth=6, early_stopping_rounds=50)
# Train with same KFold splits...
```
## Workflow
1. Define a single `StratifiedKFold(n_splits=5)` shared across both stages
2. **Stage 1:** OneHotEncode categoricals, StandardScale all features, fit Ridge(alpha=10)
3. Collect OOF predictions for train, averaged predictions for test
4. **Stage 2:** Add `ridge_oof` column to original feature set
5. Train XGBoost on original features + ridge_oof using same folds
6. Final prediction comes from Stage 2 XGBoost
## Key Decisions
- **Ridge alpha=10:** moderate regularization prevents overfitting on high-cardinality OHE
- **Same CV splits:** ensures Ridge OOF values are truly out-of-fold for XGBoost training rows
- **Why not just blend?** Stacking as a feature lets XGBoost learn *when* to trust the linear model vs. override it, unlike a fixed-weight blend
- **OHE for Ridge only:** trees handle categoricals natively; Ridge needs explicit encoding
## References
- Source: "S6E3 Ridge XGB N-gram 0.91927 CV" (Kaggle Playground Series S6E3)
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!