FMEA risk prioritization + survival analysis (Kaplan-Meier + Weibull MLE on right-censored data) + a scikit-learn failure-probability classifier.
Two different, complementary questions about materials failure:
- Which failure modes matter most? — FMEA (Failure Mode and Effects Analysis): Severity x Occurrence x Detection = RPN, the standard materials/automotive-engineering risk-prioritization framework.
- When will it fail, and can I predict it from conditions? — probabilistic reliability statistics. Some units in any real study haven't failed yet by the end of observation (right-censored) — treating them as failures at their last-seen time, or dropping them, both bias the estimate. Kaplan-Meier and Weibull MLE handle censoring correctly.
Complements polymer-degradation-simulator: that tool is deterministic physics (Arrhenius extrapolation of one property for one material from accelerated-aging curves). This one is probabilistic reliability statistics across a population of units with mixed failed/still-surviving outcomes — a different toolkit for a different question.
FMEA register: generic, textbook materials-failure modes (coating cracking, adhesion loss, corrosion under coating, delamination, chalking, filler settling) — not tied to any real material system, editable in the app.
Lifetime dataset (generate_synthetic_data.py): 250 synthetic units
with a known Weibull ground truth (β=2.5, η=500 at the class-A/
zero-exposure baseline), right-censored at a 600-unit study duration.
Covariates (material_class, exposure_severity) carry a real, modest
effect on true lifetime — the classifier has genuine signal to learn, not
noise dressed up as a demo. Generic category labels, no real material tie.
- Kaplan-Meier (
survival.kaplan_meier) — non-parametric survival estimator, implemented directly (no external survival-analysis library) - Weibull MLE (
survival.fit_weibull) —scipy.optimizemaximum likelihood fit with the correct censored-data log-likelihood (failures contribute the density, censored units contribute the survival function) - Classifier (
classifier.train_classifier) —RandomForestClassifierpredicting failure-by-threshold-T from covariates, benchmarked against aDummyClassifiermajority-class baseline (never report a bare accuracy number without a naive-baseline comparison)
Censoring-aware labeling: a unit only gets a definite classification label if its outcome relative to threshold T is actually known — failed by T (label 1), or survived to/past T (label 0, whether observed or censored). A unit censored before T is genuinely ambiguous (would it have failed by T? unknown) and is dropped rather than guessed — documented explicitly as a simplification versus full survival-ML.
tests/test_survival.py's core check: a clean (single population,
no covariates), large-sample synthetic Weibull dataset with a known
(β, η) must be recovered by the MLE fit within tight tolerance — the same
ground-truth-recovery honesty pattern used across this portfolio. The
bundled multi-class demo dataset is not used for that exact-recovery
test (it deliberately mixes populations, so a pooled fit won't match any
single class's baseline — the app says so explicitly rather than
presenting a misleading "recovery").
pip install -r requirements.txt
python generate_synthetic_data.py # writes sample_data/synthetic_lifetime_data.csv (already bundled)
pytest tests/ # 13 tests: FMEA, survival, classifier
streamlit run app.pyfmea_materials_forecaster/
├── fmea.py # RPN calculation, risk tiers, default register
├── survival.py # Kaplan-Meier + Weibull MLE (censoring-aware)
├── classifier.py # scikit-learn failure-probability classifier
├── generate_synthetic_data.py # builds the synthetic censored lifetime dataset
├── app.py # Streamlit UI — 2 tabs
├── tests/ # test_fmea.py, test_survival.py, test_classifier.py
└── sample_data/synthetic_lifetime_data.csv