Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Estimating Snow-Water-Equivalent (SWE) from Scanning Radar with a Random Forest

ARM Logo

Estimating Snow-Water-Equivalent (SWE) from Scanning Radar with a Random Forest

Open In Colab

Overview

During SAIL, the X-band Precipitation Radar from Colorado State University did full volume scans over the Upper Colorado River Basin from October 2021 - June 2023. From these scans, the ARM Facility developed a Value Added Product called Extracted Radar Columns and In-Situ Sensors (RadClss), which provided vertical columns of radar moments over all SAIL deployment sites (O'Brien et al. (2024)). The data from RadCLss are used to train the models in this notebook (O’Brien et al. (2023)).

The ARM Facility also developed Surface Quantitative Precipitation Estimates (SQUIRE), a snow water equivalent best estimate product produced from the X-band Precipitaiton Radar scans (Grover et al. (2023)). Jackson et al. (2026) evaluated different empirical estimators, power law relationships between ZeZ_{e} and SS, or Ze+KdpZ_{e}+K_{dp} and SS, or SS and KdpK_{dp}, against ground based weighing bucket rain gauges (Pluvio) and melted snow equivalent measurements. From these comparisons, they concluded that Ze−SZ_{e}-S relationships typically provided the best estimates of SWE and therefore were used in SQUIRE.

where:

  • ZeZ_{e} is the radar equivalent reflectivity factor

  • KdpK_{dp} is radar specific differential phase

  • SS is estimated snowfall rate

  • SWESWE is snow water equivalent

Here, we will repeat a similar analysis, but using Random Forest and MLP machine learning techniques in place of power law functions.

Prerequisites

ConceptsImportanceNotes
Scikit-learnHelpfulMachine learning library for clustering and preprocessing
PyTorch TutorialsNecessaryMachine learning library for building and training deep learning models
  • Time to learn: 60 min.

  • System requirements: pytorch dependency

Outline

What you’ll learn

  1. The data — what the radar features (Ze, Kdp) are, and what we are trying to predict (SWE).

  2. A clean train / validation / test split — and why we split by day rather than randomly.

  3. Random Forest 101 — what a Random Forest is, why it works well on tabular data, and what each hyperparameter actually does.

  4. Evaluation — how to read Mean Absolute Error (MAE) and Squared Correlation Coefficient (R²), and how to compare a learned model against a physical baseline (Ze = 40 · S²).

  5. A short Neural Network comparison — using the same features so you can see how Random Forest stacks up against a small MLP.

How to use this notebook

  • Run the cells top-to-bottom.

  • Markdown cells explain the why; code cells do the what.

  • Make sure the data files (radar_swe_20min_all_cases.npz and radar_swe_20min_index.csv) path is correct to your stored data location.


1. The dataset

We pre-built a multi-case machine-learning dataset of 20-minute accumulated snow-water-equivalent (SWE) from ARM RadCLss radar column NetCDF files (O’Brien et al. (2023)). Three quantities matter here:

VariableSymbolUnitsRole
Corrected radar reflectivityZedBZInput feature — how strongly the snow scatters the radar beam at each height
Filtered specific differential phaseKdpdeg/kmInput feature — sensitive to ice/snow shape and orientation
20-minute accumulated SWEy_swemmTarget — what we want to predict

Each sample is a vertical profile through the storm:

  • Heights are restricted to 3300–5300 m (where the snow-relevant signal lives), giving 41 vertical bins.

  • For each profile we compute window-mean values aligned with the 20-minute SWE accumulation target.

  • Everything is bundled into radar_swe_20min_all_cases.npz (arrays) and radar_swe_20min_index.csv (case index).

So each training example has 41 Ze values + 41 Kdp values = 82 features, and one scalar SWE target.

Loaded shapes:
  X_ze: (94689, 41) X_kdp: (94689, 41) y: (94689,)
Heights: 41 (Ze), 41 (Kdp)
time_end: (94689,)

Reading the shapes

X_ze and X_kdp are both (94689, 41) — that’s 94,689 vertical profiles, each with 41 height bins. y_swe is (94689,) — one SWE value per profile, our regression target.

In the next cell we stack Ze and Kdp side-by-side to form a single (94689, 82) feature matrix. A Random Forest is happy to consume the raw, unscaled values — it splits on thresholds, so units don’t matter.

2. Train / validation / test split — by day

We hold out whole days for validation and test, instead of randomly sampling rows. Why?

  • Profiles taken seconds apart in the same storm are highly correlated. If a random split puts neighbours in both train and test, the model effectively gets to peek at the answer and reports unrealistically high scores.

  • Splitting by day forces the model to generalize to storms it has never seen — the realistic deployment setting.

The recipe below uses a 70 / 15 / 15 day-level split with a fixed random seed (42) so the split is reproducible. We also assert the three day sets are disjoint.

Total days=375, train=262, val=56, test=57
Samples: train=65079, val=14828, test=14782
Day overlap (should all be 0): 0 0 0

Handling missing values

Radar profiles sometimes contain NaNs where the signal was below the noise floor — typically the no echo case. We fill those NaNs with the per-block minimum observed in the training set (separately for the ZeZ_{e} block and the KdpK_{dp} block):

  • “Below threshold” really does mean “very small value”, so the minimum is a defensible stand-in.

  • We compute the fill value from train data only to avoid leaking validation/test information into preprocessing.

  • Random Forests are perfectly happy with this — they only care about ordering, not exact magnitude.

Prepared shapes:
  train: (65079, 82) val: (14828, 82) test: (14782, 82)
  Ze features: 41 Kdp features: 41

3. Random Forest 101

A Random Forest is an ensemble of many independent decision trees that vote (for classification) or average their answers (for regression — what we’re doing here). It’s a great first model for tabular data like ours because:

  • It handles mixed scales (dBZ, deg/km) without any feature scaling.

  • It captures non-linear interactions between features automatically.

  • It’s robust to outliers and to a fair amount of noise.

  • It gives you feature importances for free.

  • It’s a strong baseline that often matches or beats more complex models on small/medium tabular datasets.

How a single tree learns

A regression tree repeatedly asks “which feature, at which threshold, splits my training samples into two groups whose targets are most homogeneous?” — and recurses on each side until a stopping rule kicks in (e.g., minimum samples per leaf). The prediction at a leaf is the mean target value of the training samples that landed there.

Why a forest?

A single deep tree memorises the training set (high variance). The forest tames this with two tricks:

  1. Bagging — each tree is trained on a bootstrap (random-with-replacement) sample of the rows.

  2. Feature subsampling — at each split, the tree only considers a random subset of the features.

Averaging many de-correlated trees dramatically reduces variance with little extra bias. That’s the whole magic.

Hyperparameters we use below

ParameterValueWhat it does
n_estimators=400number of treesMore trees → smoother predictions, slower training. 200–500 is a typical sweet spot.
min_samples_leaf=2smallest leaf sizeForces leaves to hold ≥ 2 samples, which gently regularises and reduces overfitting.
random_state=42RNG seedMakes the bagging / feature-subsampling reproducible.
n_jobs=-1parallelismUse all CPU cores for training (trees are independent).

We will train three RF models, identical except for which features they see:

  1. Ze + Kdp — the full 82-feature input.

  2. Ze only — 41 features.

  3. Kdp only — 41 features.

Comparing the three tells us how much each radar variable contributes.

Training RF (Ze + Kdp) on 65079 samples × 82 features...
  done.
Training RF (Ze only)...
  done.
Training RF (Kdp only)...
  done.
RF predictions ready for: Ze+Kdp, Ze-only, Kdp-only.

4. Evaluation: metrics and a physical baseline

Two metrics tell us most of what we need to know:

  • MAE (Mean Absolute Error, in mm) — the typical |predicted − actual| miss. Lower is better, and the units are interpretable: an MAE of 0.03 mm means we’re off by about 0.03 mm of liquid water on a typical 20-min window.

  • R² (coefficient of determination, dimensionless) — the fraction of variance in the target that the model explains. Higher is better; 1.0 is perfect, 0.0 means “no better than always predicting the mean”, and negative values mean “worse than that”.

We also include a classic physical baseline:

Ze = 40 · S² — a textbook Z-S (reflectivity-snowfall-rate) relation. Inverting it gives a snow rate S = √(Ze_linear / 40) in mm/hr, which we multiply by (20/60) to get mm of accumulation in a 20-minute window. We use only the first Ze gate as input.

The baseline is important: if a Random Forest can’t beat a simple physical formula, we haven’t really learned anything useful. Here, the RF barely outperforms a simple Ze−SZ_{e}-S relationship, which here would imply that, for this task, machine learning may not add value.

Test metrics (held-out days):
        model   MAE_mm       R2
 RF (Ze only) 0.032986 0.649037
  RF (Ze+Kdp) 0.033096 0.628075
    Ze=40*S^2 0.042969 0.716526
RF (Kdp only) 0.070562 0.132170
<Figure size 1200x400 with 2 Axes>

As you can see from above, using reflectivity only gives the best performance. This is consistent with the findings of Jackson et al. (2026) when they evaluated empirical Ze−SZ_{e}-S and Kdp−SK_{dp}-S relationships against Pluvio^2 snow water equivalents. Jackson et al. (2026) concluded that this could be explained by the relatively dry nature of the snow observed during SAIL that would not exhibit significant values of KdpK_{dp}. Therefore, this provides us with even more confidence that the Random Forest provides a robust estimate of snow water equivalent.

5. (Optional) Neural Network comparison

For perspective, we train a small multi-layer perceptron (MLP) with the same three feature setups (Ze, Kdp, Ze + Kdp). Two things to notice:

  • The MLP needs its inputs scaled (StandardScaler) — unlike the RF, which ignores scale entirely.

  • We use early_stopping=True so training stops automatically once the internal validation score plateaus.

This isn’t a fair fight (no architecture search, no extensive tuning), but it’s a useful sanity check: the MLP and RF should land in a similar neighbourhood, and the physical baseline should remain competitive.

Feel free to use this as a launchpad for experimentation:

  • Tune the RF (n_estimators, max_depth, max_features, …)

  • Tune the MLP (hidden_layer_sizes, alpha, learning_rate_init, …)

  • Try gradient-boosted trees (HistGradientBoostingRegressor) — often the strongest tabular model.

Training NN (Ze only)...
  done. iterations: 114, final loss: 0.016806
Training NN (Kdp only)...
  done. iterations: 37, final loss: 0.020916
Training NN (Ze + Kdp)...
  done. iterations: 77, final loss: 0.016522
Test metrics (held-out days):
        model   MAE_mm       R2
 NN (Ze only) 0.034453 0.754924
  NN (Ze+Kdp) 0.035973 0.480501
    Ze=40*S^2 0.042969 0.716526
NN (Kdp only) 0.068628 0.050628

Best test by MAE: NN (Ze only)
<Figure size 1200x400 with 2 Axes>
<Figure size 1400x600 with 2 Axes>
Best MAE: RF (Ze only) (0.0330 mm)
Best R²:  NN (Ze only) (0.755)

6. Wrap-up & where to go next

What this notebook showed:

  • A Random Forest trained on simple radar profile features can match — and sometimes beat — a textbook Ze = 40 · S² baseline, with no feature scaling and very little tuning.

  • Ze contributes most of the signal in this dataset: the ZeZ_{e}-only RF is essentially as good as the Ze+KdpZ_{e} + K_{dp} RF, while the KdpK_{dp}-only RF lags well behind. That’s a useful, defensible feature-importance result.

  • A small MLP lands in the same ballpark as the RF, but the physical baseline is hard to dethrone — a good reminder that “ML beats physics” is not the default outcome on a well-posed problem.

  • After all, Jackson et al. (2026) found that the physical baselines based on ZeZ_{e}-only had the best agreement with the Pluvio weighing bucket raingauge and melted snow equivalent measurements during SAIL.

  • So the lesson to learn here is that just because something has AI in it does not mean that it’s better than the old school methods. But this is always worth exploring, especially since MPL and Random Forests are relatively light weight and easy to train.

Suggested next experiments:

  1. Inspect feature importance — rf_both.feature_importances_ is a 1D array of length 82. Plot it vs height to see which heights the forest leans on most.

  2. Tune the RF — try max_depth, max_features='sqrt', or HistGradientBoostingRegressor for a typically-stronger boosted-tree alternative.

  3. Add features — combine Ze and Kdp profiles with derived quantities (e.g. column-mean Ze, gradient of Ze with height) and see if they help.

  4. Cross-validate by case/storm, not just by day, for a more robust estimate of generalisation error.


References
  1. O’Brien, J. R., Raut, B. A., Jackson, R. C., Collis, S. M., Theisen, A., Tuftedal, M., Feldman, D., Sherman, Z. S., & Grover, M. (2024). Extracted Radar Columns and In Situ Sensors (RadCLss) Value-Added Product Report. https://www.osti.gov/biblio/2482520
  2. O’Brien, J., Grover, M., Collis, S., Jackson, R., Sherman, Z., & Raut, B. (2023). Extracted Radar Columns and In-Situ Sensors (RadCLss) (XPRECIPRADARRADCLSS), 2023-01-01 to 2023-01-31, ARM Mobile Facility (GUC), Gunnison, CO; Supplemental Facility 2 (S2). In Atmospheric Radiation Measurement (ARM) user facility. 10.5439/1884520
  3. Grover, M., O’Brien, J., Collis, S., Jackson, R., Sherman, Z., Raut, B., Theisen, A., & Tuftedal, M. (2023). Surface QUantitatIve pRecipitation Estimation (SQUIRE) (XPRECIPRADARSQUIRE), 2023-01-01 to 2023-01-31, ARM Mobile Facility (GUC), Gunnison, CO; Supplemental Facility 2 (S2). In Atmospheric Radiation Measurement (ARM) user facility. 10.5439/1884979
  4. Jackson, R., O’Brien, J., Grover, M., Sherman, Z., Collis, S., Raut, B. A., Tuftedal, M., Theisen, A., Feldman, D., Rudisill, W., & Chandrasekar, V. (2026). Surface Quantitative Precipitation Estimates (SQUIRE) of Snow Water Equivalent from the Surface Atmospheric Integrated Field Laboratory. Journal of Atmospheric and Oceanic Technology, 43(1), 77–93. 10.1175/JTECH-D-25-0023.1