Skip to content

Make model = "best" consistent across entry points - #232

Open
takechanman1228 wants to merge 3 commits into
facebookincubator:mainfrom
takechanman1228:fix/best-model-consistency
Open

Make model = "best" consistent across entry points#232
takechanman1228 wants to merge 3 commits into
facebookincubator:mainfrom
takechanman1228:fix/best-model-consistency

Conversation

@takechanman1228

Copy link
Copy Markdown

Addresses the mechanical parts of #231; the selection-criterion question raised there stays open.

model = "best" is only implemented inside GeoLift(). The other entry points pass the string straight into augsynth's progfunc: the simulation functions die with an unhelpful error inside a foreach worker, and GetWeights() documents "best" but errors the same way. Inside GeoLift(), a failed candidate is silently scored L2 = 1, which a real fit can lose to (scaled L2 can exceed 1).

  • Extracted the "best" selection into an internal ResolveBestModel() helper that picks the lowest scaled L2 among the candidates that actually fitted, ties going to the simpler model. Failed candidates (error, or a non-finite imbalance) are excluded with a message(); if every candidate fails it stops. The previous comparison chain could return a failed candidate when the other two tied.
  • GetWeights(model = "best") now works as documented, via the same helper.
  • Added a clear early error for model = "best" in the five simulation entry points (it was never a documented value there).
  • Removed "best" from the ASCMExecution() docs (never implemented there) and fixed the \item{"best:} typo; regenerated the affected man pages.
  • Added a testthat scaffold: unit tests of the selector with ASCMExecution mocked, plus end-to-end checks (slow ones are skip_on_cran()).

Note: even with the GSYN fit repaired upstream (ebenmichael/augsynth#119), GSYN cannot currently win the comparison — for no-covariate runs augsynth reports the same scaled L2 for "none" and "GSYN" (details in #231). This PR only fixes the mechanics; what "best" should select on is #231 's open question.

'best' was only implemented inside GeoLift(); every other entry point
passed the raw string into augsynth's progfunc:

- the five simulation-based functions (GeoLiftPowerFinder,
  GeoLiftPower.search, NumberLocations, GeoLiftPower,
  GeoLiftMarketSelection) died with "progfunc must be one of ..."
  buried inside a foreach worker;
- GetWeights() documents 'best' but died on the same validation;
- inside GeoLift() itself, candidate failures in the 'best' trial were
  silently swallowed (tryCatch -> scored as L2 = 1, a sentinel a fitted
  candidate can lose to since Scaled L2 can exceed 1), so with current
  CRAN gsynth (>= 1.3.0) the GSYN candidate never fits and nobody is
  told (upstream augsynth defect, reported separately).

Changes:
- extract the 'best' trial into an internal ResolveBestModel() helper
  (@nord) that implements the documented rule directly: lowest Scaled
  L2 Imbalance among the candidates that actually fitted, ties going to
  the simpler model (none, then ridge, then GSYN). The old strict-
  comparison chain could return a candidate that had FAILED (or one
  strictly worse than a tied pair) whenever the other two tied. A
  failed candidate — error, or a scaled_l2_imbalance that is not a
  single finite number (NaN/NULL) — is reported via message() with the
  underlying error and scored Inf; if every candidate fails the
  selection stops with a clear error instead of silently returning
  'none'. The single-treatment-location GSYN skip is announced;
- wire GetWeights(model = 'best') to the same helper, making the
  documented value actually work;
- add an early, self-explanatory stop() for model = 'best' in the five
  simulation entry points (they fit one outcome model at a time by
  design; MultiCellMarketSelection inherits the clear error);
- docs: remove the 'best' row from ASCMExecution() (pass-through, never
  implemented there); fix the \item{"best:} quote typo in 4 blocks.
man/ regenerated with roxygen2, keeping only content changes (quote
typo fix, ASCMExecution 'best' row removal); testthat added to Suggests
for the new test suite.
Unit tests of ResolveBestModel() with ASCMExecution mocked: plain
minimum, failed candidates never selected (even on ties among the
fitted ones), tie-breaking toward the simpler model, NaN/NULL
imbalances treated as failures, all-candidates-failed error, and the
single-location GSYN skip. End-to-end: the new clear error in the
simulation entry points, GetWeights(model = 'best') returning weights,
the announced GSYN skip, and an unchanged GeoLift(model = 'ridge') fit
as a regression guard.
@meta-cla

meta-cla Bot commented Aug 24, 2026

Copy link
Copy Markdown

Hi @takechanman1228!

Thank you for your pull request and welcome to our community.

Action Required

In order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you.

Process

In order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA.

Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with CLA signed. The tagging process may take up to 1 hour after signing. Please give it that time before contacting us about it.

If you have received this in error or have any questions, please contact us at cla@meta.com. Thanks!

@meta-cla

meta-cla Bot commented Aug 24, 2026

Copy link
Copy Markdown

Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Meta Open Source project. Thanks!

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Aug 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant