-
Notifications
You must be signed in to change notification settings - Fork 0
Output Structure
Every pipeline run writes under a single station directory:
{output_dir}/{network}.{station}.{location}.{channel}/ β station_dir
ββ "VG.OJN.00.EHZ" β nslc
output_dir defaults to os.getcwd() when not provided; pass root_dir=... to anchor relative paths under a chosen project root.
{station_dir}/
β
βββ tremor/ # CalculateTremor
β βββ daily/ # Per-day CSVs (removed when cleanup_daily_dir=True)
β βββ figures/ # Per-day band plots (plot_daily=True)
β βββ {nslc}_{start}_{end}.csv # Merged tremor CSV (DateTime index)
β
βββ training/ # TrainingModel
β βββ training.config.yaml # tm.save_config() β auto-written at end of fit()
β βββ features/{cv-slug}/
β β βββ features-matrix_{basename}.parquet # Full tsfresh feature matrix (Snappy Parquet)
β β βββ features-label_{basename}.csv # Aligned binary labels
β β βββ seed/{seed:05d}.csv # Top-N features per seed
β β βββ seed/figures/{seed:05d}.png # Per-seed importance plots (plot_features=True)
β β βββ resampled/{seed:05d}.csv # Per-seed (id + is_erupted) β features recovered via features_df.loc[ids]
β β βββ significant_features.csv # Raw per-seed rows concatenated (features + score = p-value / importance)
β β βββ top_features.csv # Full ranked list (features, frequency, score_mean, score_std, alias=ft_N, description)
β β βββ top_{N}_features.csv # Top-N subset of top_features.csv (same columns)
β β βββ top_{N}_features.png # Aggregated importance plot
β β βββ sweep/{mode}/{classifier-name}/ # β Experimental β FeatureCountSweep outputs (sweep_feature_count)
β β βββ cv_scores.csv # Aggregated summary (N, mean, std, n_seeds)
β β βββ cv_scores_raw.csv # Full (N Γγ°γ€ seed) score matrix
β β βββ seed_argmax_hist.csv # Per-seed argmax N
β β βββ support.json # {"n_features": N*, "seeds": {seed: [features...]}}
β β βββ curve.png # meanΒ±std curve + argmax histogram
β β βββ FeatureCountSweep.pkl # Full sweep instance (FeatureCountSweep.load(path))
β β
β βββ classifiers/
β βββ ClassifierEnsemble_{cv-slug}.pkl # Bundled ClassifierEnsemble (all classifiers)
β βββ ClassifierEnsemble_{cv-slug}.json # Registry of per-classifier paths
β βββ {clf-slug}/{cv-slug}/
β βββ models/{seed:05d}.pkl # One best_estimator_ per seed
β βββ trained-model__{suffix}.json # Per-classifier trained-model registry (records with inline top-N features)
β βββ SeedEnsemble_{suffix}.pkl # Single-classifier SeedEnsemble
β
βββ prediction/ # PredictionModel
β βββ prediction.config.yaml # pm.save_config() β auto-written at end of forecast()
β βββ features/
β β βββ features-label_{basename}_step-{N}-{unit}.csv # Forecast window grid
β β βββ features-matrix_*.parquet # tsfresh matrix for the grid (Snappy Parquet)
β βββ results/{clf-slug}/{seed:05d}.csv # Per-seed probability (save_seed_result=True)
β βββ figures/forecast_{basename}.{png,pdf} # Forecast plot
β
βββ evaluation/ # EvaluationModel
β βββ training/ # When model.kind == "training"
β β βββ evaluation.config.yaml # em.save_config() β auto-written at end of evaluate()
β β βββ classifiers/{ClassifierName}/
β β β βββ predictions/
β β β β βββ y_proba.csv # (n_samples, n_seeds) matrix
β β β β βββ y_pred.csv # (n_samples, n_seeds) matrix
β β β βββ figures/
β β β βββ aggregate/{plot_name}.{png,csv} # plot_aggregate=True
β β β βββ {plot_name}/{seed:05d}.png # plot_per_seed=True
β β βββ comparison/ # em.compare()
β β β βββ metrics/ranking_*.csv
β β β βββ figures/
β β βββ MetricsEnsemble.pkl # Optional, via me.save()
β βββ prediction/ # When model.kind == "prediction"
β βββ evaluation.config.yaml # em.save_config() β auto-written at end of evaluate()
β βββ labels/y_true.csv # Built by EvaluationModel.build_label()
β βββ classifiers/{ClassifierName}/... # Same shape as training/
β
βββ explanation/ # ExplanationModel
β βββ training/ # When upstream model.kind == "training"
β β βββ explanation.config.yaml # xm.save_config() β auto-written at end of explain()
β β βββ classifiers/{ClassifierName}/
β β β βββ ClassifierExplanation_{ClassifierName}.pkl # Bundled SHAP payload
β β β βββ shap_values/{seed:05d}.pkl # Per-seed shap.Explanation (save_per_seed=True)
β β β βββ figures/
β β β βββ bar/{seed:05d}.png # plot_per_seed=True
β β β βββ beeswarm/{seed:05d}.png # plot_per_seed=True
β β β βββ aggregate/ # plot_aggregate=True
β β β βββ bar.{png,csv} # frequency-weighted importance
β β β βββ beeswarm.{png,csv} # NaN-padded union beeswarm
β β βββ eruptions/{YYYY-MM-DD}/ # Per-eruption waterfall sibling
β β βββ {ClassifierName}_{datetime}_seed={i}_index={j}.png
β βββ prediction/ # When upstream model.kind == "prediction"
β βββ explanation.config.yaml # xm.save_config() β auto-written at end of explain()
β βββ (identical sub-tree)
β
β # Cache pickles for the three cache-using stages live next to each
β # stage's other outputs β no separate cache/ subtree:
β # training/{hash}.TrainingModel.pkl # Cached fitted TrainingModel
β # training/{hash}.TrainingModel.params.json # Sidecar identity dump
β # prediction/{hash}.PredictionModel.pkl # Cached PredictionModel
β # prediction/{hash}.PredictionModel.params.json
β # explanation/{kind}/{hash}.ExplanationModel.pkl # Cached ExplanationModel
β # explanation/{kind}/{hash}.ExplanationModel.params.json
β
βββ forecast.config.yaml # fm.save_config()
βββ forecast-results_{basename}.csv # PredictionModel.forecast() top-level dump
βββ TrainingModel_{basename}.pkl # Optional, via fm.TrainingModel.save()
βββ PredictionModel_{basename}.pkl # Optional, via fm.PredictionModel.save()
βββ EvaluationModel_{basename}.pkl # Optional, via fm.EvaluationModel.save()
βββ ExplanationModel_{basename}.pkl # Optional, via fm.ExplanationModel.save()
Where basename is typically {start_date}_{end_date} (training) or {start_date}_{end_date}_ws-{window_size} (prediction).
Folder slugs come from ClassifierModel.slug_name and ClassifierModel.slug_cv_name:
| Classifier key | Folder slug |
|---|---|
rf |
random-forest-classifier |
lite-rf |
lite-random-forest-classifier |
gb |
gradient-boosting-classifier |
xgb |
xgb-classifier |
svm |
svc |
lr |
logistic-regression |
nn |
mlp-classifier |
dt |
decision-tree-classifier |
knn |
k-neighbors-classifier |
nb |
gaussian-nb |
voting |
voting-classifier |
| CV strategy | Folder slug |
|---|---|
shuffle |
shuffle-split |
stratified |
stratified-k-fold |
shuffle-stratified |
stratified-shuffle-split |
timeseries (direct ClassifierModel only)
|
time-series-split |
Inside evaluation/ and explanation/, the per-classifier folder uses the unslugified sklearn class name (RandomForestClassifier) - separate from training's slug (random-forest-classifier).
The trained-model registry JSON and ensemble pickle share a single suffix scheme:
trained-model__{ClassifierName}_{CVName}_seeds-{N}_features-{K}.json
SeedEnsemble_{ClassifierName}_{CVName}_seeds-{N}_features-{K}.pkl
Example:
trained-model__RandomForestClassifier_StratifiedShuffleSplit_seeds-25_features-20.json
SeedEnsemble_RandomForestClassifier_StratifiedShuffleSplit_seeds-25_features-20.pkl
Each trained-model__*.json is a list of per-seed records:
[
{"random_state": 0, "features": ["f_0", "f_1", "..."], "model_filepath": ".../models/00000.pkl"},
{"random_state": 1, "features": ["..."], "model_filepath": ".../models/00001.pkl"}
]SeedEnsemble.from_json (or SeedEnsemble.from_any, which dispatches on extension) reads this file as the single source of truth for the seed bundle. The legacy .csv registry remains loadable via SeedEnsemble.from_registry so older training outputs still work.
The ClassifierEnsemble is named with the CV slug only (one ensemble holds every classifier):
ClassifierEnsemble_stratified-shuffle-split.pkl
ClassifierEnsemble_stratified-shuffle-split.json
Per-seed model files inside classifiers/{clf}/{cv}/models/ are zero-padded:
00000.pkl 00001.pkl ... 00024.pkl
BaseModel.save(identity) writes content-addressed artefacts directly into each stage's own directory β no central cache/ subtree:
training/
βββ 3b7a98e6...c2.TrainingModel.pkl # joblib-pickled fitted TrainingModel
βββ 3b7a98e6...c2.TrainingModel.params.json # canonical identity dict (diff-friendly)
prediction/
βββ 9c12d04f...88.PredictionModel.pkl
βββ 9c12d04f...88.PredictionModel.params.json
explanation/{training|prediction}/
βββ 4e6f2a31...77.ExplanationModel.pkl # joblib-pickled ExplanationModel
βββ 4e6f2a31...77.ExplanationModel.params.json
The .params.json is what was hashed to produce the filename. When use_cache=True
and the next run computes the same identity, the .pkl is loaded instead of recomputed.
fm.train(..., use_cache=True), fm.predict(..., use_cache=True), fm.evaluate(..., use_cache=True),
and fm.explain(..., use_cache=True) (all defaults) use the cache; flip any of them to
False to force a clean run of that stage. use_cache gates both the load and the write β
it is independent of overwrite, which additionally controls plot / per-classifier artefact
regeneration.
scenarios.py passes a per-scenario output_dir into each stage, so artefacts land at:
output/
βββ {nslc}/
βββ tremor/ # produced ONCE outside the loop, shared
βββ scenarios/
βββ scenario-1/
β βββ training/...
β βββ prediction/...
β βββ evaluation/prediction/...
β βββ cache/...
β βββ forecast.config.yaml
β βββ forecast-results_*.csv
βββ scenario-2/
...
βββ scenario-9/
Each scenario directory mirrors a full {station_dir} sub-tree, just rooted at
output/{nslc}/scenarios/{slug}/ instead of output/{nslc}/.
Slugify is from utils/formatting.py:slugify: "Scenario 1" β scenario-1.
The shared tremor/ at the top means re-running scenarios never recomputes
tremor - only the train/predict/evaluate legs are repeated.
| You want to inspect... | Look here |
|---|---|
| The merged tremor CSV | tremor/{nslc}_{start}_{end}.csv |
| Per-day tremor plots | tremor/figures/ |
| The features tsfresh extracted | training/features/{cv}/features-matrix_*.parquet |
| Per-seed feature picks | training/features/{cv}/seed/{seed:05d}.csv |
| Raw per-seed picks concatenated | training/features/{cv}/significant_features.csv |
Full ranked feature list (all features, with alias + description) |
training/features/{cv}/top_features.csv |
The aggregated top-N features (with alias + description) |
training/features/{cv}/top_{N}_features.csv |
| Alias β canonical mapping for a ranked CSV or DataFrame |
load_feature_aliases(source) β see the Feature Alias Utilities API section |
Backfill alias + description onto a legacy ranked CSV |
update_top_features_csv(csv_path) β same section, overwrite=True to refresh |
| β Experimental β post-hoc sweep results | training/features/{cv}/sweep/{mode}/{classifier-name}/ |
| Individual trained models | training/classifiers/{clf}/{cv}/models/{seed:05d}.pkl |
| The single-classifier ensemble | training/classifiers/{clf}/{cv}/SeedEnsemble_*.pkl |
| The all-classifiers ensemble | training/classifiers/ClassifierEnsemble_{cv}.pkl |
| Forecast grid + features | prediction/features/ |
| Per-seed forecast probabilities | prediction/results/{clf}/{seed:05d}.csv |
| Combined forecast CSV (consensus + per-classifier) | forecast-results_{basename}.csv |
| Forecast PNG/PDF | prediction/figures/forecast_{basename}.{png,pdf} |
| Per-seed probability matrix | evaluation/{kind}/classifiers/{Clf}/predictions/y_proba.csv |
| Per-seed prediction matrix | evaluation/{kind}/classifiers/{Clf}/predictions/y_pred.csv |
| Aggregate metric plots + sidecar CSV | evaluation/{kind}/classifiers/{Clf}/figures/aggregate/{plot}.{png,csv} |
| Per-seed metric plots | evaluation/{kind}/classifiers/{Clf}/figures/{plot}/{seed:05d}.png |
| Comparison ranking CSV | evaluation/{kind}/comparison/metrics/ranking_*.csv |
| Bundled SHAP per classifier | explanation/{kind}/classifiers/{Clf}/ClassifierExplanation_{Clf}.pkl |
| Per-seed SHAP explanations | explanation/{kind}/classifiers/{Clf}/shap_values/{seed:05d}.pkl |
| Per-seed bar / beeswarm plots | explanation/{kind}/classifiers/{Clf}/figures/{bar,beeswarm}/{seed:05d}.png |
| Aggregate SHAP bar / beeswarm + sidecar CSV | explanation/{kind}/classifiers/{Clf}/figures/aggregate/{bar,beeswarm}.{png,csv} |
| Per-eruption waterfall plots | explanation/{kind}/eruptions/{YYYY-MM-DD}/{Clf}_*.png |
| Cache identity (diff-friendly) | cache/{Stage}/{hash}.params.json |
| Replayable pipeline config | forecast.config.yaml |
| Standalone training config | training/training.config.yaml |
| Standalone prediction config | prediction/prediction.config.yaml |
| Standalone evaluation config | evaluation/{kind}/evaluation.config.yaml |
| Standalone explanation config | explanation/{kind}/explanation.config.yaml |