z/OS port of shap — "A unified approach to explain the output of any machine learning model."
This repo holds the patch that makes shap's Python code numba-free on z/OS
(patches/shap-zos/), plus a buildenv that drives shap's real
scikit-build-core/CMake build. It is not wired into CI yet, because
two hard runtime dependencies exist as zopencommunity port repos but have
not published a release:
- scipy — scipyport exists and is under active development (32+ commits, currently fixing LAPACK pkg-config linkage) but has not published a release.
- scikit-learn — scikit-learnport exists (one commit, builds against numpy/scipy without OpenMP) but has not published a release either.
The toolchain gap that used to block this — no cmake/ninja on z/OS, so
scikit-build-core (shap's build backend) could not drive its C++ build —
has since closed:
- cmakeport and ninjaport both have released binaries on z/OS.
- In practice
ninjaisn't even required:scikit-build-core's ownninja.make-fallbacksetting (on by default) drives CMake's "Unix Makefiles" generator withgmake(makeport) when ninja is absent — the same generatorcmakeportitself is bootstrapped with. Confirmed directly:cmake --helpon a z/OS build machine reports "Unix Makefiles" as the starred default generator, andgmake(frommakeport) is onPATHthere. - nanobind and scikit-build-core are both pure-Python
(
py3-none-any) wheels on PyPI — no port needed for either.
So the build system is ready; only the two runtime dependencies remain.
On z/OS 2.5, Python 3.12, with pandas, slicer, tqdm, cloudpickle
installed from the zopen wheel index and scipy/scikit-learn stubbed out
for import-only testing:
shap's two native extensions (_cext, a plain C extension, and_cutils, a nanobind extension) both compile with IBM Open XL C/C++ and import successfully. (Compiled by hand at the time, beforecmakewas available as a zopen port — seepatches/shap-zos/README.md. Thebuildenvin this repo now drives the same compiler throughscikit-build-core/CMake instead.)- With
patches/shap-zos/shap-remove-numba-zos.patchapplied,import shapsucceeds end to end, registering all built-in explainers (TreeExplainer,KernelExplainer,PartitionExplainer,ExactExplainer,GPUTreeExplainer, etc.). - The de-numba'd functions (
shap.links.identity/logit,shap.explainers._partition.lower_credit,shap.utils._masked_model._build_fixed_single_output, mask-building helpers) were smoke-tested against synthetic inputs and produce correct output.
See patches/shap-zos/README.md for full details, exact compiler/linker
flags, and links to the upstream numba-removal effort
(shap#4327).
Modeled on scikit-learnport's and pandasport's Python buildenvs:
- Builds one wheel per interpreter (3.12/3.13/3.14) via
python -m build --wheel --no-isolation, so pip never resolves its own copy ofscikit-build-core,nanobind,numpy,scipy, orscikit-learnfrom PyPI behind our back. - Installs
numpy,scipy,scikit-learn,pandasfrom the zopen wheel index into the build venv (PyPI has no wheel for this platform for any of them);nanobind/scikit-build-core/slicer/tqdm/cloudpicklestraight from PyPI, since all five are pure Python. - Leaves the CMake generator to
scikit-build-core's own default detection (Unix Makefiles + gmake, no-G/CMAKE_GENERATORoverride needed) — see the buildenv's comments for why. zopen_python_testexercises the public API without needing any of the heavy ML frameworks (torch,tensorflow,xgboost,lightgbm,catboost,transformers) that ~45% of shap's own test suite references behindpytest.importorskip: link functions,KernelExplainerandTreeExplaineron scikit-learn models,PartitionExplainer(which exercises the de-numba'dlower_credit), and the nanobind_cutilsextension directly.
- Wait for
scipyportandscikit-learnportto each publish a release. - Run
zopen-buildhere for real and fix whatever the dry-run analysis inbuildenvgot wrong — it has not executed end to end, because it needs scipy/scikit-learn wheels this system cannot yet produce. - Wire up GitHub Actions and Jenkins CI once (1) and (2) are done.
Not yet available. Once unblocked:
zopen install shap