Install

rieszreg holds the shared abstractions; pick at least one implementation package for an actual learner.

Python

The five packages live in sibling GitHub repos: rieszreg (meta-package + this user guide), rieszboost, krrr, forestriesz, riesznet. Clone them into a parent directory:

mkdir RieszReg && cd RieszReg
git clone https://github.com/rieszreg/rieszreg.git
git clone https://github.com/rieszreg/rieszboost.git
git clone https://github.com/rieszreg/krrr.git
git clone https://github.com/rieszreg/forestriesz.git
git clone https://github.com/rieszreg/riesznet.git
python3 -m venv .venv
.venv/bin/pip install -e rieszreg/python
.venv/bin/pip install -e rieszboost/python      # gradient boosting backend
.venv/bin/pip install -e krrr/python            # kernel ridge backend
.venv/bin/pip install -e forestriesz/python     # random-forest backend
.venv/bin/pip install -e riesznet/python        # neural-network backend

rieszboost’s XGBoostBackend requires OpenMP. On macOS:

brew install libomp

Linux distributions (and GitHub Actions ubuntu-latest) ship libgomp1; no extra step is needed. krrr has no system prerequisites; an optional GPU backend uses falkon (pip install -e 'krrr/python[falkon]'). forestriesz depends on econml, which ships prebuilt wheels for macOS arm64+x86_64 and ubuntu — no compiler required. riesznet depends on torch>=2.0; CPU wheels are fetched automatically, GPU wheels need a --index-url per the PyTorch install matrix.

Combining rieszboost and riesznet in one process

The macOS pip wheels for xgboost and torch each bundle their own libomp.dylib. When both are loaded into one Python process, the two OpenMP runtimes can deadlock during a fit (troubleshooting). Two install paths avoid this:

  • conda-forge — installs xgboost and pytorch against a single shared llvm-openmp, so the conflict cannot occur:

    conda install -c conda-forge xgboost pytorch
    pip install -e rieszreg/python rieszboost/python riesznet/python
  • pip + thread-limit env vars — keep the pip install above and set OMP_NUM_THREADS=1 (and MKL_NUM_THREADS=1) in the shell or at the top of every script that uses both backends. See the troubleshooting page for the full discussion and options including threadpoolctl.threadpool_limits for finer-grained control.

Verify

The chunks below import each package and exercise its public entry point. Failure to import or instantiate raises immediately.

import importlib.metadata as _md
import rieszreg, rieszboost, krrr, forestriesz, riesznet
from rieszreg import ATE, BoundedSquaredLoss, SquaredLoss
from rieszboost import RieszBooster
from krrr import KernelRieszRegressor
from forestriesz import ForestRieszRegressor
from riesznet import RieszNet

# Construct one estimator from each backend to confirm wiring.
estimand = ATE()
RieszBooster(estimand=estimand, n_estimators=5)
RieszBooster(estimand=<rieszreg.estimands.base.ATE object at 0x7f4c879984d0>,
             n_estimators=5)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
KernelRieszRegressor(estimand=estimand, lambda_grid=(1e-2,))
KernelRieszRegressor(estimand=<rieszreg.estimands.base.ATE object at 0x7f4c879984d0>,
                     lambda_grid=(0.01,))
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
ForestRieszRegressor(estimand=estimand, n_estimators=10)
ForestRieszRegressor(estimand=<rieszreg.estimands.base.ATE object at 0x7f4c879984d0>,
                     n_estimators=10)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
RieszNet(estimand=estimand, hidden_sizes=(8,), epochs=1)
RieszNet(epochs=1,
         estimand=<rieszreg.estimands.base.ATE object at 0x7f4c879984d0>,
         hidden_sizes=(8,))
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
for pkg in ("rieszreg", "rieszboost", "krrr", "forestriesz", "riesznet"):
    print(f"{pkg:<12} {_md.version(pkg)}")
rieszreg     0.0.1
rieszboost   0.0.1
krrr         0.0.1
forestriesz  0.0.1
riesznet     0.0.1
# `_setup.qmd` already dev-loaded rieszreg + rieszboost. Reference the
# exported symbols and instantiate one R6 wrapper to confirm reticulate
# is wired through to the Python venv.
stopifnot(is.function(ATE), R6::is.R6Class(RieszBooster))
booster <- RieszBooster$new(estimand = ATE(), n_estimators = 5L)
cat("rieszreg + rieszboost R wrappers OK (",
    class(booster)[1], ")\n", sep = "")
rieszreg + rieszboost R wrappers OK (RieszBooster)

R wrappers (optional)

The R packages are R6 wrappers that call the Python implementations through reticulate. They do not require any separate algorithmic dependency.

First-time setup:

  1. Install the R package dependencies:

    install.packages(c(
      "reticulate", "R6",          # required: Python bridge + R6 classes
      "pkgload",                   # required for `pkgload::load_all` below
      "rsample", "xgboost"         # optional: used in the landing-page R quickstart
                                   # and the estimation/custom-code page
    ))
  2. Load the R wrappers. For this guide we dev-load them from the source tree:

    pkgload::load_all("rieszboost/r/rieszboost")
    pkgload::load_all("krrr/r/krrr")
    pkgload::load_all("forestriesz/r/forestriesz")
    pkgload::load_all("riesznet/r/riesznet")
  3. Point reticulate at the Python venv:

    use_python_rieszboost(".venv/bin/python")

    Or set the environment variable before R starts:

    export RETICULATE_PYTHON=/path/to/RieszReg/.venv/bin/python

The R API exposes every built-in estimand, every loss, and the full estimator interface for each backend. The symbolic tracer for custom m() is Python-only; see r-interface for how to call it from R.

Tests

.venv/bin/python -m pytest rieszreg/python/tests -v
.venv/bin/python -m pytest rieszboost/python/tests -v
.venv/bin/python -m pytest krrr/python/tests -v
.venv/bin/python -m pytest forestriesz/python/tests -v
.venv/bin/python -m pytest riesznet/python/tests -v

Rscript -e '
  Sys.setenv(RETICULATE_PYTHON = file.path(getwd(), ".venv/bin/python"))
  pkgload::load_all("rieszreg/r/rieszreg")
  pkgload::load_all("rieszboost/r/rieszboost")
  testthat::test_dir("rieszboost/r/rieszboost/tests/testthat")
  pkgload::load_all("krrr/r/krrr")
  testthat::test_dir("krrr/r/krrr/tests/testthat")
  pkgload::load_all("forestriesz/r/forestriesz")
  testthat::test_dir("forestriesz/r/forestriesz/tests/testthat")
  pkgload::load_all("riesznet/r/riesznet")
  testthat::test_dir("riesznet/r/riesznet/tests/testthat")
'