Getting Started

Purpose

Onboard a new user from install to first successful DSAMbayes run, then point them into the workflow guidance needed for serious modelling use.

Audience

  • New DSAMbayes users.
  • Analysts running DSAMbayes through R scripts or CLI.
  1. Install and Setup
  2. Quickstart (YAML Runner)
  3. Principled Bayesian Workflow
  4. Your First BLM Model or Your First Hierarchical Model

If you are coming from classical econometrics, read Frequentist to Bayesian Translation before customising priors or interpreting diagnostics.

Pages

Page Topic
Install and Setup Prerequisites, installation commands, and verification
Concepts What DSAMbayes does and how Bayesian MMM differs from classical regression
Your First BLM Model Build, fit, and interpret a single-market model using the R API
Your First Hierarchical Model Multi-market model with partial pooling and CRE
Quickstart (YAML Runner) Minimal end-to-end CLI run from config to output inspection
FAQ Answers to common questions

Use Getting Started for setup, not for the whole methodology

The Getting Started pages are intentionally practical. Once you can run the package, use the workflow section to answer the two questions that matter most in Bayesian MMM:

  • how should I think about priors?
  • which diagnostics matter before I trust outputs?

Subsections of Getting Started

Install and Setup

Audience

Engineers and analysts setting up DSAMbayes for local development or modelling runs.

Prerequisites

  • R >= 4.1 — check with R --version.
  • A C++ toolchain for Stan compilation. This is the most common source of setup issues:
    • macOS: install Xcode Command Line Tools (xcode-select --install).
    • Windows: install Rtools matching your R version. Ensure make is on your PATH.
    • Linux (Ubuntu/Debian): sudo apt install build-essential.
    • See the RStan Getting Started Guide for detailed platform instructions.
  • A local checkout of this repository.

Open a terminal in the repository root and run:

# 1. Select an ABI-safe host library and create it with the cache
source scripts/r-library-path.sh
dsambayes_set_r_library host
mkdir -p "$R_LIBS_USER" .cache

# 2. Set the cache path (add both settings to .bashrc/.zshrc for persistence)
export XDG_CACHE_HOME="$PWD/.cache"

# 3. Install DSAMbayes from the local checkout
R -q -e 'install.packages(".", repos = NULL, type = "source")'

This keeps all package libraries and Stan compilation caches inside the repo, avoiding permission issues with system library paths.

Do not share a compiled package library between R runtimes or containers. dsambayes_set_r_library host selects .Rlib-host-r<active-R-version>/; use dsambayes_set_r_library container inside a container instead. The path is deliberately derived from the active runtime, not hard-coded in the repository.

Verify the installation

1. Confirm DSAMbayes loads

R -q -e 'library(DSAMbayes); cat("Version:", as.character(utils::packageVersion("DSAMbayes")), "\n")'

Expected: prints Version: 1.3.3 (or current version).

2. Confirm the runner works

Rscript scripts/dsambayes.R validate --config config/blm_timeseries.yaml

Expected: validation completes without errors.

3. (Optional) Run the test suite

R -q -e 'testthat::test_dir("tests/testthat")'

Expected: all tests pass.

Alternative: install from GitHub

If you do not have a local checkout, install from the GitHub remote:

R -q -e 'remotes::install_github("groupm-global/DSAMbayes")'

This installs the latest version on main. For the development fork with v1.3.3 features, use the local-checkout path above.

Using renv (optional)

The repository includes a renv.lock file for fully reproducible dependency management. To use it:

R -q -e 'install.packages("renv"); renv::restore()'

This installs the exact dependency versions used during development. It is optional but recommended for production runs where reproducibility matters.

Runner setup and first execution

1. Validate the example config

Rscript scripts/dsambayes.R validate --config config/blm_timeseries.yaml

2. Execute a full run

Rscript scripts/dsambayes.R run --config config/cre_geo_panel.yaml

Expected: a timestamped run directory is created under results/ with model outputs and diagnostics.

Troubleshooting

Stan compilation fails

Symptom: errors during Compiling model... referencing C++ or compiler issues.

Actions:

  1. Confirm your C++ toolchain is working: R -q -e 'pkgbuild::has_build_tools(debug = TRUE)'.
  2. On Windows, ensure Rtools is installed and make is on your PATH.
  3. Clear the Stan cache and retry: rm -rf .cache/dsambayes.
  4. Follow the RStan Getting Started Guide for your platform.

Package installation fails

Symptom: install.packages(".", repos = NULL, type = "source") errors.

Actions:

  1. Confirm you are in the repository root directory.
  2. Confirm the selected R_LIBS_USER directory exists and is writable.
  3. Check for missing system dependencies in the error output.

Stale Stan cache

Symptom: unexpected model behaviour after updating the package.

Actions:

  1. Clear the cache: rm -rf .cache/dsambayes.
  2. Re-run with model.force_recompile: true in your config if you need to invalidate a stale compiled model.

Permission issues

Symptom: write failures for library, cache, or run outputs.

Actions:

  1. Ensure R_LIBS_USER, .cache, and results/ are writable.
  2. Keep R_LIBS_USER and XDG_CACHE_HOME set in your shell session.
  3. Run all commands from the repository root.

Concepts

Purpose

Give new DSAMbayes users a compact conceptual orientation before they move into tutorials, runner usage, or the workflow section.

This page is intentionally introductory. It does not try to be the full methodology guide for Bayesian MMM. For that, use Principled Bayesian Workflow.

What is DSAMbayes?

DSAMbayes is an R package for Bayesian marketing mix modelling built on Stan. It provides:

  • an lm()-style modelling interface for interactive work
  • model classes for single-series, hierarchical, and pooled MMM
  • prior and boundary controls
  • post-fit extraction, diagnostics, decomposition, and optimisation tooling
  • a YAML/CLI runner for reproducible runs

The main practical difference from classical regression is that DSAMbayes works with a posterior distribution, not just a single fitted coefficient vector.

Why Bayesian MMM?

MMM datasets often have the exact features that make naive regression unstable:

  • short time series
  • overlapping media timing
  • strong baseline structure
  • uncertain functional form
  • real business need for uncertainty-aware decisions

Bayesian modelling helps because it makes several things explicit:

  • regularisation through priors
  • structural constraints through boundaries
  • uncertainty propagation into downstream outputs
  • diagnostic gates rather than fit-statistic-only thinking

The DSAMbayes mental model

DSAMbayes should be thought of as a workflow, not just a fitter.

At a high level:

  1. specify the model and priors
  2. fit the model
  3. check whether the posterior computation is trustworthy
  4. check whether the fitted model is adequate for the data
  5. only then interpret decomposition, comparison, or optimisation outputs

That is the main philosophical shift from a simpler OLS-style workflow.

Model classes

DSAMbayes supports three main model classes.

BLM

Single-market Bayesian linear model.

Use when:

  • you have one KPI series
  • one market / brand / region is the modelling unit
  • you want the simplest Bayesian MMM starting point

Hierarchical

Multi-group model with partial pooling.

Use when:

  • you have panel data across markets, regions, or brands
  • you want to borrow strength across groups while preserving group structure

Pooled

Single-market model with structured pooling across labelled media dimensions.

Use when:

  • the outcome is one series
  • the media structure has nested or repeated dimensions that should share information

For the detailed class contract, see Model Classes.

Interactive API vs runner

DSAMbayes has two main ways of working:

Interactive R API

Best when you want to prototype directly in R:

  • blm()
  • set_prior()
  • set_boundary()
  • fit()
  • get_posterior()

YAML / CLI runner

Best when you want reproducibility and staged artefacts:

  • validate
  • run
  • staged outputs under results/

See Quickstart and Runner.

What this page does not try to teach

This page does not try to fully answer:

  • how to choose priors
  • which diagnostics matter most
  • when business interpretation is allowed

Those are workflow questions, and they are handled in the dedicated methodology pages:

Your First BLM Model

Goal

Build, fit, and interpret a single-market Bayesian linear model (BLM) using the DSAMbayes R API.

This page is a hands-on tutorial. For the broader methodological questions behind prior-setting and diagnostics, use the workflow pages:

Prerequisites

  • DSAMbayes installed locally (see Install and Setup).
  • Familiarity with R and lm()-style formulas.

Dataset

This walkthrough uses the synthetic dataset shipped at data/synthetic_dsam_example_wide_data.csv. It contains weekly observations for a single market with columns for:

  • Response: kpi_os_hfb01_value — weekly KPI (e.g. revenue).
  • Media: m_tv, m_search, m_social, m_display, m_ooh, m_email, m_affiliate.
  • Controls: t_scaled (trend), sin52_1/cos52_1/sin52_2/cos52_2 (Fourier seasonality), price_index, distribution, bm_ikea_trust_12r (brand metric).
  • Holidays: h_black_friday, h_christmas, h_new_year, h_easter, h_summer_sale.
library(DSAMbayes)
df <- read.csv("data/synthetic_dsam_example_wide_data.csv")
str(df)

Step 1: Construct the model

blm() creates an unfitted model object. No fitting happens yet.

model <- blm(
  kpi_os_hfb01_value ~
    t_scaled + sin52_1 + cos52_1 + sin52_2 + cos52_2 +
    h_black_friday + h_christmas + h_new_year + h_easter + h_summer_sale +
    bm_ikea_trust_12r + price_index + distribution +
    m_tv + m_search + m_social + m_display + m_ooh + m_email + m_affiliate,
  data = df
)

Inspect defaults:

peek_prior(model)      # normal(0, 5) for all terms
peek_boundary(model)   # (-Inf, Inf) — unconstrained

Step 2: Set boundaries

Media channels should have non-negative effects. Use inequality notation:

model <- model %>%
  set_boundary(
    m_tv > 0, m_search > 0, m_social > 0,
    m_display > 0, m_ooh > 0, m_email > 0, m_affiliate > 0
  )

Step 3: (Optional) Override priors

Default priors are weakly informative. Override only with domain knowledge:

model <- model %>%
  set_prior(price_index ~ normal(-0.2, 0.1))

See Stage 2: Model and Priors and Minimal-Prior Policy for guidance.

Step 4: Fit with MCMC

fitted_model <- model %>%
  fit(cores = 2, iter = 2000, warmup = 1000, seed = 123)

First-time Stan compilation takes 1–3 minutes. Subsequent runs use a cached binary. With 2 chains on synthetic data, sampling typically completes in under 2 minutes.

Step 5: Sampler diagnostics

chain_diagnostics(fitted_model)
Metric Good Concern
Max Rhat <= 1.01 > 1.01 means chains have not converged
Min ESS (bulk) > 400 < 200 means too few effective samples
Divergences 0 Any non-zero count warrants investigation

These are the computational checks. They do not by themselves prove the model is adequate for interpretation.

Step 6: Extract the posterior

post <- get_posterior(fitted_model)

post is a tibble with one row per draw containing coef (named coefficient list), yhat (fitted values), noise_sd, r2, rmse, and smape.

Summarise coefficients:

library(dplyr); library(tidyr)

coef_summary <- post %>%
  select(coef) %>%
  unnest_wider(coef) %>%
  pivot_longer(everything(), names_to = "term") %>%
  group_by(term) %>%
  summarise(
    mean = mean(value), median = median(value), sd = sd(value),
    ci_low = quantile(value, 0.025), ci_high = quantile(value, 0.975),
    .groups = "drop"
  )
print(coef_summary, n = 30)

What to look for:

  • Media coefficients should be positive (boundaries enforce this).
  • Wide credible intervals mean the prior dominates — the data cannot identify the effect precisely.

Step 7: Assess model fit

fit_tbl <- fitted(fitted_model)
cat("Median R²:", median(r2(fitted_model)), "\n")
cat("Median RMSE:", median(rmse(fitted_model)), "\n")

For a well-specified MMM on weekly data, in-sample R² above 0.85 is typical.

Step 8: Response decomposition

decomp_tbl <- decomp(fitted_model)
head(decomp_tbl)

Shows each term’s contribution (coefficient × design-matrix column) to the predicted KPI at each time point — the foundation for media contribution and ROI reporting.

Step 9: MAP for rapid iteration

During development, use MAP for fast point estimates:

map_model <- model %>% fit_map(n_runs = 10)
get_posterior(map_model)

Use MCMC for final reporting; MAP for formula iteration. A MAP result is one point estimate, not posterior draws: it has no valid credible intervals or MCMC diagnostics. Review the restart diagnostics if objectives differ materially; use fit() when uncertainty, convergence, or decision risk matters.

Common pitfalls

Pitfall Symptom Fix
Forgetting to set boundaries Media coefficients go negative Add set_boundary(m_x > 0)
Too few iterations High Rhat, low ESS Increase iter and warmup
Missing controls High residual autocorrelation Add trend, seasonality, or holiday terms
Scaling confusion Coefficients look wrong model.scale: true is default; get_posterior() back-transforms automatically

Next steps

Your First Hierarchical Model

Goal

Build, fit, and interpret a multi-market hierarchical model with partial pooling and optional CRE (Mundlak) correction using the DSAMbayes R API.

This page is a hands-on tutorial. For the broader methodological questions behind prior-setting, diagnostics, and interpretation, use the workflow pages:

Prerequisites

Dataset

This walkthrough uses data/synthetic_dsam_example_hierarchical_data.csv — a panel dataset with weekly observations across multiple markets. Key columns:

  • Response: kpi_value — weekly KPI per market.
  • Group: market — market identifier.
  • Media: m_tv, m_search, m_social — media exposure variables.
  • Controls: trend, seasonality, brand_metric.
  • Date: date — weekly date index.
library(DSAMbayes)
panel_df <- read.csv("data/synthetic_dsam_example_hierarchical_data.csv")
table(panel_df$market)  # Check group counts

Step 1: Construct the hierarchical model

The (term | group) syntax tells DSAMbayes to fit random effects. Terms inside the parentheses get group-specific deviations from the population mean:

model <- blm(
  kpi_value ~
    trend + seasonality + brand_metric +
    m_tv + m_search + m_social +
    (1 + m_tv + m_search + m_social | market),
  data = panel_df
)

This specifies:

  • Population (fixed) effects for all terms — the average effect across markets.
  • Random intercepts and slopes for media terms by market — each market can deviate from the population average.

Step 2: Set boundaries

model <- model %>%
  set_boundary(m_tv > 0, m_search > 0, m_social > 0)

Boundaries apply to the population-level coefficients.

Step 3: (Optional) Add CRE / Mundlak correction

If you suspect that group-level spending patterns are correlated with unobserved market characteristics (e.g. high-spend markets also have higher baseline demand), CRE controls for this:

model <- model %>%
  set_cre(vars = c("m_tv", "m_search", "m_social"))

This adds cre_mean_m_tv, cre_mean_m_search, cre_mean_m_social as fixed effects — the group-level means of each media variable. The within-group coefficients then represent purely temporal variation, controlling for between-group confounding.

See CRE / Mundlak for when and why to use this.

Step 4: Fit with MCMC

fitted_model <- model %>%
  fit(cores = 4, iter = 2000, warmup = 1000, seed = 42)

Hierarchical models are slower than BLM — expect 10–30 minutes depending on group count and data size. First-time Stan compilation of the hierarchical template adds 2–3 minutes.

Step 5: Check diagnostics

chain_diagnostics(fitted_model)

Pay special attention to Rhat and ESS for sd_* parameters (group-level standard deviations), which are often harder to estimate than population coefficients.

Step 6: Extract the posterior

post <- get_posterior(fitted_model)

For hierarchical models, coefficient draws from get_posterior() return vectors (one value per group) rather than scalars. The population-level (fixed-effect) estimates are averaged across groups.

Step 7: Group-level results

Fitted values and decomposition are returned per group:

# Fitted values — one row per observation, grouped by market
fit_tbl <- fitted(fitted_model)
head(fit_tbl)

# Decomposition — per-group predictor contributions
decomp_tbl <- decomp(fitted_model)

Step 8: Budget optimisation (population level)

Budget optimisation uses population-level (fixed-effect) beta draws, not group-specific totals:

# See Budget Optimisation docs for full scenario specification
result <- optimise_budget(fitted_model, scenario = my_scenario)

Key differences from BLM

Aspect BLM Hierarchical
Data structure Single market Panel (multiple groups)
Coefficient draws Scalars Vectors (one per group)
Fit time 2–5 min 10–30 min
Decomposition Direct May fail gracefully for `
Forest/prior-posterior plots Direct Group-averaged population estimates
Stan template bayes_lm_updater_revised.stan general_hierarchical.stan (templated per group count)

Common pitfalls

Pitfall Symptom Fix
Too few groups Weak partial pooling; group SDs poorly estimated Need 4+ groups for meaningful hierarchical structure
Too few obs per group High Rhat on sd_* parameters Increase iterations; simplify random-effect structure
CRE with too many vars More CRE variables than groups Reduce CRE variable set; see identification warnings
CRE mean has zero variance scale=TRUE aborts with constant column error Use model.type: re (without CRE) or model.scale: false

Next steps

Quickstart (YAML Runner)

Goal

Complete one reproducible DSAMbayes runner execution from validation to artefact inspection, then load the fitted model in R to explore the results interactively.

This page is operational by design. It teaches you how to run the package, not the full modelling methodology. After the quickstart succeeds, use Principled Bayesian Workflow before treating outputs as decision-ready.

Before you start

Complete the setup in Install and Setup. If you want to build a model interactively from R code instead of YAML, see Your First BLM Model.

1. Set up the environment

Open a terminal in the repository root:

source scripts/r-library-path.sh
dsambayes_set_r_library host
mkdir -p "$R_LIBS_USER" .cache
export XDG_CACHE_HOME="$PWD/.cache"

2. Validate the configuration (dry run)

Rscript scripts/dsambayes.R validate --config config/blm_timeseries.yaml

Expected: exits with code 0. No Stan compilation or sampling occurs.

3. Execute the full run

Rscript scripts/dsambayes.R run --config config/blm_timeseries.yaml

Expected: a timestamped run directory under results/ with staged outputs.

4. Locate and inspect the run directory

latest_run="$(ls -td results/* | head -n 1)"
echo "$latest_run"
find "$latest_run" -maxdepth 2 -type d | sort

Expected stage folders:

Folder Content
00_run_metadata/ Original/resolved/compiled configs, session info
10_pre_run/ VIF report, data dictionary, media spend plots
20_model_fit/ Fitted model object, fit plots
30_post_run/ Posterior summary, fitted/observed CSVs
40_diagnostics/ Diagnostics report, residual plots
50_model_selection/ LOO summary, Pareto-k diagnostics
60_optimisation/ Budget allocation, response curves (when enabled)

5. Verify key artefacts

test -f "$latest_run/00_run_metadata/config.compiled.yaml" && echo "ok: config.compiled.yaml"
test -f "$latest_run/00_run_metadata/config.resolved.yaml" && echo "ok: config.resolved.yaml"
test -f "$latest_run/20_model_fit/model.rds" && echo "ok: model.rds"
test -f "$latest_run/30_post_run/posterior_summary.csv" && echo "ok: posterior_summary.csv"
test -f "$latest_run/40_diagnostics/diagnostics_report.csv" && echo "ok: diagnostics_report.csv"

6. Load the model in R

The fitted model is saved as an RDS object. Load it interactively to explore:

library(DSAMbayes)

model <- readRDS("results/<run_dir>/20_model_fit/model.rds")

# Posterior coefficient summary
post <- get_posterior(model)

# Fit quality
cat("Median R²:", median(r2(model)), "\n")

# Sampler diagnostics
chain_diagnostics(model)

# Fitted values
head(fitted(model))

7. Review diagnostics

Open 40_diagnostics/diagnostics_report.csv:

cat "$latest_run/40_diagnostics/diagnostics_summary.txt"

Quick interpretation:

  • pass — no immediate blocker
  • warn — review before sharing or acting
  • fail — do not treat the run as publishable or decision-ready

For the operational triage, see Interpret Diagnostics. For the methodological meaning of these gates, see:

8. Start from a tracked example config

Copy one of the two tracked examples and adapt it to your data:

  • config/blm_timeseries.yaml for single-series work
  • config/cre_geo_panel.yaml for geo-panel CRE work

Edit the copied YAML to point to your data and columns, then validate and run.

What the quickstart does not prove

A successful run means:

  • the package is installed correctly
  • the runner contract works on the example config
  • you have a complete staged result

It does not by itself prove:

  • the priors are appropriate
  • the fit is decision-ready
  • the decomposition is substantively meaningful
  • the optimisation output should be acted on

That is why the next stop should be the workflow pages.

If the quickstart fails

  • re-run validate before run
  • read the full error message
  • inspect 00_run_metadata/config.resolved.yaml
  • inspect 00_run_metadata/config.compiled.yaml
  • use Debug Run Failures

Next steps

FAQ

This page is for short, practical answers.

For the bigger methodological questions, start with:

Installation and setup

How long does the first Stan compilation take?

Usually 1 to 3 minutes. Subsequent runs typically reuse the cached binary. If compilation appears stuck, check the C++ toolchain in Install and Setup.

Do I need to set R_LIBS_USER every time?

Yes, unless you add it to your shell profile. Use dsambayes_set_r_library host to select a repo-local path that is isolated from both your system library and any container library.

Can I use renv instead of .Rlib?

Yes. The repo includes renv.lock. Use renv::restore() if you want exact dependency restoration.

Modelling

How many weeks of data do I need?

There is no hard minimum, but a useful rule of thumb is:

  • BLM: about 100+ weeks for a model with roughly 10 to 15 predictors
  • Hierarchical: about 80+ weeks per group, ideally with at least 4 groups

Shorter series can still be modelled, but the posterior will usually be much more prior-driven and less decision-ready.

Should I use identity or log response?

  • Identity when the KPI is naturally additive and variance is fairly stable
  • Log when the KPI is strictly positive and effect interpretation is more naturally multiplicative

If unsure, fit both and compare the adequacy and diagnostic picture, not just a single fit metric. See Response Scale Semantics.

How should I think about priors?

Start with Stage 2: Model and Priors.

The short answer is:

  • start with defaults
  • add sparse sign constraints only for structural assumptions
  • add sparse prior overrides only when you can defend them in business or modelling terms
  • do not use priors as a substitute for weak model design

How many MCMC iterations do I need?

The defaults are a reasonable starting point. Then inspect the Stage 4 diagnostics:

  • Rhat <= 1.01 and healthy ESS usually mean the draw count is adequate
  • Rhat > 1.01 or weak ESS usually means you need to increase iterations and warmup
  • any divergences should be addressed before treating the fit as decision-ready

See Stage 4: Computation and Sampler.

How strict is the stationarity requirement for MMM?

DSAMbayes does not require the raw KPI to satisfy a textbook stationarity condition before fitting.

The important question is whether the remaining unexplained structure, after adding sensible controls and baseline terms, is weak enough that media effects are not standing in for missing baseline dynamics.

When should I set boundaries on media coefficients?

Use m_channel > 0 when non-negativity is a structural belief you would defend in writing. Do not apply blanket sign constraints just to make the output look tidier. See Stage 2: Model and Priors and Minimal-Prior Policy.

When should I use CRE (Mundlak)?

Use CRE when you want to separate within-group temporal effects from between-group cross-sectional structure in a hierarchical model. See CRE / Mundlak.

How should I handle CRE mean terms in decomposition / attribution?

Treat cre_mean_* terms as baseline or between-group structure, not as media attribution terms. They are there to absorb confounding structure, not to claim channel contribution.

What priors should I use on CRE mean terms?

Usually the defaults. Avoid manually tightening or positivity-constraining them unless you have a very strong reason, because that can undermine the whole point of CRE adjustment.

Can I add random slopes for CRE mean terms?

No. Those terms are constant within group, so random slopes on them are not separately identifiable from the group intercept.

What does scale = TRUE do?

It standardises the response and predictors before Stan fitting to improve sampler efficiency. Post-fit coefficient extraction is back-transformed automatically.

Runner and outputs

How long does a typical run take?

Roughly:

  • BLM MCMC: a few minutes
  • BLM MAP: seconds
  • Hierarchical MCMC: tens of minutes depending on size
  • Pooled MCMC: usually between BLM and hierarchical

First-time Stan compilation adds extra startup time.

What is the difference between validate and run?

  • validate checks config and data contracts without compiling or fitting Stan
  • run validates, fits, writes staged artefacts, and runs diagnostics

Always validate first after config changes.

Where do outputs go?

Under results/<timestamp>_<model_name>/ by default. See Output Artefacts.

How do I compare two model runs?

Use compare_runs() or compare the model-selection artefacts directly. See Compare Runs.

Diagnostics

Which diagnostics matter most?

Read them in order:

  1. Stage 4: Computation and Sampler
  2. Stage 5: Model Adequacy

That is more important than memorising one threshold in isolation.

What does “Pareto-k > 0.7” mean?

It means the LOO approximation is unreliable for that observation and the point is highly influential. Investigate the observation and be cautious about using LOO-based comparisons mechanically.

My diagnostics say warn. Should I worry?

Usually yes, but not always in the same way.

  • in exploratory work, a warning may be acceptable if understood
  • in shareable reporting, warnings should be disclosed and interpreted
  • repeated or severe warnings usually mean the model needs revision before decision use

Use Interpret Diagnostics for triage and the workflow pages for meaning.

Budget optimisation

How does the allocator work?

It searches feasible spend allocations within channel constraints and scores them against the fitted model. It is a decision layer built on the model, not an independent source of truth.

Can I use budget optimisation with MAP-fitted models?

Yes, but then the result is point-estimate-driven rather than uncertainty-rich. That is fine for rough iteration, not ideal for final decision support.