How rolling features improved my CMAPSS baseline

entry
tabular-ml
prognostics
A grouped split and a chosen 30-cycle smoothing window moved XGBoost past my local Ridge baseline. Published model scores remain unaudited context.
Author

Alvin Alias

Published

May 28, 2026

My XGBoost pipeline reaches 15.85 RMSE on NASA C-MAPSS FD001, compared with 17.47 for the Ridge baseline run inside the same project. A 2017 LSTM paper reports 16.14, but I have not audited preprocessing, split, capping, and scoring parity closely enough to call that a head-to-head win. This entry focuses on the comparison I can defend and the two design decisions behind it.

The problem, briefly

NASA’s C-MAPSS FD001 dataset simulates 100 turbofan engines running to failure, 20,631 training cycles in all, each cycle a row of 21 sensor readings: temperatures, pressures, shaft speeds, fuel flow. The task is remaining useful life: given an engine’s sensor history, predict how many cycles remain. You train on complete run-to-failure trajectories and predict on engines cut off at an arbitrary point, scored against the official held-back answers.

Seven of the 21 sensors barely move in FD001, so they carry nothing. That leaves 14 informative channels, and one convention worth knowing: remaining life is capped at 125 cycles, because a healthy engine’s sensors look identical whether it has 130 or 300 cycles left. Predicting “125 or more” is the honest ceiling.

Decision one: split by engine, never randomly

The most common way to get a flattering RUL number is a random train/validation split. Rows from the same engine land on both sides, the model memorizes each engine’s personal drift, and validation error collapses. It isn’t prediction, it’s recognition.

Every split in this project is grouped by engine: an engine’s entire trajectory is either training or validation, never both. The validation score got worse the day I did this, which is exactly the point. The number stopped lying.

If you take one thing from this entry: on any dataset where rows belong to units that degrade, group your splits by unit and expect the honest number to be uglier.

Decision two: choose a smoothing horizon, then test it

FD001 represents gradual degradation, so cycle-level sensor changes can be small relative to noise. I used 30-cycle rolling means and standard deviations to expose longer movement. Thirty was a chosen smoothing horizon, not a measured fouling cycle and not the result of a completed sensitivity study.

The window encodes a reasonable prior that degradation unfolds over multiple cycles. That can help a tabular model, but a proper follow-up should compare several horizons with the same grouped validation protocol. The direct project comparison is:

Model RMSE, project evaluation
Ridge regression, my baseline 17.47
XGBoost on rolling features, this project 15.85

Published deep-learning scores are useful literature context, not audited baselines for this table. Before comparing against the reported 16.14 LSTM result, I would need to reproduce its preprocessing, RUL cap, test construction, and metric calculation.

The model agrees with the thermodynamics

The top SHAP feature is often the 30-cycle mean of sensor 3, identified in the dataset metadata as HPC outlet total temperature. That association is compatible with a compressor-degradation story, but SHAP explains the model’s use of a feature, not the physical cause. It is a reason to investigate the relationship, not a thermodynamic validation.

What I’d redo

The prediction ships with a ±15 cycle band, and that band is a heuristic, labeled as such in the API schema itself. It is not a calibrated interval, and pretending otherwise would be worse than the crude band. The fix is known (conformal prediction or quantile regression) and it is the top of the V2 list, along with extending past FD001’s single operating condition, where this feature set would need regime clustering before any rolling statistics make sense.

Try it against the official answers

The live demo at turbofan.alvinalias.com does something I wish more ML demos did: one click loads a real engine from NASA’s held-back test set, the model commits to an estimate, and then the official answer prints next to it, error included. Some runs miss. That’s what 15.85 RMSE means, and watching it miss honestly tells you more about the model than any metric table. Code, notebooks, and the model card are in the repo.

Citation

BibTeX citation:
@online{alias2026,
  author = {Alias, Alvin},
  title = {How Rolling Features Improved My {CMAPSS} Baseline},
  date = {2026-05-28},
  url = {https://alvinalias.com/notes/posts/rolling-mean-vs-lstm.html},
  langid = {en}
}
For attribution, please cite this work as:
Alias, Alvin. 2026. “How Rolling Features Improved My CMAPSS Baseline.” May 28, 2026. https://alvinalias.com/notes/posts/rolling-mean-vs-lstm.html.