Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8"/> | |
| <meta name="viewport" content="width=device-width, initial-scale=1"/> | |
| <title>Differentiable CREST — CONUS→Global · progress briefing 2026-07-03</title> | |
| <style> | |
| :root{--bg:#f6f8fb;--fg:#1a2230;--mut:#5f6b7d;--acc:#1f6fd6;--good:#1f9d57;--mid:#c98a00;--low:#d6453c;--card:#ffffff;--line:#e2e8f1;--soft:#eef3fa} | |
| *{box-sizing:border-box} | |
| html,body{margin:0;height:100%;background:var(--bg);color:var(--fg);font-family:-apple-system,Segoe UI,Roboto,Helvetica,Arial,"PingFang SC","Microsoft YaHei",sans-serif} | |
| #deck{height:100vh;overflow:hidden;position:relative} | |
| .slide{position:absolute;inset:0;padding:3.6vh 5.2vw 6vh;opacity:0;transform:translateX(26px);transition:opacity .32s,transform .32s;pointer-events:none;overflow-y:auto} | |
| .slide.active{opacity:1;transform:none;pointer-events:auto} | |
| h1{font-size:clamp(26px,4vw,50px);line-height:1.1;margin:.1em 0 .3em} | |
| h2{font-size:clamp(21px,2.8vw,34px);margin:0 0 .5em;color:var(--acc)} | |
| h3{font-size:clamp(15px,1.6vw,20px);margin:.9em 0 .3em} | |
| p,li{font-size:clamp(13.5px,1.45vw,18px);line-height:1.5} | |
| .mut{color:var(--mut)} | |
| .kicker{color:var(--acc);font-weight:700;letter-spacing:.11em;text-transform:uppercase;font-size:12.5px} | |
| .grid{display:grid;gap:16px} | |
| .g2{grid-template-columns:1fr 1fr}.g3{grid-template-columns:1fr 1fr 1fr} | |
| .card{background:var(--card);border:1px solid var(--line);border-radius:13px;padding:15px 17px;box-shadow:0 1px 3px rgba(20,40,80,.04)} | |
| .card h3{margin-top:0;color:var(--acc)} | |
| .big{font-size:clamp(30px,5vw,56px);font-weight:800;line-height:1;color:var(--good)} | |
| .good{color:var(--good)}.mid{color:var(--mid)}.low{color:var(--low)}.acc{color:var(--acc)} | |
| table{border-collapse:collapse;width:100%;font-size:clamp(12.5px,1.4vw,17px)} | |
| th,td{padding:7px 11px;border-bottom:1px solid var(--line);text-align:left} | |
| th{color:var(--mut);font-weight:600} | |
| td.n,th.n{text-align:right;font-variant-numeric:tabular-nums} | |
| .pipe{display:flex;gap:9px;align-items:stretch;flex-wrap:wrap;margin:12px 0} | |
| .stage{flex:1;min-width:150px;background:var(--soft);border:1px solid var(--line);border-left:4px solid var(--acc);border-radius:11px;padding:13px} | |
| .stage .t{font-weight:700;font-size:17px}.stage .s{color:var(--mut);font-size:13px;margin-top:4px} | |
| .arrow{align-self:center;color:var(--acc);font-size:24px} | |
| .tag{display:inline-block;background:var(--soft);border:1px solid var(--line);color:var(--acc);border-radius:999px;padding:3px 11px;font-size:12.5px;margin:3px 4px 0 0} | |
| figure{margin:10px 0 0;text-align:center} | |
| figure img{max-width:100%;max-height:52vh;border:1px solid var(--line);border-radius:10px;background:#fff} | |
| figcaption{color:var(--mut);font-size:12.5px;margin-top:6px} | |
| .figrow{display:flex;gap:14px;flex-wrap:wrap;align-items:flex-start} | |
| .figrow figure{flex:1;min-width:280px} | |
| .foot{position:fixed;bottom:11px;left:0;right:0;display:flex;justify-content:space-between;padding:0 22px;color:var(--mut);font-size:12px;pointer-events:none} | |
| .bar{position:fixed;top:0;left:0;height:3px;background:var(--acc);transition:width .32s;z-index:9} | |
| .nav{position:fixed;bottom:16px;right:22px;display:flex;gap:12px;z-index:10;align-items:center} | |
| .nav button{background:var(--acc);color:#fff;border:none;border-radius:11px;width:52px;height:52px;font-size:26px;line-height:1;cursor:pointer;box-shadow:0 2px 8px rgba(20,60,120,.22);transition:background .15s,transform .1s} | |
| .nav button:hover{background:#1a5fbf} | |
| .nav button:active{transform:scale(.94)} | |
| .nav .cnt{font-size:15px;color:var(--mut);font-variant-numeric:tabular-nums;min-width:52px;text-align:center} | |
| code{background:var(--soft);border:1px solid var(--line);border-radius:6px;padding:1px 6px;font-size:.92em;color:#0a52aa} | |
| .mono{font-family:ui-monospace,SFMono-Regular,Menlo,monospace} | |
| .q{border-left:3px solid var(--mid);padding:5px 0 5px 13px;margin:9px 0;font-size:15px} | |
| .q b{color:var(--mid)} | |
| ul{margin:.3em 0;padding-left:1.15em} | |
| .center{display:flex;flex-direction:column;justify-content:center;height:100%} | |
| .lead{font-size:clamp(14.5px,1.65vw,20px);color:var(--mut);max-width:62ch} | |
| .hl{background:linear-gradient(transparent 62%,#cfe3fb 0)} | |
| .datechip{display:inline-block;background:var(--acc);color:#fff;border-radius:8px;padding:5px 13px;font-size:13px;font-weight:600;letter-spacing:.03em} | |
| a{color:var(--acc)} | |
| </style> | |
| </head> | |
| <body> | |
| <div class="bar" id="bar"></div> | |
| <div id="deck"> | |
| <!-- 1 TITLE --> | |
| <section class="slide active"> | |
| <div class="center"> | |
| <div class="kicker">CREST-Global · progress briefing</div> | |
| <h1>A differentiable CREST:<br/>from CONUS calibration to global parameters</h1> | |
| <p class="lead">Re-implementing the CREST distributed hydrologic model as a GPU-native, | |
| fully differentiable PyTorch program — so parameters can be learned by gradient descent and | |
| <b>regionalized to ungauged basins worldwide</b>, while staying byte-faithful to the EF5 C++ model.</p> | |
| <p style="margin-top:22px"><span class="datechip">Interim report · 2026-07-03</span> | |
| <span class="mut" style="margin-left:12px">Three stages · Snow-17 → Water balance → Routing · tested on the continental U.S.</span></p> | |
| </div> | |
| </section> | |
| <!-- 2 WHY --> | |
| <section class="slide"> | |
| <div class="kicker">Motivation</div> | |
| <h2>Why differentiate CREST?</h2> | |
| <div class="grid g2"> | |
| <div class="card"><h3>The parameter problem</h3> | |
| <p>CREST has ~10 spatial parameters per cell. Traditional calibration (SCE-UA, DREAM) is | |
| per-basin and needs <b>10⁵–10⁶ model runs</b> — impossible to scale to the globe, and it | |
| leaves the 99% of ungauged land untouched.</p></div> | |
| <div class="card"><h3>The differentiable answer</h3> | |
| <p>If the model is differentiable, <b>one backprop pass</b> gives the gradient of a | |
| basin-loss w.r.t. <i>every</i> parameter at once. Then a small neural net | |
| <span class="hl">g(attributes)→parameters</span> can be trained end-to-end through the physics | |
| and applied anywhere — <b>differentiable parameter learning (dPL)</b>.</p></div> | |
| </div> | |
| <div class="card" style="margin-top:14px"><h3>Design commitments</h3> | |
| <span class="tag">Byte-faithful to EF5 C++</span><span class="tag">GPU-native PyTorch</span> | |
| <span class="tag">Physics stays; only parameters are learned</span> | |
| <span class="tag">EF5 a-priori grids as the base map</span> | |
| <span class="tag">CONUS first, then global</span></div> | |
| </section> | |
| <!-- 3 THREE STAGES --> | |
| <section class="slide"> | |
| <div class="kicker">Architecture</div> | |
| <h2>Three physical stages, one differentiable graph</h2> | |
| <div class="pipe"> | |
| <div class="stage"><div class="t">① Snow-17</div><div class="s">T, P → SWE, snowmelt + rain-through = liquid input. Temperature-index snowpack.</div></div> | |
| <div class="arrow">→</div> | |
| <div class="stage"><div class="t">② Water balance</div><div class="s">Liquid input, PET → cell runoff. VIC infiltration + soil store + interflow/GW reservoirs.</div></div> | |
| <div class="arrow">→</div> | |
| <div class="stage"><div class="t">③ Routing</div><div class="s">Cell runoff → gauge discharge. Kinematic wave along the river network.</div></div> | |
| </div> | |
| <div class="grid g3" style="margin-top:4px"> | |
| <div class="card"><h3 class="acc">Calibrated & frozen</h3><p>Stage-1 fit to SNODAS SWE, then <b>frozen</b> — feeds a physically-consistent liquid-water signal downstream.</p></div> | |
| <div class="card"><h3 class="acc">The learning core</h3><p>Stage-2 carries the parameters we calibrate and regionalize. Monthly runoff is the training signal (routing washes out monthly).</p></div> | |
| <div class="card"><h3 class="acc">Prior, evaluated daily</h3><p>Stage-3 uses the EF5-Global KW prior as-is; daily streamflow tells us how much routing adds.</p></div> | |
| </div> | |
| </section> | |
| <!-- 4 pycrest --> | |
| <section class="slide"> | |
| <div class="kicker">Engineering · pycrest</div> | |
| <h2>Writing CREST into GPU-native Python</h2> | |
| <div class="grid g2"> | |
| <div class="card"><h3>Port, don't re-invent</h3> | |
| <p>Each EF5 C++ kernel is re-implemented as a vectorized PyTorch step and checked | |
| <b>byte-for-byte</b> against the original on identical forcing.</p> | |
| <p class="mono mut" style="font-size:13.5px;margin-top:8px">pycrest/<br> | |
| ├ snow17_torch.py <span class="mut"># + numpy twin</span><br> | |
| ├ crest_torch.py <span class="mut"># CT.step(p,sm,P,PET,dt)</span><br> | |
| ├ route_kw <span class="mut"># stage-3 (in progress)</span><br> | |
| └ params.py</p></div> | |
| <div class="card"><h3>Why it runs on GPU</h3> | |
| <p>The water balance is <b>cell-independent</b> → 146,250 CONUS cells evaluate in parallel. | |
| One joint calibration of <b>all 424 basins × 14 years</b> ≈ 460k cell-years/iteration, | |
| <b>~70 s/iter</b>, converges in <b>~1 hour</b> on one RTX 4500.</p> | |
| <p class="mut">vs. days–weeks for per-basin DREAM over the same set. Gradient-safe powers, | |
| per-step NaN sanitization, per-month checkpointing made the gradients usable.</p></div> | |
| </div> | |
| </section> | |
| <!-- 5 STAGE 1 --> | |
| <section class="slide"> | |
| <div class="kicker">Stage 1 · Snow-17</div> | |
| <h2>A calibrated, physically-bounded snowpack</h2> | |
| <div class="figrow"> | |
| <figure><img src="assets/talk/s1_snow.png" alt="Stage-1 snow product"/> | |
| <figcaption>Final CONUS Snow-17 product: SWE test-KGE, snow-correction & melt factors, temperature correction (0.1°, WY2010–2024).</figcaption></figure> | |
| </div> | |
| <div class="grid g3" style="margin-top:8px"> | |
| <div class="card"><div class="big">0.61</div><p class="mut">median SWE KGE across the snow domain</p></div> | |
| <div class="card"><h3>Physically bounded</h3><p>Prior λ=200 cuts bound-railing 54–76%→<3% at only −0.036 KGE. Calibration adds ~+0.6 per-cell over defaults.</p></div> | |
| <div class="card"><h3>Frozen coupling</h3><p>Liquid input drives Stage-2; snow & snow-free basins score alike downstream (0.66 vs 0.70) — coupling is sound.</p></div> | |
| </div> | |
| </section> | |
| <!-- 6 STAGE 2 physics --> | |
| <section class="slide"> | |
| <div class="kicker">Stage 2 · Water balance</div> | |
| <h2>Parameters = multiplier × EF5 a-priori</h2> | |
| <div class="grid g2"> | |
| <div class="card"><h3>The EF5 multiplier scheme</h3> | |
| <p><span class="mono">θ_cell = m_basin × apriori_grid</span> — we learn a small | |
| per-basin multiplier on the physically-derived EF5 base map, not raw parameters. Same scheme | |
| EF5 uses; it is what makes global transfer plausible.</p> | |
| <p class="mut">Original CREST params: wm, b, im, fc, ke (fc frozen — unidentifiable monthly).</p></div> | |
| <div class="card"><h3>Process extensions (each earned by held-out gain)</h3> | |
| <span class="tag">GW reservoir φ, gwc</span><span class="tag">quickflow qc</span> | |
| <span class="tag">precip multiplier pm</span><span class="tag">loss fraction lf</span> | |
| <span class="tag">fast→GW recharge fgw</span> | |
| <p class="mut" style="margin-top:8px">As correct process terms were added, the original | |
| multipliers relaxed toward 1 (wm 1.57→1.06, ke 2.35→1.48) — parameters becoming physical is | |
| evidence the structure is right.</p></div> | |
| </div> | |
| </section> | |
| <!-- 7 STAGE 2 result --> | |
| <section class="slide"> | |
| <div class="kicker">Stage 2 · Result</div> | |
| <h2>Monthly runoff skill — 424 U.S. basins</h2> | |
| <figure><img src="assets/talk/s2_result.png" alt="Stage-2 result"/> | |
| <figcaption>Per-basin monthly-runoff KGE map & CDF, calibrated multiplier ranges, and sample hydrographs across regions (median KGE 0.79; 80% > 0.5).</figcaption></figure> | |
| <div class="grid g3" style="margin-top:8px"> | |
| <div class="card"><div class="big">0.786</div><p class="mut">median monthly KGE, calibrated</p></div> | |
| <div class="card"><div class="big">0.719</div><p class="mut">temporal holdout (unseen years)</p></div> | |
| <div class="card"><h3>One joint fit</h3><p>~4,200 free multipliers across all 424 basins, ~1 h GPU. Biggest lever: interannual Oudin PET (r 0.59→0.78).</p></div> | |
| </div> | |
| </section> | |
| <!-- 8 dPL --> | |
| <section class="slide"> | |
| <div class="kicker">Stage 2 · Regionalization (dPL)</div> | |
| <h2>From 424 gauges to any basin</h2> | |
| <div class="figrow"> | |
| <figure><img src="assets/talk/s2_fields.png" alt="v2 parameter fields"/> | |
| <figcaption>Full-coverage v2 parameter fields: per-basin calibration inside gauged basins, dPL-ensemble multipliers from each cell's AlphaEarth embedding elsewhere.</figcaption></figure> | |
| <div class="card" style="flex:1;min-width:300px"> | |
| <p class="mut" style="margin-top:0">A shared MLP <span class="hl">g(AlphaEarth 64-dim embedding) → the ten multipliers</span>, trained end-to-end through the water balance.</p> | |
| <table> | |
| <tr><th>Ungauged test</th><th class="n">med KGE</th><th class="n">>0</th></tr> | |
| <tr><td>PUB (212 held-out, ensemble)</td><td class="n good">0.65</td><td class="n">90%</td></tr> | |
| <tr><td>Independent 295 Reference, zero-shot</td><td class="n good">0.52</td><td class="n">86%</td></tr> | |
| <tr><td class="mut">vs nearest-basin transfer</td><td class="n mid">0.45</td><td class="n">74%</td></tr> | |
| <tr><td class="mut">vs a-priori only</td><td class="n low">−1.31</td><td class="n">11%</td></tr> | |
| </table> | |
| <p class="mut" style="margin-bottom:0">~80% of gauged skill at ungauged sites. <b>Finding:</b> the embedding alone suffices; ensembling was the one reliable lever.</p></div> | |
| </div> | |
| </section> | |
| <!-- 9 STAGE 3 --> | |
| <section class="slide"> | |
| <div class="kicker">Stage 3 · Routing (fresh — 2026-07-03)</div> | |
| <h2>Does the EF5-Global KW prior help daily?</h2> | |
| <div class="figrow"> | |
| <figure><img src="assets/talk/s3_route.png" alt="Stage-3 routing result"/> | |
| <figcaption>Left: daily timing-skill CDF (bias-removed) — KW & UH shift the whole distribution right of no-routing. Right: routing gain grows with river-network depth.</figcaption></figure> | |
| <div class="card" style="flex:1;min-width:300px"> | |
| <p style="margin-top:0">Forward-only: calibrated runoff → EF5-Global KW prior (0.05°, α₀/α/β, D8, <b>zero calibration</b>) → daily gauge Q.</p> | |
| <table> | |
| <tr><th>Engine</th><th class="n">daily KGE*</th><th class="n">Δ</th></tr> | |
| <tr><td>No routing</td><td class="n">0.503</td><td class="n mut">—</td></tr> | |
| <tr><td>Dynamic KW prior</td><td class="n good">0.549</td><td class="n good">+0.02</td></tr> | |
| <tr><td>Travel-time UH</td><td class="n good">0.564</td><td class="n good">+0.03</td></tr> | |
| </table> | |
| <ul style="margin-top:8px"> | |
| <li><b>Works, small daily lever</b> (+0.05 for the deepest nets).</li> | |
| <li><b>UH ≈ KW</b> → a cheap differentiable UH suffices.</li> | |
| <li><b>Real gap is volumetric bias</b> (β≈0.62), not timing.</li></ul></div> | |
| </div> | |
| </section> | |
| <!-- 10 GLOBAL --> | |
| <section class="slide"> | |
| <div class="kicker">The point of it all</div> | |
| <h2>Path to global CREST parameters</h2> | |
| <div class="grid g2"> | |
| <div class="card"><h3>Why CONUS transfers</h3> | |
| <ul><li>Same <b>EF5-Global a-priori</b> base map worldwide (Clark 2017, 5 km).</li> | |
| <li>Same <b>AlphaEarth embedding</b> for every land pixel on Earth.</li> | |
| <li>Multipliers relaxed toward 1 → base map largely unbiased; dPL learns a modest correction field.</li></ul></div> | |
| <div class="card"><h3>Proposed global template</h3> | |
| <ul><li><b>HydroBASINS L6/7</b> tiling (seamless, nested, ~1k–10k km²).</li> | |
| <li>Per-unit basin-mean embedding → g → multipliers → one static parameter grid.</li> | |
| <li>Gauged units (GRDC) keep calibrated multipliers; dPL fills the rest.</li> | |
| <li>Train/apply granularity matches → PUB/independent numbers carry over.</li></ul></div> | |
| </div> | |
| <p class="mut" style="margin-top:10px">The CONUS pipeline is the dress rehearsal; every ingredient has a global counterpart already in hand.</p> | |
| </section> | |
| <!-- 11 DISCUSSION --> | |
| <section class="slide"> | |
| <div class="kicker">For discussion</div> | |
| <h2>Open points we'd like expert input on</h2> | |
| <div class="grid g2"> | |
| <div class="q"><b>1 · A-priori transfer.</b> EF5-US and EF5-Global base maps differ | |
| (wm median 181 vs 87 mm) → CONUS multipliers won't transfer directly; global work needs | |
| re-calibration on the global base map. Right base, or harmonize base maps first?</div> | |
| <div class="q"><b>2 · Process extensions vs CREST orthodoxy.</b> We added φ/gwc/qc/pm/lf/fgw reservoirs. | |
| Acceptable within "CREST," or should timing live entirely in routing (EF5's under/leaki)?</div> | |
| <div class="q"><b>3 · Monthly training, daily use.</b> We calibrate on monthly runoff, evaluate daily. | |
| The daily bias (β≈0.62) suggests monthly under-constrains storm magnitude — calibrate daily directly?</div> | |
| <div class="q"><b>4 · Routing scope.</b> Daily gain +0.02 (→+0.05 big/deep nets). Worth a | |
| differentiable KW, or is a static UH sufficient until we target large rivers?</div> | |
| <div class="q"><b>5 · Basin-boundary seams.</b> Product keeps per-basin multipliers inside gauged | |
| basins, dPL elsewhere → visible seams (largest in lf/fgw). Ship accurate-patchy, smooth all-dPL, or both?</div> | |
| <div class="q"><b>6 · Global gauges & attributes.</b> Which reference network (GRDC, GSIM) and which | |
| attributes beyond AlphaEarth (aridity, snow fraction, lithology) matter most for global dPL?</div> | |
| </div> | |
| </section> | |
| <!-- 12 STATUS --> | |
| <section class="slide"> | |
| <div class="kicker">Status & next · 2026-07-03</div> | |
| <h2>Where we are</h2> | |
| <div class="grid g3"> | |
| <div class="card"><h3 class="good">Done</h3><ul> | |
| <li>pycrest: Snow-17 + WB, GPU, byte-faithful</li> | |
| <li>Stage-1 snow calibrated (0.61)</li> | |
| <li>Stage-2 WB calibrated (0.786 / holdout 0.719)</li> | |
| <li>dPL regionalization (PUB 0.65, indep 0.52)</li> | |
| <li>v2 full-coverage CONUS parameter set</li> | |
| <li>Stage-3 routing prior evaluated daily</li></ul></div> | |
| <div class="card"><h3 class="mid">In progress</h3><ul> | |
| <li>Routing module into pycrest</li> | |
| <li>Daily-bias diagnosis (β≈0.62)</li> | |
| <li>Seam-free product variant</li></ul></div> | |
| <div class="card"><h3 class="acc">Next</h3><ul> | |
| <li>Global base-map re-calibration</li> | |
| <li>HydroBASINS + GRDC global dPL</li> | |
| <li>Daily-scale calibration option</li> | |
| <li>Differentiable UH/KW if warranted</li></ul></div> | |
| </div> | |
| <p class="mut" style="margin-top:16px">Companion pages: <a href="stage1-snow.html">Stage 1 — Snow</a> · | |
| <a href="stage2-water.html">Stage 2 — Water balance & dPL</a></p> | |
| </section> | |
| </div> | |
| <div class="foot"><div>Differentiable CREST · CONUS→Global · interim briefing 2026-07-03</div><div></div></div> | |
| <div class="nav"><button onclick="go(-1)" title="Previous (←)">‹</button><span class="cnt" id="pg"></span><button onclick="go(1)" title="Next (→)">›</button></div> | |
| <script> | |
| const s=[...document.querySelectorAll('.slide')];let i=0; | |
| function show(n){i=Math.max(0,Math.min(s.length-1,n));s.forEach((e,k)=>e.classList.toggle('active',k===i)); | |
| document.getElementById('pg').textContent=(i+1)+' / '+s.length; | |
| document.getElementById('bar').style.width=((i)/(s.length-1)*100)+'%';location.hash=i+1;} | |
| function go(d){show(i+d)} | |
| addEventListener('keydown',e=>{if(e.key==='ArrowRight'||e.key==='PageDown')go(1); | |
| else if(e.key==='ArrowLeft'||e.key==='PageUp')go(-1);else if(e.key==='Home')show(0);else if(e.key==='End')show(s.length-1);}); | |
| const h=parseInt(location.hash.slice(1));show(isNaN(h)?0:h-1); | |
| </script> | |
| </body> | |
| </html> | |