diff --git a/.gitattributes b/.gitattributes index a6344aac8c09253b3b630fb776ae94478aa0275b..2cd2b0962e6ccb335bc9d9670a0c65bf43a73665 100644 --- a/.gitattributes +++ b/.gitattributes @@ -33,3 +33,27 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text *.zip filter=lfs diff=lfs merge=lfs -text *.zst filter=lfs diff=lfs merge=lfs -text *tfevents* filter=lfs diff=lfs merge=lfs -text +figures/_preview-mae-heatmap.png filter=lfs diff=lfs merge=lfs -text +figures/bpi2017-drift-with-tsfm.png filter=lfs diff=lfs merge=lfs -text +figures/bpi2017-drift-xgb-only.png filter=lfs diff=lfs merge=lfs -text +figures/demo-1-bundled.png filter=lfs diff=lfs merge=lfs -text +figures/demo-3-diff-abs.png filter=lfs diff=lfs merge=lfs -text +figures/demo-4-diff-rel.png filter=lfs diff=lfs merge=lfs -text +figures/demo-5-live.png filter=lfs diff=lfs merge=lfs -text +figures/demo-screencast-poster.png filter=lfs diff=lfs merge=lfs -text +figures/demo-screencast.mp4 filter=lfs diff=lfs merge=lfs -text +figures/df-complexity-radar.png filter=lfs diff=lfs merge=lfs -text +figures/er-bars.png filter=lfs diff=lfs merge=lfs -text +figures/ft-slope.png filter=lfs diff=lfs merge=lfs -text +figures/ft-table.png filter=lfs diff=lfs merge=lfs -text +figures/mae-full.png filter=lfs diff=lfs merge=lfs -text +figures/results-mae-bars.png filter=lfs diff=lfs merge=lfs -text +figures/rmse-full.png filter=lfs diff=lfs merge=lfs -text +figures/s14-drift-tsfm.png filter=lfs diff=lfs merge=lfs -text +figures/s14-intermittent-tsfm.png filter=lfs diff=lfs merge=lfs -text +figures/s6-drift-xgb-box.png filter=lfs diff=lfs merge=lfs -text +figures/s6-drift-xgb.png filter=lfs diff=lfs merge=lfs -text +figures/s6-intermittent-xgb-arrow.png filter=lfs diff=lfs merge=lfs -text +figures/s6-intermittent-xgb.png filter=lfs diff=lfs merge=lfs -text +figures/s7-complexity-radar.png filter=lfs diff=lfs merge=lfs -text +logos/kuleuven-liris.png filter=lfs diff=lfs merge=lfs -text diff --git a/404.html b/404.html new file mode 100644 index 0000000000000000000000000000000000000000..2700ddb4af9e240d0ace3183ccecf113a4ad550f --- /dev/null +++ b/404.html @@ -0,0 +1,43 @@ + + +
+ + +CAiSE 2026 presentation — pmf-tsfm +Yongbo Yu, Jari Peeperkorn, Johannes De Smedt, Jochen De Weerdt +KU Leuven · LIRIS
+`,highlighter:"shiki",twoslash:!0,lineNumbers:!1,colorSchema:"light",routerMode:"history",aspectRatio:1.7777777777777777,canvasWidth:1280,exportFilename:"",selectable:!1,themeConfig:{},fonts:{sans:['"Inter"',"ui-sans-serif","system-ui","-apple-system","BlinkMacSystemFont",'"Segoe UI"',"Roboto",'"Helvetica Neue"',"Arial",'"Noto Sans"',"sans-serif",'"Apple Color Emoji"','"Segoe UI Emoji"','"Segoe UI Symbol"','"Noto Color Emoji"'],serif:["ui-serif","Georgia","Cambria",'"Times New Roman"',"Times","serif"],mono:['"JetBrains Mono"',"ui-monospace","SFMono-Regular","Menlo","Monaco","Consolas",'"Liberation Mono"','"Courier New"',"monospace"],webfonts:["Inter","JetBrains Mono"],provider:"google",local:["Avenir Next"],italic:!1,weights:["400","500","600","700"]},favicon:"https://cdn.jsdelivr.net/gh/slidevjs/slidev/assets/favicon.png",drawings:{enabled:!0,persist:!1,presenterOnly:!1,syncAll:!0},plantUmlServer:"https://www.plantuml.com/plantuml",codeCopy:!0,magicMoveCopy:!0,author:"",record:"dev",css:"unocss",presenter:!0,browserExporter:"dev",htmlAttrs:{},transition:"slide-left",editor:!0,contextMenu:null,wakeLock:!0,mdc:!0,comark:!1,seoMeta:{},notesAutoRuby:{},duration:"20min",timer:"stopwatch",magicMoveDuration:800,preloadImages:!0,layout:"cover",eyebrow:"CAiSE 2026",logo:"/logos/kuleuven-liris.png",venue:`arXiv:2512.07624 +10 June · Verona, Italy +`,slidesTitle:"Time Series Foundation Models for Process Model Forecasting - Slidev"};function gn(t,e,n){return Math.min(n,Math.max(e,t))}function yr(...t){return wr(t).reduce((e,n)=>e+n,0)}function vr(t){return t=t??[],Array.isArray(t)?t:[t]}function wr(t){return vr(t).flat(1)}function br(t){return Array.from(new Set(t))}function Jn(...t){let e,n,s;t.length===1?(e=0,s=1,[n]=t):[e,n,s=1]=t;const o=[];let r=e;for(;rZn(a,i)),a.hooks.callHook("init",a),t.init?.forEach(i=>i&&a.push(i)),a}const Ur=(t,e)=>xo(e)?dn(e):e,ro="usehead";function Gr(t){return{install(n){n.config.globalProperties.$unhead=t,n.config.globalProperties.$head=t,n.provide(ro,t)}}.install}function Qr(){if(Fo()){const t=Vs(ro);if(t)return t}throw new Error("useHead() was called without provide context, ensure you call it through the setup() function.")}function Jr(t,e={}){const n=e.head||Qr();return n.ssr?n.push(t||{},e):Kr(n,t,e)}function Kr(t,e,n={}){const s=O(!1);let o;return tt(()=>{const a=s.value?{}:It(e,Ur);o?o.patch(a):o=t.push(a,n)}),Us()&&(Ho(()=>{o.dispose()}),jo(()=>{s.value=!0}),zo(()=>{s.value=!1})),o}function wn(t){if(t===!1||t==="false")return null;if(t==null||t===!0||t==="true")return"+1";if(typeof t=="string"&&"+-".includes(t[0]))return t;const e=+t;return Number.isNaN(e)?(console.error(`Invalid "at" prop value: ${t}`),null):e<=0?(console.warn(`[Slidev] "at" prop value must be greater than 0, but got ${t}, has been set to 1`),1):e}function Yr(t){return Array.isArray(t)?[wn(t[0]),wn(t[1])]:null}function ao(t,e=0,n){const s=O(!1);let o=new Map,r=new Map;const a={get current(){return gn(+t.value,e,a.total)},set current(i){t.value=s.value?gn(i,e,a.total):i},clicksStart:e,get relativeSizeMap(){return o},get maxMap(){return r},get isMounted(){return s.value},setup(){Gs(()=>{s.value=!0,r=A(r),Bo(t)||(a.current=t.value)}),Wo(()=>{s.value=!1,o=new Map,r=new Map})},calculateSince(i,l=1){const c=wn(i);if(c==null)return null;let f,d,h;if(typeof c=="string"){const u=a.currentOffset,g=+c;f=u+g,d=u+g+l-1,h=g+l-1}else f=c,d=c+l-1,h=0;return{start:f,end:+Number.POSITIVE_INFINITY,max:d,delta:h,currentOffset:k(()=>a.current-f),isCurrent:k(()=>a.current===f),isActive:k(()=>a.current>=f)}},calculateRange(i){const l=Yr(i);if(l==null)return null;const[c,f]=l;let d,h,u;return typeof c=="string"?(d=a.currentOffset+ +c,u=+c):(d=c,u=0),typeof f=="string"?(h=d+ +f,u+=+f):h=f,{start:d,end:h,max:h,delta:u,currentOffset:k(()=>a.current-d),isCurrent:k(()=>a.current===d),isActive:k(()=>d<=a.current&&a.current [S-01]
+OPENING ANCHOR LINE (rehearse cold):
+"I'm going to show you something that took me a while to believe:
+the best forecaster for your process model isn't one you trained —
+and probably isn't one you should train." Pause. Let it land. Then advance. [S-02]
+Q: Why isn't a discovered model enough? Process discovery extracts a process model from event-log data — here a Directly-Follows
+Graph (DFG): nodes are activities, arrows count directly-follows relations.
+Same BPI2017 offer process, two periods: same representation, but the counts move
+(Accepted → End falls 465 → 306). The process drifted. PMF starts here — learn those
+temporal changes and forecast the next DFG. Transition out: "If the model drifts, the natural question is HOW — and that splits into
+two very different prediction problems." → S3 (PMF vs PPM) [S-03]
+Q: PMF vs the PPM I already know? Same loan log, two different prediction problems. PPM is case-level: take ONE ongoing
+application and predict its future — the next event, the remaining time, or the outcome
+("will THIS loan be canceled?"). Horizon = the rest of that one case. PMF is system-level: take a WINDOW of the whole log, and forecast the next process model —
+how often each transition fires next, e.g. how often "offer sent → canceled" occurs across
+ALL cases. Horizon = the near-term system future (conceptually weeks-to-months; the 7-day
+experimental horizon is setup detail for S12 — don't say it here). Same event log, different question. (Absorbed into the assertion — deliver in speech.) 60s. Transition out: "Both need data, but PMF needs something different — let me show you
+the pipeline." [S-04]
+Q: How does PMF become a forecasting problem? Transition IN (from S3): "Both need data, but PMF needs something different — let me show you the pipeline." DF is introduced here (full term "directly-follows (DF) relations"); DFG is already known from S2 —
+use the abbreviation. Let the THREE CLICKS carry it; don't talk over them:
+• click 0 — event log → one daily count series per DF edge (the navy "past" window; 3 arcs shown,
+the point being we forecast ALL arcs, not just the hero).
+• click 1 — forecast the next 7 days for every arc (amber tail; the "future" window).
+• click 2 — sum each arc's 7 daily forecasts → the reassembled, FORECASTED DFG (≈316 vs held-out 315). Keep it to "aggregate daily, forecast 7 days ahead." Do NOT mention stride / expanding window /
+60-20-20 here — that's S12. "past/future" are a conceptual history→horizon motif, not the
+experimental window. Transition OUT (to S5): "So it's a forecasting problem. Why isn't it already solved?" [S-05]
+Q: What makes these series difficult? Transition IN (from S4): "So it's a forecasting problem. Why isn't it already solved?" Three data challenges, shown with REAL ground-truth series (no model lines yet):
+① Drift — BPI2017 Sent → Canceled: a genuine level shift, fires ~46/day early, decays to ~3.
+② Intermittent — BPI2019-1 Cancel → Record Invoice Receipt: ~80% zeros, sudden spikes to ~29.
+③ Heterogeneous — the two panels are different logs with completely different shapes; DF
+relations also differ within a single log. Neither is white noise, neither is a smooth trend. Axes: x = day (stride = 1, so consecutive windows are consecutive days), y = value (the 7-day-ahead
+forecast's last day). These two plots reappear on S14 with the model lines revealed — DO NOT show
+any model line here. 45s. Transition OUT (to S6): "These are hard. So — do the methods we already have handle them?" [S-06]
+Q: Do the methods we already have handle these patterns? Transition IN (from S5): "These are hard. So — do existing methods handle them?" ML/DL don't win in general. Here is the prior benchmark's TOP ML — tuned XGBoost (Yu et al. 2025) —
+on the SAME two series from S5:
+• Drift: XGBoost stays high and misses the level-shift drop.
+• Intermittent: XGBoost overfits badly — it hallucinates large values (40–71) where the truth is
+mostly zero. A textbook overfit to a small, complex, heterogeneous signal.
+Reason (callback to S5's challenges): small + complex + heterogeneous data makes from-scratch
+ML/DL overfit. XGBoost is the benchmark's recommended top model and still loses — it becomes our ML
+baseline going forward. Honest nuance (speech only): the TSFM revealed on S14 wins by staying controlled (not overshooting),
+not by capturing the rare spikes. Do NOT show any TSFM line here — that's S14. 45s. Transition OUT (to S7 complexity): "It's not bad luck — these series are statistically off the
+charts, and the logs are tiny." [S-07]
+Q: Why do trained-from-scratch models struggle here? Transition IN (from S6): "It's not bad luck — these series are statistically off the charts,
+and the logs are tiny." This is the quantitative WHY behind S6's overfitting. Two facts, one message:
+• COMPLEX — across 7 paper complexity metrics, three stand out: Transition, Shifting,
+Non-Gaussianity. The paper reports these as HIGHER than the 21 public forecasting
+benchmarks (Li et al. 2025). Say it qualitatively — we don't plot the benchmark
+numbers (not in our repo); the amber axes + badge carry it.
+• SMALL — every log is one short multivariate series: only 307–726 daily steps, split
+expanding-window, with up to 149 DF variables. Sepsis is the extreme (999 cases /
+16,009 events over 459 days) — the sparsity that drives its later ER failure (backup). Together: complex signal + little data → from-scratch ML/DL overfit (exactly S6). Numbers are
+paper-faithful (stats_log.tex / stats_df.tex). Don't re-explain S6's overfit — prove it. 45-60s. Transition OUT (to S8 TSFM): "Small, complex, heterogeneous data is exactly where a
+model you don't train might win." [S-08]
+Q: What is the current direction in forecasting? (And are we forecasting with an LLM?) Transition IN (from S7): "Small, complex, heterogeneous data is exactly where a model you
+don't train might win." THE load-bearing slide (outline: the single slide that, if cut, most weakens the talk — without
+it half the room thinks we fine-tuned GPT). One message: the current direction in forecasting is
+foundation models. Just as an LLM is a foundation model for language (text → text), a Time Series
+Foundation Model (TSFM) is one for time series (time series → time series) — same recipe (pretrain
+at scale, then generalize across tasks), different data. So we are NOT using an LLM. Two terms defined here so later slides can lean on them:
+• zero-shot — run the pretrained model on a new log, no training.
+• fine-tuning — keep training it on task data. (LoRA / full variants defined later, S11/S15.) 45s. Transition OUT (to S9 — Why TSFMs for PMF): "Same recipe as LLMs. So why would that help
+our problem?" [S-09]
+Q: Why should a generic forecaster beat a specialized one? Transition IN (from S8): "Same recipe as LLMs. So why would that help our problem?" Callback to S7: our DF series are both COMPLEX and SMALL — only 307–726 daily points per log —
+exactly where a model trained from scratch overfits. LOAD-BEARING line (say aloud): "Specialized models overfit on small heterogeneous PMF data.
+Foundation models, pretrained on millions of diverse series, are designed to not." Caveat (critique constraint): "No event logs in pretraining, to our knowledge" — so this is
+genuinely zero-shot transfer; we test whether generic forecasting knowledge carries to DF series.
+(Say "no event logs in pretraining, to our knowledge" — NOT "no process data".) ~35s. Transition OUT (to S10 — Three questions): "We have a candidate. Here's what we ask of it." [S-10]
+Q: What three things does this talk actually test? Transition IN (from S9): "We have a candidate. Here's what we ask of it." 30s scaffold for the results. Names (Chronos / MOIRAI / TimesFM, LoRA, Entropic Relevance)
+land on later slides, not here. Standard terminology only: zero-shot (NOT off-the-shelf),
+fine-tuning (NOT adapting). Q1 is forecasting accuracy vs the strongest PMF baselines ONLY (seasonal-naive + tuned
+XGBoost) — the on-slide line is trimmed to "give better DF time-series forecasts?"; say the
+"vs the strongest PMF baselines" comparator ALOUD. Do NOT claim process-model quality here —
+that is Q3 / ER.
+Q2 ("further") = does fine-tuning add on top of the zero-shot win.
+Q3 (amber) = the open one: does a better forecast translate to a better forecasted process model? Maps to the results (speaker-notes only): Q1 -> S13 (zero-shot beats both baselines),
+Q2 -> S15 (fine-tuning marginal), Q3 -> S16 (ER parity). Transition OUT (into S11 — The candidates): "Three questions. Here's what we point at them." [S-11]
+Q: Which models, and what settings? Key message: we tried a lot — 3 model families across 3 settings (12 zero-shot variants). Names stay ON SCREEN, not in the voice (attention-risk #1 — let the timeline carry the load).
+Say the shape, not the roster: each family has shipped several generations; the latest of each
+(amber) is what the results use, and the trend is "newer = smaller, yet better" — MOIRAI-2.0 is just
+~11.4M params. univariate throughout (Yu 2025). LoRA = Low-Rank Adaptation, small trainable adapters
+on attention (full form is on the slide). 45s. Transition IN (from S10 three questions): "Three questions. Here's what we point at them."
+Transition OUT (to S12 experimental setup): "That's the coverage — now exactly how we evaluated it."
+(The "...no event logs in pretraining ... point them at DF time series" line belongs at the results
+entry, S13, not here.) [S-12]
+Q: How exactly did you evaluate? (And was it fair?) Transition IN (from S11 candidates): "Before the results, one slide on exactly how we tested." This slide OWNS the window/stride detail kept off S4. Reconciliation: S4 says only "aggregate
+daily, forecast 7 days ahead"; S12 adds the protocol — expanding window, stride = 1 day. Nothing
+on S4 contradicts this. Deliver the assumption -> design-choice mapping ALOUD (it is intentionally NOT on the slide): 45s. Transition OUT (to S13 — zero-shot results): "With that setup, here are the zero-shot results." [S-13]
+Q: Does Q1 hold — do zero-shot TSFMs beat the baselines? Transition in: "Three families. Twelve variants. No event logs in pretraining.
+Here's what happens when you point them at DF time series." ~2 min. Say "Mean Absolute Error" on first use (kicker carries MAE). CRITIQUE CONSTRAINT —
+open with the baseline framing verbatim (the on-slide caption was dropped; deliver it aloud):
+"We compare against the two strongest baselines from our prior benchmark; full ranking
+on backup." Pre-empts cherry-picking. Callouts (click 1 then 2): (1) the 3 latest TSFMs average −21% MAE vs the best baseline.
+(2) across ALL twelve zero-shot variants × 4 logs, 92% of results beat the best baseline
+(−15% mean); only four older/smaller models miss, all on BPI2017. The three latest models (Chronos-2, MOIRAI-2.0, TimesFM-2.5) win MAE on all four logs —
+including Sepsis (MOIRAI-2.0 ↓28%). Sepsis is NOT a MAE exception; it only becomes the
+hard case later, on ER (beat 9). Don't undercut the MAE win here. Q&A defense: some older/smaller variants don't beat the baselines on BPI2017 (paper
+p.11) — that's why the bars show the latest of each family. Transition out (into 7b): "Same data, same window — here's what that win looks like." [S-14]
+Q: What does the zero-shot win look like on real DF patterns? Transition IN (from S13 bars): "Same data, same window — here's what that win looks like." THE CALLBACK MOMENT — the audience remembers these two plots from S5/S6 (truth only, then XGBoost
+failing). One click reveals the MOIRAI-2.0 line on BOTH, with the amber marks. Don't rush the click.
+• Drift (left, amber box): "Same plot, same window. The TSFM tracks the drop XGBoost missed."
+MOIRAI-2.0 misses the initial drop, then catches up at the troughs — online adaptation, NO
+retraining. The box frames where it comes down while XGBoost stays stuck high.
+• Sparsity (right, amber arrow) — the HONEST beat: MOIRAI-2.0 holds near zero. It avoids
+XGBoost's false bursts (XGBoost hallucinated 40–71 where truth is mostly 0; MOIRAI-2.0 MAE 2.0,
+−89%), but it does NOT catch the rare spikes. The arrow marks it: down to ~0, still present.
+"Not a miracle spike detector — on a near-empty signal, the honest answer is to stay near zero." Mechanism (if asked): the TSFM adapts via an EXPANDING historical-context window at inference —
+no retraining (paper §4.1). ~1 min. Transition OUT (to S15 fine-tuning): "TSFMs win zero-shot. Natural next question: can we
+make them better?" [S-15] Q: Does fine-tuning (Q2) help? Is it worth it? ~1 min 30s. The clean-negative beat before S16's low-energy ER concession.
+Transition in: "TSFMs win zero-shot. Natural next question — can we make them better?" Panel order (logs are small on screen — name them aloud): top-left BPI2017, top-right BPI2019-1,
+bottom-left Sepsis, bottom-right Hospital Billing. Read the slope: most lines hug the 1.0 zero-shot baseline (gray bundle — fine-tuning barely moves
+accuracy), while a few full-FT lines shoot up in amber (overfitting on small logs):
+MOIRAI-1.1-R-large +87% on BPI2019-1, +31% on Sepsis; Chronos-2 +16% on Sepsis. Click reveals the
+tally: across all 36 LoRA + full fine-tuning runs, 19 (53%) landed worse than zero-shot. The few real
+gains (Sepsis full-FT −10 to −13%) are small and dataset-dependent. COST — speak it, do NOT put on slide (no wall-clock logged, no fabricated ratio):
+"And it never comes for free. Zero-shot is one forward pass per window. LoRA and full fine-tuning each
+add a whole training stage — repeated for every model and every log — and in the worst case full
+fine-tuning nearly doubled the error. The accuracy payoff is a coin-flip and sometimes catastrophic.
+So at PMF data scale, skip it." Transition out: "Fine-tuning isn't the win. So does the forecasting win even translate into a better
+process model?" [S-16]
+Q: Does the forecasting win translate into a better process model? Transition in: "But forecasting accuracy isn't the only thing we care about in PM."
+OPEN WITH THE QUESTION, not the result — S14→S16 is the talk's lowest-energy moment. Introduce the term: say "Entropic Relevance" in full on first use (the on-slide line carries it
+full-form-first); use "ER" thereafter. One line: ER = expected bits to encode a log trace under the
+forecasted model; lower = better; Truth is the floor. Two findings (revealed in sequence with the two callouts): ~1 min 30s. THE LOAD-BEARING SLIDE.
+Memorized rebuttal — deliver in SPEECH, not on slide (verbatim from SLIDES.md): "ER parity means we're not producing better DFG structures — we're producing
+DFGs with better edge weights. For tasks where the forecast itself is the
+deliverable — capacity planning, drift detection, anomaly baselines —
+edge-weight accuracy IS the contribution. For tasks where you need a different
+process model, ER says the bottleneck is now the DFG representation,
+not the forecaster." Do not skip this line. Rehearse it cold. Transition out (hands the "bottleneck has moved" framing to S17): "So the forecasting is solved —
+which means the open problem has moved somewhere else." [S-17]
+Q: Where does process model forecasting go from here? Transition in (from S16): "So the forecasting is solved — the open problem has moved somewhere else." LEAD WITH THE HEADER (say it first): the bottleneck has moved from forecasting accuracy
+(solved — zero-shot TSFMs beat the baselines) to PROCESS-AWARE REPRESENTATION. DFGs capture
+only the control-flow / workflow aspect — a lossy target (callback to S16's ER parity). This
+slide OWNS the "bottleneck has moved" line — S18 must not repeat it. Then the three future directions (paper §Discussion): Also mention aloud (kept off-slide): concept drift is a key challenge — combine drift detection
+with incremental / lightweight fine-tuning for adaptive retraining (paper §Discussion). ~1 min. Transition out (to S18 Takeaways): "So what do we actually walk away with?" [S-18]
+Q: What do I walk away with — and what do I do next? Transition in: "So what do we walk away with?" ~75s. Two audiences: practitioners (what to do)
+and the field (what we learned). Practitioner — ONE point: these models are small. Run them on a laptop or a cheap GPU, get a
+forecast fast, little compute. You CAN fine-tune, but at PMF data scale it's rarely worth it. Two signals: Do NOT say the "bottleneck has moved" line here (that's S17). No artifact/code links here (S19). CLOSING ANCHOR — rehearse COLD, deliver in SPEECH (not on slide):
+"Zero-shot TSFMs are the new PMF default. Four logs is not a paradigm — but it is a strong enough
+signal that the right new default is to try a zero-shot TSFM first. The deeper signal is that
+time-series forecasting just became cheap enough that process mining can borrow from it without
+paying the training tax. What else can we borrow?" Transition out (to S19 artifacts): "And all of this is yours to run." [S-19]
+~1.5–2 min. THE DEMO BEAT — the work is reproducible and usable. Transition in: "Everything I've shown is public and runs out of the box." ONE click plays the ~29s screencast (once, no loop) — a real recording of the live app.
+What it walks through:
+• Forecast vs actual future — the bundled backtest, forecast DFG beside the held-out truth.
+• Accuracy — ER / MAE / RMSE against that real future (ER truth = the floor to beat).
+• Diff — where the forecast matched, missed (amber), or over-called (red): absolute, then relative %.
+• Upload your own log — the live ZeroGPU path, forecast vs the last-known window.
+Talk over it as it plays (~29s); let it finish before the next click advances the slide. Point at the QR: "scan it now — the live Space, Chronos-2 on HF ZeroGPU, is in your
+pocket for the Q&A; upload your own log." Reproducibility: the same code path runs on a laptop (MPS), a CUDA box, or the HPC
+cluster (H100 via Slurm) — nothing in the paper needs special hardware. [S-20]
+10 min Q&A. Backup slides follow, hidden from ToC (each backup carries speaker note: Honest answer to "why only two baselines?" We did not cherry-pick — these are the top non-trained and top trained methods from the external Yu 2025 benchmark. The full ranking table lives in that benchmark, not in this deck; happy to point to it offline. speaker note: The full MAE table behind the S13 headline bars — paper Table 4, all 14 variants across the four logs. The headline compared the latest TSFM per family against the two baselines; this is the complete field. The story holds variant by variant: the latest Chronos / MOIRAI / TimesFM are best or statistically competitive on every log, and the occasional baseline-level number sits with the small/older variants. Amber marks the best (lowest) per log; gray rows are the two baselines. speaker note: Same field, RMSE instead of MAE — sourced from the paper's dedicated RMSE table (Table 5), so it is camera-ready faithful. Switching the error metric does not change the story: the latest zero-shot TSFM per family is best or statistically competitive on every one of the four logs, the same ranking as MAE. speaker note: [S-backup-FT] Paper Table 6 — the detail behind the S15 slope. Five fine-tunable models (Chronos-2 has no LoRA, hence two rows); MAE and RMSE per log for zero-shot vs LoRA vs full tune, grouped by model. Gains over zero-shot are small and dataset-dependent, and several rows get worse — the extreme is MOIRAI-1.1-R-large full fine-tuning on BPI2019-1 (23.06 vs 12.30 zero-shot). This is the per-number evidence behind "skip fine-tuning at PMF data scale." speaker note: The main ER slide showed only Hospital Billing; this generalizes it. On three of four logs TSFMs sit at parity with the baselines. Sepsis is the lone exception — it is both heterogeneous (many rare variants) and intrinsically hard to encode, so ER stays high. This sets up the next Sepsis-specific frame. speaker note: Pre-empts "was the baseline even tuned?" — yes, XGBoost gets per-dataset Optuna search over lagged daily-aggregated features, so the comparison is fair. And "what was the LoRA setup?" — rank 2, alpha 4 on the attention projections (Q/K/V/O), patch 16, batch 32, AdamW at 1e-4 for 3 epochs; full fine-tuning instead follows each model's own published recipe. Deliberately not quoting an Optuna trial count: the exact N isn't pinned in the repo, so I won't invent one — happy to confirm offline. speaker note: The full seven-metric profile — seasonality, trend, stationarity, transition, shifting, correlation, non-Gaussianity — backs the "DF series are unusually hard" claim. Three metrics stand out: frequent regime transitions, distribution shifting over time, and strong non-Gaussianity. The comparison to public forecasting benchmarks stays qualitative: we have no benchmark bars in the repo, so claim only that these three metrics run higher than typical public benchmarks (Li et al. 2025). speaker note: Sepsis is the ER outlier. 790 variants over 999 cases means an enormous long tail and very sparse DF activity per relation — so the forecasted model encodes traces poorly and fitting ratios collapse (TSFMs 4–18%). High heterogeneity (variant tail + sparse DF) drives the tiny ratios. Crucially this is ER only: on MAE, Sepsis is still a win — MOIRAI-2.0 cuts error 28%. Don't conflate the two metrics. Sources: stats_log.tex, results_ER.tex, results_1_mae.tex. speaker note: 7 days is a deliberate choice, not a limitation we hide — it lines up with the Yu 2025 benchmark, the logs' own reporting cadence, and typical TSFM pretraining horizons, so comparisons are clean. We did NOT test month-long horizons; I'd flag that openly as future work, ideally paired with drift detection so a forecast is refreshed when the process shifts rather than extrapolated blindly. speaker note: This was pre-empted on the DF-complexity slide — DF series are highly heterogeneous, so the cross-series attention that helps homogeneous panels does not transfer. Here it's reinforced with the actual experiment: we ran true multivariate inference on MOIRAI, MOIRAI-MoE, and Chronos-2 (all three support it natively), and saw no consistent improvement over univariate, matching Yu 2025. We don't claim multivariate is hopeless — only that off-the-shelf shared attention doesn't help at this scale; dedicated multivariate fine-tuning for PMF is the open direction. {if(re(i)){let c=a(s,i,v);c.length&&(o[v]||(o[v]={idx:v,item:i,matches:[]},l.push(o[v])),c.forEach(({matches:d})=>{o[v].matches.push(...d)}))}}),l}_searchObjectList(e){const s=Dt(e,this.options),{keys:a,records:n}=this._myIndex,o=[];return n.forEach(({$:l,i})=>{if(!re(l))return;let v=[];a.forEach((c,d)=>{v.push(...this._findMatches({key:c,value:l[d],searcher:s}))}),v.length&&o.push({idx:i,item:l,matches:v})}),o}_findMatches({key:e,value:s,searcher:a}){if(!re(s))return[];let n=[];if(Me(s))s.forEach(({v:o,i:l,n:i})=>{if(!re(o))return;const{isMatch:v,score:c,indices:d}=a.searchIn(o);v&&n.push({score:c,key:e,value:o,idx:l,norm:i,indices:d})});else{const{v:o,n:l}=s,{isMatch:i,score:v,indices:c}=a.searchIn(o);i&&n.push({score:v,key:e,value:o,norm:l,indices:c})}return n}}Te.version="7.1.0";Te.createIndex=gn;Te.parseIndex=ga;Te.config=k;Te.parseQuery=_n;Fa(Ba);const Na={class:"bg-main transform",shadow:"~",p:"x-4 y-2",border:"~ transparent rounded dark:main"},Oa=["value","disabled"],za={table:"","w-full":"","border-collapse":""},ja=["border","onClick"],Wa={"text-right":"",op50:"","text-sm":"","table-cell":"","py-2":"","pl-4":"","pr-3":"","vertical-middle":""},Ha=Q({__name:"Goto",setup(t){const e=Y(),s=Y(),a=Y(),n=Y(),o=Y(""),l=Y(0),{go:i,slides:v}=ce();function c(M){return M!=null}const d=R(()=>new Te(v.value.map(M=>M.meta?.slide).filter(c),{keys:["no","title"],threshold:.3,shouldSort:!0,minMatchCharLength:1})),m=R(()=>o.value.startsWith("/")?o.value.substring(1):o.value),p=R(()=>d.value.search(m.value).map(M=>M.item)),y=R(()=>!!p.value.length);function x(){if(y.value){const M=p.value.at(l.value||0);M&&i(M.no)}A()}function A(){o.value="",$e.value=!1}function h(M){M.preventDefault(),l.value++,l.value>=p.value.length&&(l.value=0),F()}function b(M){M.preventDefault(),l.value--,l.value<=-2&&(l.value=p.value.length-1),F()}function F(){const M=n.value?.[l.value];M&&a.value&&(M.offsetTop+M.offsetHeight>a.value.offsetHeight+a.value.scrollTop?a.value.scrollTo({behavior:"smooth",top:M.offsetTop+M.offsetHeight-a.value.offsetHeight+1}):M.offsetTop You can modify this app directly by editing index.html in the Files and versions tab.
- Also don't forget to check the
- Spaces documentation.
-
+
+
+
+
+
+
+
+hideInToc: true).
+Hostile-Q answers rehearsed cold — see SLIDES.md "Required backup slides" + the Q&A defense section.1&&o.push(r):o.push(r),o.push(t[e+3])}else{const a=t[e+0],i=t[e+1],l=t[e+2],c=t[e+3],f=Be(a,i,.5),d=Be(i,l,.5),h=Be(l,c,.5),u=Be(f,d,.5),g=Be(d,h,.5),p=Be(u,g,.5);Ln([a,f,u,p],0,n,o),Ln([p,g,h,c],0,n,o)}return o}function Kl(t,e){return zt(t,0,t.length,e)}function zt(t,e,n,s,o){const r=o||[],a=t[e],i=t[n-1];let l=0,c=1;for(let f=e+1;f0)return;if(Ws){let t=Ws;for(Ws=void 0;t;){const n=t.next;t.next=void 0,t.flags&=-9,t=n}}let e;for(;Us;){let t=Us;for(Us=void 0;t;){const n=t.next;if(t.next=void 0,t.flags&=-9,t.flags&1)try{t.trigger()}catch(s){e||(e=s)}t=n}}if(e)throw e}function Vu(e){for(let t=e.deps;t;t=t.nextDep)t.version=-1,t.prevActiveLink=t.dep.activeLink,t.dep.activeLink=t}function $u(e){let t,n=e.depsTail,s=n;for(;s;){const r=s.prevDep;s.version===-1?(s===n&&(n=r),Dl(s),tm(s)):t=s,s.dep.activeLink=s.prevActiveLink,s.prevActiveLink=void 0,s=r}e.deps=t,e.depsTail=n}function Uo(e){for(let t=e.deps;t;t=t.nextDep)if(t.dep.version!==t.version||t.dep.computed&&(Bu(t.dep.computed)||t.dep.version!==t.version))return!0;return!!e._dirty}function Bu(e){if(e.flags&4&&!(e.flags&16)||(e.flags&=-17,e.globalVersion===rr)||(e.globalVersion=rr,!e.isSSR&&e.flags&128&&(!e.deps&&!e._dirty||!Uo(e))))return;e.flags|=2;const t=e.dep,n=Re,s=Ft;Re=e,Ft=!0;try{Vu(e);const r=e.fn(e._value);(t.version===0||Xe(r,e._value))&&(e.flags|=128,e._value=r,t.version++)}catch(r){throw t.version++,r}finally{Re=n,Ft=s,$u(e),e.flags&=-3}}function Dl(e,t=!1){const{dep:n,prevSub:s,nextSub:r}=e;if(s&&(s.nextSub=r,e.prevSub=void 0),r&&(r.prevSub=s,e.nextSub=void 0),n.subs===e&&(n.subs=s,!s&&n.computed)){n.computed.flags&=-5;for(let i=n.computed.deps;i;i=i.nextDep)Dl(i,!0)}!t&&!--n.sc&&n.map&&n.map.delete(n.key)}function tm(e){const{prevDep:t,nextDep:n}=e;t&&(t.nextDep=n,e.prevDep=void 0),n&&(n.prevDep=t,e.nextDep=void 0)}function nm(e,t){e.effect instanceof sr&&(e=e.effect.fn);const n=new sr(e);t&&fe(n,t);try{n.run()}catch(r){throw n.stop(),r}const s=n.run.bind(n);return s.effect=n,s}function sm(e){e.effect.stop()}let Ft=!0;const Hu=[];function fn(){Hu.push(Ft),Ft=!1}function hn(){const e=Hu.pop();Ft=e===void 0?!0:e}function Kc(e){const{cleanup:t}=e;if(e.cleanup=void 0,t){const n=Re;Re=void 0;try{t()}finally{Re=n}}}let rr=0;class rm{constructor(t,n){this.sub=t,this.dep=n,this.version=n.version,this.nextDep=this.prevDep=this.nextSub=this.prevSub=this.prevActiveLink=void 0}}class zi{constructor(t){this.computed=t,this.version=0,this.activeLink=void 0,this.subs=void 0,this.map=void 0,this.key=void 0,this.sc=0,this.__v_skip=!0}track(t){if(!Re||!Ft||Re===this.computed)return;let n=this.activeLink;if(n===void 0||n.sub!==Re)n=this.activeLink=new rm(Re,this),Re.deps?(n.prevDep=Re.depsTail,Re.depsTail.nextDep=n,Re.depsTail=n):Re.deps=Re.depsTail=n,ju(n);else if(n.version===-1&&(n.version=this.version,n.nextDep)){const s=n.nextDep;s.prevDep=n.prevDep,n.prevDep&&(n.prevDep.nextDep=s),n.prevDep=Re.depsTail,n.nextDep=void 0,Re.depsTail.nextDep=n,Re.depsTail=n,Re.deps===n&&(Re.deps=s)}return n}trigger(t){this.version++,rr++,this.notify(t)}notify(t){Ml();try{for(let n=this.subs;n;n=n.prevSub)n.sub.notify()&&n.sub.dep.notify()}finally{kl()}}}function ju(e){if(e.dep.sc++,e.sub.flags&4){const t=e.dep.computed;if(t&&!e.dep.subs){t.flags|=20;for(let s=t.deps;s;s=s.nextDep)ju(s)}const n=e.dep.subs;n!==e&&(e.prevSub=n,n&&(n.nextSub=e)),e.dep.subs=e}}const di=new WeakMap,jn=Symbol(""),Wo=Symbol(""),ir=Symbol("");function ot(e,t,n){if(Ft&&Re){let s=di.get(e);s||di.set(e,s=new Map);let r=s.get(n);r||(s.set(n,r=new zi),r.map=s,r.key=n),r.track()}}function tn(e,t,n,s,r,i){const o=di.get(e);if(!o){rr++;return}const l=c=>{c&&c.trigger()};if(Ml(),t==="clear")o.forEach(l);else{const c=q(e),a=c&&Ui(n);if(c&&n==="length"){const f=Number(s);o.forEach((u,h)=>{(h==="length"||h===ir||!at(h)&&h>=f)&&l(u)})}else switch((n!==void 0||o.has(void 0))&&l(o.get(n)),a&&l(o.get(ir)),t){case"add":c?a&&l(o.get("length")):(l(o.get(jn)),us(e)&&l(o.get(Wo)));break;case"delete":c||(l(o.get(jn)),us(e)&&l(o.get(Wo)));break;case"set":us(e)&&l(o.get(jn));break}}kl()}function im(e,t){const n=di.get(e);return n&&n.get(t)}function ts(e){const t=ge(e);return t===e?t:(ot(t,"iterate",ir),bt(e)?t:t.map(Vt))}function Yi(e){return ot(e=ge(e),"iterate",ir),e}function qt(e,t){return Gt(e)?_s(ln(e)?Vt(t):t):Vt(t)}const om={__proto__:null,[Symbol.iterator](){return _o(this,Symbol.iterator,e=>qt(this,e))},concat(...e){return ts(this).concat(...e.map(t=>q(t)?ts(t):t))},entries(){return _o(this,"entries",e=>(e[1]=qt(this,e[1]),e))},every(e,t){return Yt(this,"every",e,t,void 0,arguments)},filter(e,t){return Yt(this,"filter",e,t,n=>n.map(s=>qt(this,s)),arguments)},find(e,t){return Yt(this,"find",e,t,n=>qt(this,n),arguments)},findIndex(e,t){return Yt(this,"findIndex",e,t,void 0,arguments)},findLast(e,t){return Yt(this,"findLast",e,t,n=>qt(this,n),arguments)},findLastIndex(e,t){return Yt(this,"findLastIndex",e,t,void 0,arguments)},forEach(e,t){return Yt(this,"forEach",e,t,void 0,arguments)},includes(...e){return So(this,"includes",e)},indexOf(...e){return So(this,"indexOf",e)},join(e){return ts(this).join(e)},lastIndexOf(...e){return So(this,"lastIndexOf",e)},map(e,t){return Yt(this,"map",e,t,void 0,arguments)},pop(){return Ds(this,"pop")},push(...e){return Ds(this,"push",e)},reduce(e,...t){return qc(this,"reduce",e,t)},reduceRight(e,...t){return qc(this,"reduceRight",e,t)},shift(){return Ds(this,"shift")},some(e,t){return Yt(this,"some",e,t,void 0,arguments)},splice(...e){return Ds(this,"splice",e)},toReversed(){return ts(this).toReversed()},toSorted(e){return ts(this).toSorted(e)},toSpliced(...e){return ts(this).toSpliced(...e)},unshift(...e){return Ds(this,"unshift",e)},values(){return _o(this,"values",e=>qt(this,e))}};function _o(e,t,n){const s=Yi(e),r=s[t]();return s!==e&&!bt(e)&&(r._next=r.next,r.next=()=>{const i=r._next();return i.done||(i.value=n(i.value)),i}),r}const lm=Array.prototype;function Yt(e,t,n,s,r,i){const o=Yi(e),l=o!==e&&!bt(e),c=o[t];if(c!==lm[t]){const u=c.apply(e,i);return l?Vt(u):u}let a=n;o!==e&&(l?a=function(u,h){return n.call(this,qt(e,u),h,e)}:n.length>2&&(a=function(u,h){return n.call(this,u,h,e)}));const f=c.call(o,a,s);return l&&r?r(f):f}function qc(e,t,n,s){const r=Yi(e),i=r!==e&&!bt(e);let o=n,l=!1;r!==e&&(i?(l=s.length===0,o=function(a,f,u){return l&&(l=!1,a=qt(e,a)),n.call(this,a,qt(e,f),u,e)}):n.length>3&&(o=function(a,f,u){return n.call(this,a,f,u,e)}));const c=r[t](o,...s);return l?qt(e,c):c}function So(e,t,n){const s=ge(e);ot(s,"iterate",ir);const r=s[t](...n);return(r===-1||r===!1)&&wr(n[0])?(n[0]=ge(n[0]),s[t](...n)):r}function Ds(e,t,n=[]){fn(),Ml();const s=ge(e)[t].apply(e,n);return kl(),hn(),s}const cm=At("__proto__,__v_isRef,__isVue"),Uu=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(at));function am(e){at(e)||(e=String(e));const t=ge(this);return ot(t,"has",e),t.hasOwnProperty(e)}class Wu{constructor(t=!1,n=!1){this._isReadonly=t,this._isShallow=n}get(t,n,s){if(n==="__v_skip")return t.__v_skip;const r=this._isReadonly,i=this._isShallow;if(n==="__v_isReactive")return!r;if(n==="__v_isReadonly")return r;if(n==="__v_isShallow")return i;if(n==="__v_raw")return s===(r?i?Ju:Yu:i?zu:Gu).get(t)||Object.getPrototypeOf(t)===Object.getPrototypeOf(s)?t:void 0;const o=q(t);if(!r){let c;if(o&&(c=om[n]))return c;if(n==="hasOwnProperty")return am}const l=Reflect.get(t,n,Ie(t)?t:s);if((at(n)?Uu.has(n):cm(n))||(r||ot(t,"get",n),i))return l;if(Ie(l)){const c=o&&Ui(n)?l:l.value;return r&&be(c)?Dt(c):c}return be(l)?r?Dt(l):_t(l):l}}class Ku extends Wu{constructor(t=!1){super(!1,t)}set(t,n,s,r){let i=t[n];const o=q(t)&&Ui(n);if(!this._isShallow){const a=Gt(i);if(!bt(s)&&!Gt(s)&&(i=ge(i),s=ge(s)),!o&&Ie(i)&&!Ie(s))return a||(i.value=s),!0}const l=o?Number(n){if(Di(e)){const{children:n,loc:s}=e,{slotName:r,slotProps:i}=V0(e,t),o=[t.prefixIdentifiers?"_ctx.$slots":"$slots",r,"{}","undefined","true"];let l=2;i&&(o[2]=i,l=3),n.length&&(o[3]=Cs([],n,!1,!1,s),l=4),t.scopeId&&!t.slotted&&(l=5),o.splice(l),e.codegenNode=Ge(t.helper(Bh),o,s)}};function V0(e,t){let n='"default"',s;const r=[];for(let i=0;i(e[t]=aS(()=>_r=!0),e),{}),El=kr.reduce((e,t)=>{const n=go[t];return e[t]=(s,r=!1,i=!1)=>(_r||dS(),n.schedule(s,r,i)),e},{}),fS=kr.reduce((e,t)=>(e[t]=go[t].cancel,e),{});kr.reduce((e,t)=>(e[t]=()=>go[t].process(bs),e),{});const hS=e=>go[e].process(bs),qd=e=>{_r=!1,bs.delta=_l?Wd:Math.max(Math.min(e-bs.timestamp,uS),1),bs.timestamp=e,Sl=!0,kr.forEach(hS),Sl=!1,_r&&(_l=!1,Kd(qd))},dS=()=>{_r=!0,_l=!0,Sl||Kd(qd)},Gd=()=>bs;function zd(e,t){var n={};for(var s in e)Object.prototype.hasOwnProperty.call(e,s)&&t.indexOf(s)<0&&(n[s]=e[s]);if(e!=null&&typeof Object.getOwnPropertySymbols=="function")for(var r=0,s=Object.getOwnPropertySymbols(e);r{const n=Object.assign(Object.assign({},e),t),s={};for(const r in n)e[r]!==void 0&&t[r]!==void 0&&(s[r]=ip(e[r],t[r]));return r=>{for(const i in s)n[i]=s[i](r);return n}};function Su(e){const t=Lr.parse(e),n=t.length;let s=0,r=0,i=0;for(let o=0;oi&&(a=o,i=l)}i>n&&(a-e>1&&pt(t,e,a,n,r),r.push(t[a]),s-a>1&&pt(t,a,s,n,r))}function Ee(t,e){const s=t.length-1,n=[t[0]];return pt(t,0,s,e,n),n.push(t[s]),n}function Ct(t,e,s=!1){if(t.length<=2)return t;const n=e*e;return t=s?t:Pe(t,n),t=Ee(t,n),t}var O=class{constructor(t){this.drauu=t,this.event=void 0,this.point=void 0,this.start=void 0,this.el=null}onSelected(t){}onUnselected(){}onStart(t){}onMove(t){return!1}onEnd(t){}get brush(){return this.drauu.brush}get shiftPressed(){return this.drauu.shiftPressed}get altPressed(){return this.drauu.altPressed}get svgElement(){return this.drauu.el}getMousePosition(t){const e=this.drauu.el,s=this.drauu.options.cssZoom??1,n=this.drauu.options.coordinateScale??1,r=this.drauu.options.offset??{x:0,y:0};if(this.drauu.options.coordinateTransform===!1){const i=this.drauu.el.getBoundingClientRect();return{x:(t.pageX/s-i.left+r.x)*n,y:(t.pageY/s-i.top+r.y)*n,pressure:t.pressure}}else{const i=this.drauu.svgPoint;i.x=t.clientX/s+r.x,i.y=t.clientY/s+r.y;const a=i.matrixTransform(e.getScreenCTM()?.inverse());return{x:a.x*n,y:a.y*n,pressure:t.pressure}}}createElement(t,e){const s=document.createElementNS("http://www.w3.org/2000/svg",t),n=e?{...this.brush,...e}:this.brush;return s.setAttribute("fill",n.fill??"transparent"),s.setAttribute("stroke",n.color),s.setAttribute("stroke-width",n.size.toString()),s.setAttribute("stroke-linecap","round"),n.dasharray&&s.setAttribute("stroke-dasharray",n.dasharray),s}attr(t,e){this.el.setAttribute(t,typeof e=="string"?e:e.toFixed(k))}_setEvent(t){this.event=t,this.point=this.getMousePosition(t)}_eventDown(t){return this._setEvent(t),this.start=this.point,this.onStart(this.point)}_eventMove(t){return this._setEvent(t),this.onMove(this.point)}_eventUp(t){return this._setEvent(t),this.onEnd(this.point)}},Me=class K extends O{constructor(...e){super(...e),this.points=[],this.count=0}onStart(e){if(this.el=this.createElement("path",{fill:"transparent"}),this.points=[e],this.brush.arrowEnd){this.arrowId=Tt();const s=Kt(this.arrowId,this.brush.color);this.el.appendChild(s)}return this.el}onMove(e){return this.el||this.onStart(e),this.points[this.points.length-1]!==e&&(this.points.push(e),this.count+=1),this.count>5&&(this.points=Ct(this.points,1,!0),this.count=0),this.attr("d",K.toSvgData(this.points)),!0}onEnd(){const e=this.el;if(this.el=null,!e)return!1;if(e.setAttribute("d",K.toSvgData(Ct(this.points,1,!0))),!e.getTotalLength()){const{x:s,y:n}=this.points[0],r=this.brush.size/2;e.setAttribute("d",`M ${s-r} ${n} a ${r},${r} 0 1,0 ${r*2},0 a ${r},${r} 0 1,0 ${-r*2},0`),e.setAttribute("fill",this.brush.color),e.setAttribute("stroke-width","0")}return!0}static line(e,s){const n=s.x-e.x,r=s.y-e.y;return{length:Math.sqrt(n**2+r**2),angle:Math.atan2(r,n)}}static controlPoint(e,s,n,r){const i=s||e,a=n||e,o=.2,l=K.line(i,a),p=l.angle+(r?Math.PI:0),v=l.length*o;return{x:e.x+Math.cos(p)*v,y:e.y+Math.sin(p)*v}}static bezierCommand(e,s,n){const r=K.controlPoint(n[s-1],n[s-2],e),i=K.controlPoint(e,n[s-1],n[s+1],!0);return`C ${r.x.toFixed(k)},${r.y.toFixed(k)} ${i.x.toFixed(k)},${i.y.toFixed(k)} ${e.x.toFixed(k)},${e.y.toFixed(k)}`}static toSvgData(e){return e.reduce((s,n,r,i)=>r===0?`M ${n.x.toFixed(k)},${n.y.toFixed(k)}`:`${s} ${K.bezierCommand(n,r,i)}`,"")}},Ce=class extends O{onStart(t){return this.el=this.createElement("ellipse"),this.attr("cx",t.x),this.attr("cy",t.y),this.el}onMove(t){if(!this.el||!this.start)return!1;let[e,s]=nt(t.x-this.start.x),[n,r]=nt(t.y-this.start.y);if(this.shiftPressed){const i=Math.min(e,n);e=i,n=i}if(this.altPressed)this.attr("cx",this.start.x),this.attr("cy",this.start.y),this.attr("rx",e),this.attr("ry",n);else{const[i,a]=[this.start.x,this.start.x+e*s].sort(st),[o,l]=[this.start.y,this.start.y+n*r].sort(st);this.attr("cx",(i+a)/2),this.attr("cy",(o+l)/2),this.attr("rx",(a-i)/2),this.attr("ry",(l-o)/2)}return!0}onEnd(){const t=this.el;if(this.el=null,!t)return!1;try{if(!t.getTotalLength())return!1}catch{return!1}return!0}},ke=class extends O{constructor(...t){super(...t),this.pathSubFactor=20,this.pathFragments=[],this._erased=[]}onSelected(t){const e=(s,n)=>{if(s&&s.length)for(let r=0;r`.
+
+Semantic kebab-case naming. Full per-beat mapping in
+`slides/talk_design/workflow.md` (Figure naming convention).
+
+## Currently expected (drop files here as you produce them)
+
+| File | Used by | Notes |
+|---|---|---|
+| `dfg-evolution.gif` (or `.mp4`) | beat 2 | DFG t₁→t₂→t₃→forecasted t₄ animation, 10–15s |
+| `bpi2017-drift-xgb-only.png` | beat 3 | Ground truth + XGBoost only — TSFM line stripped for callback |
+| `tsfm-release-timeline.svg` | beat 6 | 2023→2026 horizontal timeline, 3 family lanes, dots per version |
+| `results-mae-bars.png` | beat 7a | 4 panels, 5 horizontal bars per panel, baselines gray + TSFMs accent |
+| `bpi2017-drift-with-tsfm.png` | beat 7b | Full reveal — actual + XGBoost + TSFM (paper Fig 1 BPI2017 panel) |
+| `ft-slope.png` | beat 8 | 3-point slope ZS→LoRA→Full-FT, one line per (model × dataset), colored by dataset |
+| `ft-compute-bars.png` | beat 8 | Log-scale wall-clock bars, 3 ZS + 3 LoRA + 3 Full-FT + 1 XGBoost |
+| `er-bars.png` | beat 9 | Compact 4-panel ER bars, 3 TSFMs + 2 baselines, Truth/Training reference lines |
+| `demo-screencast.mp4` | beat 11 | ~2 min pre-recorded screencast: load log → pick TSFM → render forecasted DFG |
+| `baseline-ranking-full.png` | backup | Full benchmark ranking from Yu 2025 |
+| `rmse-full.png` | backup | Full RMSE table |
+| `df-complexity-radar.png` | backup | 7-metric DF complexity vs 21 standard benchmarks |
+| `sepsis-variants.png` | backup | Sepsis trace variant distribution / DFG showing heterogeneity |
+
+When a file lands here, the next `/03-content-pass
`).
+
+## Source pipeline
+
+- For the 4 plots derived from existing `.eps` in `slides/figures/`:
+ convert with `pdftocairo -png -r 300 source.eps target` and rename per the table above.
+- For new charts (results bars, slope, compute, ER): generate from your experiment outputs
+ with matplotlib; save as PNG at 2× resolution.
+- For animations: Manim or matplotlib + ffmpeg.
+- For the screencast: any screen-recording tool; export at 720p+, ≤2 min.
diff --git a/figures/_preview-mae-bars-v2.png b/figures/_preview-mae-bars-v2.png
new file mode 100644
index 0000000000000000000000000000000000000000..94b80e142cb533e253c8e4b5b2b98580b764f159
Binary files /dev/null and b/figures/_preview-mae-bars-v2.png differ
diff --git a/figures/_preview-mae-bars.png b/figures/_preview-mae-bars.png
new file mode 100644
index 0000000000000000000000000000000000000000..07a933ad2aad79fe19e2aad8cac0d29fd6bed90f
Binary files /dev/null and b/figures/_preview-mae-bars.png differ
diff --git a/figures/_preview-mae-heatmap.png b/figures/_preview-mae-heatmap.png
new file mode 100644
index 0000000000000000000000000000000000000000..a1077fa65f6172983dc0b89c71608058dabd5eec
--- /dev/null
+++ b/figures/_preview-mae-heatmap.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:0e79f45a3c2b630862f9b3aef6847aba2b542704dcdab0b4e0781f7752dba5eb
+size 103457
diff --git a/figures/_preview-mae-hero.png b/figures/_preview-mae-hero.png
new file mode 100644
index 0000000000000000000000000000000000000000..e6516c4131a664f627811e0356a0de2333c600cb
Binary files /dev/null and b/figures/_preview-mae-hero.png differ
diff --git a/figures/bpi2017-drift-with-tsfm.png b/figures/bpi2017-drift-with-tsfm.png
new file mode 100644
index 0000000000000000000000000000000000000000..232e003c4c575e0ceb16d72f33794f7ccb88b0bb
--- /dev/null
+++ b/figures/bpi2017-drift-with-tsfm.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:5efcd414972695ce3b429b25991b596605eb0db41ef9f856da433804fbc923bb
+size 223115
diff --git a/figures/bpi2017-drift-xgb-only.png b/figures/bpi2017-drift-xgb-only.png
new file mode 100644
index 0000000000000000000000000000000000000000..a035a2d46c48d85b358f9038cdbd52741614113c
--- /dev/null
+++ b/figures/bpi2017-drift-xgb-only.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:ce058b988b83cf3c6c543c8e917f1193f3a69b34754e3cd4b5c26038e0b055c3
+size 161851
diff --git a/figures/demo-1-bundled.png b/figures/demo-1-bundled.png
new file mode 100644
index 0000000000000000000000000000000000000000..54c2c03f8566fae6b942322bf99ddfa9a0548991
--- /dev/null
+++ b/figures/demo-1-bundled.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:161ffb367a50ce9d0d6baa3bbddc74c856ac39a1cac8f2e44e7f37f51aa6af48
+size 469253
diff --git a/figures/demo-2-metrics.png b/figures/demo-2-metrics.png
new file mode 100644
index 0000000000000000000000000000000000000000..3344993f908a7ded26429389f8e25193f0130e72
Binary files /dev/null and b/figures/demo-2-metrics.png differ
diff --git a/figures/demo-3-diff-abs.png b/figures/demo-3-diff-abs.png
new file mode 100644
index 0000000000000000000000000000000000000000..f44226b1aa12aee0e47f18c85f45656f0e8f1eaa
--- /dev/null
+++ b/figures/demo-3-diff-abs.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b35837a183e112728a7914ae73215a24b311758d05971beb66289b7836c8535c
+size 397482
diff --git a/figures/demo-4-diff-rel.png b/figures/demo-4-diff-rel.png
new file mode 100644
index 0000000000000000000000000000000000000000..219441c4ef6fb662e47cab32c262e68e9b6de0a4
--- /dev/null
+++ b/figures/demo-4-diff-rel.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:3b383a1d3e5b969366d4611b8db43fb7131c270c33476dd8026fa52d9ee0f90b
+size 407860
diff --git a/figures/demo-5-live.png b/figures/demo-5-live.png
new file mode 100644
index 0000000000000000000000000000000000000000..58dc1512524900ac762fb81953cb9aad632881e6
--- /dev/null
+++ b/figures/demo-5-live.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:ce833958b069755c3887ee4944a693d648a422d2a553f072772428f64ef9aacc
+size 521031
diff --git a/figures/demo-qr.png b/figures/demo-qr.png
new file mode 100644
index 0000000000000000000000000000000000000000..1815aa1d604c4ac1c08a943ccd01e1eb4db6bfda
Binary files /dev/null and b/figures/demo-qr.png differ
diff --git a/figures/demo-screencast-poster.png b/figures/demo-screencast-poster.png
new file mode 100644
index 0000000000000000000000000000000000000000..64904ef12b45820a29dd97849be94544ea790d11
--- /dev/null
+++ b/figures/demo-screencast-poster.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:4cea831f877f43817face018ff951d6339b82b4b810568ae0b60a2912e3a5c07
+size 195106
diff --git a/figures/demo-screencast.mp4 b/figures/demo-screencast.mp4
new file mode 100644
index 0000000000000000000000000000000000000000..a39e523db3af9697493d1586d1a38b64d45bcf78
--- /dev/null
+++ b/figures/demo-screencast.mp4
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:c81b4951551d6063f742b653f124d4ff360b79d0a77addcd307b2880ed6e249d
+size 1596949
diff --git a/figures/df-complexity-radar.png b/figures/df-complexity-radar.png
new file mode 100644
index 0000000000000000000000000000000000000000..d87f9ab785480e2b5d83df1ad056578ec069231f
--- /dev/null
+++ b/figures/df-complexity-radar.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:bf7311972da19f50829c9d094e3049bdcb8049f0b18ab89d3f9445ae4c6abd0a
+size 301927
diff --git a/figures/er-bars.png b/figures/er-bars.png
new file mode 100644
index 0000000000000000000000000000000000000000..f7cd026fed7675a453d05a11b86a18a39c3e2e22
--- /dev/null
+++ b/figures/er-bars.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:84295ae552450bbfeb69f255dae10470f475d568b249e1f52a8188047f9e89ce
+size 152409
diff --git a/figures/er-hospital-billing.png b/figures/er-hospital-billing.png
new file mode 100644
index 0000000000000000000000000000000000000000..0bb921a89cfe8a992150b105ecbdf7e1a7246a9c
Binary files /dev/null and b/figures/er-hospital-billing.png differ
diff --git a/figures/ft-slope.png b/figures/ft-slope.png
new file mode 100644
index 0000000000000000000000000000000000000000..9981d64e915bb230ee2efdcd26d412ccf62d246b
--- /dev/null
+++ b/figures/ft-slope.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:820c9685eb9d9a21ab76bb225100b5926789eb6da425181c1cb75471531ebdd1
+size 167979
diff --git a/figures/ft-table.png b/figures/ft-table.png
new file mode 100644
index 0000000000000000000000000000000000000000..3bada16a859e2dd7b10504a9d07c371c147152aa
--- /dev/null
+++ b/figures/ft-table.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:801f156e98434fa81855bec8d025e7fe969c9db38233ebd8a89dbfa9eb7f85d1
+size 157514
diff --git a/figures/mae-full.png b/figures/mae-full.png
new file mode 100644
index 0000000000000000000000000000000000000000..7f30bc83a68b8e132477e8d5f30397e3b28ab16a
--- /dev/null
+++ b/figures/mae-full.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b1e58f18178e5740319e805c434798c49fabfd1d38c94005aa88384613421375
+size 137694
diff --git a/figures/results-mae-bars.png b/figures/results-mae-bars.png
new file mode 100644
index 0000000000000000000000000000000000000000..f603362945fc90a94af497cd1c37506fc9de6010
--- /dev/null
+++ b/figures/results-mae-bars.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2d20280ecf6bc62662c4af3918ec4ea80e0a48915ec1283c6cae9ddacf3e15b3
+size 117985
diff --git a/figures/rmse-full.png b/figures/rmse-full.png
new file mode 100644
index 0000000000000000000000000000000000000000..54ca575366b4429e4c1c53a49325038c3c3e9607
--- /dev/null
+++ b/figures/rmse-full.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:c28033596445e0b58c473c57cc0313419e3c013bfb89e863a820cede62a6b737
+size 138648
diff --git a/figures/s14-drift-tsfm.png b/figures/s14-drift-tsfm.png
new file mode 100644
index 0000000000000000000000000000000000000000..6ab0b7d60474fb6f760a868f699c1c09e3cb85b9
--- /dev/null
+++ b/figures/s14-drift-tsfm.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e0791a833d62fa03b84f9c8dfd61e9cd0c1b5d9c10256261475e57c1f2617aa3
+size 154739
diff --git a/figures/s14-intermittent-tsfm.png b/figures/s14-intermittent-tsfm.png
new file mode 100644
index 0000000000000000000000000000000000000000..c88368881a0671c8578e36ff7b2d4d39e5f6d3eb
--- /dev/null
+++ b/figures/s14-intermittent-tsfm.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6e79f1b7a7556614f8472ed98422d062a452980ebf522f4b1f99531b4a1cfb76
+size 111812
diff --git a/figures/s5-drift-truth.png b/figures/s5-drift-truth.png
new file mode 100644
index 0000000000000000000000000000000000000000..75994d31ce12c4dffb04bcf04bded86969399c2e
Binary files /dev/null and b/figures/s5-drift-truth.png differ
diff --git a/figures/s5-intermittent-truth.png b/figures/s5-intermittent-truth.png
new file mode 100644
index 0000000000000000000000000000000000000000..09b2a1ee8075b3203d20d9b13887e30ff5ab13d6
Binary files /dev/null and b/figures/s5-intermittent-truth.png differ
diff --git a/figures/s6-drift-xgb-box.png b/figures/s6-drift-xgb-box.png
new file mode 100644
index 0000000000000000000000000000000000000000..e7de3a4b87d9458bdd627293ef3846c3ab1a55b2
--- /dev/null
+++ b/figures/s6-drift-xgb-box.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:83f3cd657143ad8dd34d2f2e82e0b85a89b6a42f990749c52733d405a9dba341
+size 122436
diff --git a/figures/s6-drift-xgb.png b/figures/s6-drift-xgb.png
new file mode 100644
index 0000000000000000000000000000000000000000..494843b91fce200a2e6ffdbaa2a6c595bb8107c5
--- /dev/null
+++ b/figures/s6-drift-xgb.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:812db6e266bc7092c03d04183a6fb59c0497c1479e2605b7bf6823cb66295a3f
+size 123237
diff --git a/figures/s6-intermittent-xgb-arrow.png b/figures/s6-intermittent-xgb-arrow.png
new file mode 100644
index 0000000000000000000000000000000000000000..ef0b457b79344e9fc27dd2069efc60be31492e30
--- /dev/null
+++ b/figures/s6-intermittent-xgb-arrow.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:f48ed19fc9d516a42a06c1b6a0ba4ddc79c2dd070e21d2c6ccca7e9f78341cf8
+size 110560
diff --git a/figures/s6-intermittent-xgb.png b/figures/s6-intermittent-xgb.png
new file mode 100644
index 0000000000000000000000000000000000000000..c9e0c380bd764c55de59006b0f5dbbefff087843
--- /dev/null
+++ b/figures/s6-intermittent-xgb.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:3a945f8427828280f16be851f668055d90a592d17b095fd7df818c0797afae46
+size 106491
diff --git a/figures/s7-complexity-radar.png b/figures/s7-complexity-radar.png
new file mode 100644
index 0000000000000000000000000000000000000000..e622b180dac864f40541229d187a6b396b08a91e
--- /dev/null
+++ b/figures/s7-complexity-radar.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:94f342c1738f9e8daeb4f924c47c3d812920deef51f7d309722fa719c09d6ed8
+size 126771
diff --git a/index.html b/index.html
index b0c4b3666032a737f3903db53e6a8a9272483e28..2700ddb4af9e240d0ace3183ccecf113a4ad550f 100644
--- a/index.html
+++ b/index.html
@@ -1,19 +1,43 @@
-
-
-
-
-
-
Welcome to your static Space!
-