Skip to content

Commit a3019e3

Browse files
author
Florence Bockting
committed
chore: update developer-notes
1 parent 9611656 commit a3019e3

2 files changed

Lines changed: 91 additions & 20 deletions

File tree

notes/developer-notes.Rmd

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ knitr::opts_chunk$set(
2020

2121
> **Status:** In Progress
2222
> **Base branch:** `loo-v3.0.0`
23-
> **Compare branch:** `pred_measure`
23+
> **Compare branch:** `pred_measure` (+ `integrate-loo_compare`)
2424
> **Related PR:** [#363](https://github.com/stan-dev/loo/pull/363)
2525
> **Contributors:** @florence-bockting, @avehtari, @VisruthSK, @jgabry
26-
> **Last updated:** 2026-07-03
26+
> **Last updated:** 2026-07-07
2727
2828
These notes document internal design decisions and ongoing work for the
2929
`pred_measure` feature. This PR **adds** the new API.
@@ -37,7 +37,7 @@ These notes document internal design decisions and ongoing work for the
3737
| Scoring rules (`measure_rps`) | Done |
3838
| Documentation | In progress |
3939
| `group_ids` grouping | Not started |
40-
| `loo_compare` integration | Not started |
40+
| `loo_compare` integration | Done (`integrate-loo_compare`) |
4141

4242
## Scope of this PR (`pred_measure` vs `loo-v3.0.0`)
4343

@@ -52,6 +52,7 @@ These notes document internal design decisions and ongoing work for the
5252
- `vignettes/migration-guide.Rmd`
5353
- Website-only articles: `overview-measures.Rmd`, `pred-measure-workflow.Rmd`
5454
- Test suite + pre-fitted fixtures + `test_data_generation.R`
55+
- `loo_compare()` multi-measure path for `loo_pred_measure` objects
5556

5657
### Changed on existing code (implementations retained)
5758

@@ -61,6 +62,9 @@ These notes document internal design decisions and ongoing work for the
6162
- `elpd()` — refactored to `.elpd_matrix_impl()` to avoid double deprecation
6263
warnings
6364
- Minor doc cross-references in `compare.R`, `psislw.R`
65+
- `loo_compare()` — extended for `loo_pred_measure` objects: `rank_by`, multi-measure
66+
paired diffs, updated `print.compare.loo(measures = ...)`; classic `loo` path unchanged
67+
- `R/loo-glossary.R` — multi-measure comparison columns (`{measure}_diff`, `rank_by`, etc.)
6468
- `NEWS.md`, `NAMESPACE`, `_pkgdown.yml`, pkgdown CI workflow
6569

6670
## Design decisions (resolved)
@@ -111,6 +115,29 @@ Design choices **internal to `pred_measure`**:
111115
- [ ] Verify `kfold_pred_measure()` with categorical/multinomial examples
112116
end-to-end (penguins fixture exists; confirm test/doc coverage)
113117

118+
### D4: `loo_compare()` for `loo_pred_measure` objects
119+
120+
**Decision:** Extend existing `loo_compare()`, not a separate function.
121+
122+
- When all inputs are `loo_pred_measure` objects, compute paired differences for
123+
every measure common to all models
124+
- Rank models by `rank_by` (default `"elpd"`); top-ranked model is the reference
125+
for all `{measure}_diff` columns
126+
- ELPD-family measures keep `elpd_diff` / `se_diff`; other measures use
127+
`{measure}_diff` / `{measure}_se_diff`
128+
- `p_worse` and `diag_diff` apply to ELPD only; `diag_elpd` per model as before
129+
- Loss measures (MSE, RMSE, MAE, IC) compared on a utility scale (negated) so
130+
worse models have negative diffs, consistent with ELPD
131+
- Pointwise SEs use the same paired formula as ELPD when the overall estimate is
132+
a sum or mean of pointwise contributions; otherwise `{measure}_se_diff` is `NA`
133+
(e.g. `r2`, `mse`, `rmse`)
134+
- Reuse `elpd_diffs`, `se_elpd_diff`, `diag_diff`, `diag_elpd`, and many-model
135+
order-statistic check (with `rank_by` when applicable)
136+
- `print.compare.loo(measures = ...)` shows one or all measure diff tables
137+
138+
Implemented on branch `integrate-loo_compare`; tests in `test_compare.R` with
139+
fixture `test_data_roaches_compare.Rds`.
140+
114141
## Open decisions
115142

116143
### D1: Sign convention for pointwise estimates
@@ -138,7 +165,7 @@ Design choices **internal to `pred_measure`**:
138165
- [x] In `*_pred_measure()`, compute `elpd` as base when `ylp` supplied;
139166
require explicit `measure = "ic"` for information criterion
140167
- [x] Document and test deprecated vs new API comparisons *(see appendix)*
141-
- [ ] Provide an interface to `loo_compare` and verify consistency
168+
- [x] Provide an interface to `loo_compare` and verify consistency
142169
- [ ] Resolve `r_eff` handling *(see D3)*
143170

144171
### Implementation
@@ -156,7 +183,8 @@ Design choices **internal to `pred_measure`**:
156183
- [x] Online-only articles published via `_pkgdown.yml`
157184
- [ ] Formula derivations article (`pred_measure-formulas.Rmd`)
158185
- [ ] Detailed per-measure descriptions (derivations where appropriate)
159-
- [ ] Extend glossary (`R/loo-glossary.R`) — measure, metric, score, utility, loss
186+
- [x] Extend glossary (`R/loo-glossary.R`) — multi-measure `loo_compare` columns
187+
- [ ] Extend glossary further — measure, metric, score, utility, loss (general terms)
160188

161189
### Grouping via `group_ids`
162190

@@ -170,8 +198,8 @@ Design choices **internal to `pred_measure`**:
170198

171199
- Rename `ic``information_criteria` for clarity?
172200
- Should `measure_elpd()` also return `ic`, or keep them separate?
173-
- What defines class `"loo"` on measure objects? (e.g. deprecated `elpd_generic`
174-
inherits `"loo"`)
201+
- What defines class `"loo"` on measure objects? `loo_pred_measure` inherits `"loo"`
202+
(see `integrate-loo_compare`); deprecated `elpd_generic` also inherits `"loo"`.
175203
- Should `elpd` always be computed when `ylp` is supplied, or allow
176204
`loo_pred_measure()` for non-ELPD measures only?
177205

notes/developer-notes.md

Lines changed: 56 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ Developer Notes: `pred_measure` Feature
1414

1515
> **Status:** In Progress
1616
> **Base branch:** `loo-v3.0.0`
17-
> **Compare branch:** `add-pred-measure`
17+
> **Compare branch:** `pred_measure` (+ `integrate-loo_compare`)
1818
> **Related PR:** [\#363](https://github.com/stan-dev/loo/pull/363)
1919
> **Contributors:** @florence-bockting, @avehtari, @VisruthSK, @jgabry
20-
> **Last updated:** 2026-07-03
20+
> **Last updated:** 2026-07-07
2121
2222
These notes document internal design decisions and ongoing work for the
2323
`pred_measure` feature. This PR **adds** the new API on top of
@@ -39,7 +39,7 @@ For the merge summary, see the PR description
3939
| Scoring rules (`measure_rps`) | Done |
4040
| Documentation | In progress |
4141
| `group_ids` grouping | Not started |
42-
| `loo_compare` integration | Not started |
42+
| `loo_compare` integration | Done (`integrate-loo_compare`) |
4343

4444
------------------------------------------------------------------------
4545

@@ -59,6 +59,8 @@ For the merge summary, see the PR description
5959
- Website-only articles: `overview-measures.Rmd`,
6060
`pred-measure-workflow.Rmd`
6161
- Test suite + pre-fitted fixtures + `test_data_generation.R`
62+
- `loo_compare()` multi-measure path for `loo_pred_measure` objects
63+
(`integrate-loo_compare`)
6264

6365
### Changed on existing code (implementations retained)
6466

@@ -69,6 +71,11 @@ For the merge summary, see the PR description
6971
- `elpd()` — refactored to `.elpd_matrix_impl()` to avoid double
7072
deprecation warnings
7173
- Minor doc cross-references in `compare.R`, `psislw.R`
74+
- `loo_compare()` — extended for `loo_pred_measure` objects: `rank_by`,
75+
multi-measure paired diffs, updated `print.compare.loo(measures = ...)`;
76+
classic `loo` path unchanged
77+
- `R/loo-glossary.R` — multi-measure comparison columns (`{measure}_diff`,
78+
`rank_by`, etc.)
7279
- `NEWS.md`, `NAMESPACE`, `_pkgdown.yml`, pkgdown CI workflow
7380

7481
------------------------------------------------------------------------
@@ -127,17 +134,51 @@ Design choices **internal to `pred_measure`** (not a migration from
127134
examples end-to-end (penguins fixture exists; confirm test/doc
128135
coverage)
129136

137+
### D4: `loo_compare()` for `loo_pred_measure` objects
138+
139+
**Decision:** Extend existing `loo_compare()`
140+
141+
- When all inputs are `loo_pred_measure` objects, compute paired
142+
differences for every measure common to all models
143+
- Rank models by `rank_by` (default `"elpd"`); top-ranked model is the
144+
reference for all `{measure}_diff` columns
145+
- ELPD-family measures keep `elpd_diff` / `se_diff`; other measures use
146+
`{measure}_diff` / `{measure}_se_diff`
147+
- `p_worse` and `diag_diff` apply to ELPD only; `diag_elpd` per model as
148+
before
149+
- Loss measures (MSE, RMSE, MAE, IC, Brier score, SRPS) compared on a common
150+
utility scale (higher is better): sign flipped from the raw loss orientation
151+
so worse models have negative diffs, consistent with ELPD. Orientation is
152+
read from `measure_revert_sign` on each `*_pred_measure()` result; result
153+
attribute
154+
`sign_converted_measures` records affected measures. A short message is
155+
emitted at compare time; full interpretation is in `?loo_compare` /
156+
`?loo-glossary`.
157+
- Pointwise SEs use the same paired formula as ELPD when the overall
158+
estimate is a sum or mean of pointwise contributions; otherwise
159+
`{measure}_se_diff` is `NA` (e.g. `r2`, `mse`, `rmse`)
160+
- Reuse `elpd_diffs`, `se_elpd_diff`, `diag_diff`, `diag_elpd`, and
161+
many-model order-statistic check (with `rank_by` when applicable)
162+
- `print.compare.loo(measures = ...)` shows one or all measure diff tables
163+
164+
Implemented on branch `integrate-loo_compare`; tests in `test_compare.R`
165+
with fixture `test_data_roaches_compare.Rds`.
166+
130167
------------------------------------------------------------------------
131168

132169
## Open decisions
133170

134171
### D1: Sign convention for pointwise estimates
135172

136-
- **Context:** Measures differ in orientation (`rps`: lower is better;
137-
`srps`: higher is better). Aligning orientations may help comparisons.
138-
- **Options:** `lower_is_better`, `orientation = "utility" / "loss"`,
139-
`revert_sign` (currently internal on some `measure_*()` functions)
140-
- **Decision:** *pending*
173+
- **Context:** Measures differ in orientation (e.g. ELPD/CRPS on a utility
174+
scale; MSE and Brier score as losses). `loo_compare()` aligns them for
175+
paired differences.
176+
- **Decision (for `loo_compare`):** Each `*_pred_measure()` result stores the
177+
`revert_sign` value used per measure in `measure_revert_sign`. Built-in loss
178+
measures are sign-flipped for utility-scale `{measure}_diff` when
179+
`revert_sign` is `FALSE`.
180+
- **Still open:** Whether to expose orientation metadata on `*_pred_measure()`
181+
results themselves (e.g. when `revert_sign = TRUE` in `control`).
141182

142183
### D3: Handling of `r_eff`
143184

@@ -163,7 +204,7 @@ Design choices **internal to `pred_measure`** (not a migration from
163204
require explicit `measure = "ic"` for information criterion
164205
- [x] Document and test deprecated vs new API comparisons *(see
165206
appendix)*
166-
- [ ] Provide an interface to `loo_compare` and verify consistency
207+
- [x] Provide an interface to `loo_compare` and verify consistency
167208
- [ ] Resolve `r_eff` handling *(see D3)*
168209

169210
### Implementation
@@ -181,8 +222,9 @@ Design choices **internal to `pred_measure`** (not a migration from
181222
- [x] Online-only articles published via `_pkgdown.yml`
182223
- [ ] Formula derivations article (`pred_measure-formulas.Rmd`)
183224
- [ ] Detailed per-measure descriptions (derivations where appropriate)
184-
- [ ] Extend glossary (`R/loo-glossary.R`) — measure, metric, score,
185-
utility, loss
225+
- [x] Extend glossary (`R/loo-glossary.R`) — multi-measure `loo_compare` columns
226+
- [ ] Extend glossary further — measure, metric, score, utility, loss
227+
(general terms)
186228

187229
### Grouping via `group_ids`
188230

@@ -200,8 +242,9 @@ Design choices **internal to `pred_measure`** (not a migration from
200242

201243
- Rename `ic``information_criteria` for clarity?
202244
- Should `measure_elpd()` also return `ic`, or keep them separate?
203-
- What defines class `"loo"` on measure objects? (e.g. deprecated
204-
`elpd_generic` inherits `"loo"`)
245+
- What defines class `"loo"` on measure objects? `loo_pred_measure` inherits
246+
`"loo"` (see `integrate-loo_compare`); deprecated `elpd_generic` also
247+
inherits `"loo"`.
205248
- Should `elpd` always be computed when `ylp` is supplied, or allow
206249
`loo_pred_measure()` for non-ELPD measures only?
207250

0 commit comments

Comments
 (0)