From bfe7a09439a41be6796d0d6d6f25bf752106657a Mon Sep 17 00:00:00 2001 From: Hyunsu Cho Date: Tue, 30 Jun 2026 00:12:01 -0700 Subject: [PATCH 1/6] Add installation guide and migration guide --- docs/source/fil_migration.rst | 47 +++++++++++++++++++++++++++++++++ docs/source/getting_started.rst | 13 +++++++++ docs/source/index.rst | 2 ++ 3 files changed, 62 insertions(+) create mode 100644 docs/source/fil_migration.rst diff --git a/docs/source/fil_migration.rst b/docs/source/fil_migration.rst new file mode 100644 index 0000000..fc58aab --- /dev/null +++ b/docs/source/fil_migration.rst @@ -0,0 +1,47 @@ +############### +Migration guide +############### + +Basic workflow +============== + +Call :py:meth:`~nvforest.load_model`, :py:meth:`~nvforest.load_from_sklearn`, +or :py:meth:`~nvforest.load_from_treelite_model`. Note that it is no longer +necessary to specify the ``is_classifier`` parameter. + +.. code-block:: python + + # BEFORE + fil_model = cuml.fil.ForestInference.load("xgb_model.ubj", is_classifier=True) + fil_model.optimize(batch_size=1024) + predictions = fil_model.predict(X_test) + probabilities = fil_model.predict_proba(X_test) + per_tree_pred = fil_model.predict_per_tree(X_test) + lead_ids = fil_model.apply(X_test) + + # AFTER + nvforest_model = nvforest.load_model("xgb_model.ubj") + nvforest_model_optimized = nvforest_model.optimize(batch_size=1024) + predictions = nvforest_model.predict(X_test) + probabilities = nvforest_model.predict_proba(X_test) + per_tree_pred = nvforest_model.predict_per_tree(X_test) + lead_ids = nvforest_model.apply(X_test) + +Device selection +================ +Specify the ``device`` parameter when calling :py:meth:`~nvforest.load_model`. + +.. code-block:: python + + # BEFORE + with set_fil_device_type("cpu"): + fil_model = cuml.fil.ForestInference.load("xgboost_model.ubj") + result = fil_model.predict(data) + + # AFTER + nvforest_model = nvforest.load_model("xgboost_model.ubj", device="cpu") + +nvForest also differs from FIL when it comes to the behavior when no device is explicitly +specified. The ``device`` parameter defaults to ``"auto"``. nvForest will attempt to +load the tree model onto a GPU device, if one is available. If no GPU is available, +nvForest will fall back to the CPU. diff --git a/docs/source/getting_started.rst b/docs/source/getting_started.rst index c21add7..8d04e30 100644 --- a/docs/source/getting_started.rst +++ b/docs/source/getting_started.rst @@ -2,6 +2,19 @@ Getting started with nvForest ############################# +Installation +============ +nvForest is available on PyPI and Conda. + +.. code-block:: console + + $ pip install nvforest-cu13 + + $ conda install nvforest + +You can also install nvForest as part of RAPIDS, a collection of libraries for GPU accelerated data science. +Visit https://docs.rapids.ai/install/ for more information. + nvForest with Python ==================== diff --git a/docs/source/index.rst b/docs/source/index.rst index 3ee2a4a..686a26b 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -8,6 +8,7 @@ It supports many kinds of decision tree models, including XGBoost, LightGBM, sci * :doc:`python_api`: Python API documentation * :doc:`cpp_api`: C++ API documentation * :doc:`build`: How to build nvForest from the source +* :doc:`fil_migration`: How to migrate existing code using Forest Inference Library (FIL) .. toctree:: :maxdepth: 2 @@ -17,3 +18,4 @@ It supports many kinds of decision tree models, including XGBoost, LightGBM, sci python_api cpp_api build + fil_migration From 7c4864dc19a72866b6ebf4f29863d09c0a68b585 Mon Sep 17 00:00:00 2001 From: Hyunsu Cho Date: Tue, 30 Jun 2026 00:44:20 -0700 Subject: [PATCH 2/6] Fix typo --- docs/source/fil_migration.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/fil_migration.rst b/docs/source/fil_migration.rst index fc58aab..da3a6fa 100644 --- a/docs/source/fil_migration.rst +++ b/docs/source/fil_migration.rst @@ -21,7 +21,7 @@ necessary to specify the ``is_classifier`` parameter. # AFTER nvforest_model = nvforest.load_model("xgb_model.ubj") - nvforest_model_optimized = nvforest_model.optimize(batch_size=1024) + nvforest_model = nvforest_model.optimize(batch_size=1024) predictions = nvforest_model.predict(X_test) probabilities = nvforest_model.predict_proba(X_test) per_tree_pred = nvforest_model.predict_per_tree(X_test) From a77c92aa80ebee25b51721c09dbf426632bb2f65 Mon Sep 17 00:00:00 2001 From: Hyunsu Cho Date: Tue, 30 Jun 2026 13:13:32 -0700 Subject: [PATCH 3/6] Add doctest --- .../all_cuda-129_arch-aarch64.yaml | 1 + .../all_cuda-129_arch-x86_64.yaml | 1 + .../all_cuda-133_arch-aarch64.yaml | 1 + .../all_cuda-133_arch-x86_64.yaml | 1 + dependencies.yaml | 1 + docs/source/fil_migration.rst | 44 ++++++++++++------- 6 files changed, 33 insertions(+), 16 deletions(-) diff --git a/conda/environments/all_cuda-129_arch-aarch64.yaml b/conda/environments/all_cuda-129_arch-aarch64.yaml index 774117d..c7e5948 100644 --- a/conda/environments/all_cuda-129_arch-aarch64.yaml +++ b/conda/environments/all_cuda-129_arch-aarch64.yaml @@ -15,6 +15,7 @@ dependencies: - cuda-profiler-api - cuda-python>=12.9.2,<13.0a0 - cuda-version=12.9 +- cuml==26.8.*,>=0.0.0a0 - cupy>=14.0.1,!=14.1.0 - cxx-compiler - cython>=3.0.0 diff --git a/conda/environments/all_cuda-129_arch-x86_64.yaml b/conda/environments/all_cuda-129_arch-x86_64.yaml index 22a13c6..e34884f 100644 --- a/conda/environments/all_cuda-129_arch-x86_64.yaml +++ b/conda/environments/all_cuda-129_arch-x86_64.yaml @@ -15,6 +15,7 @@ dependencies: - cuda-profiler-api - cuda-python>=12.9.2,<13.0a0 - cuda-version=12.9 +- cuml==26.8.*,>=0.0.0a0 - cupy>=14.0.1,!=14.1.0 - cxx-compiler - cython>=3.0.0 diff --git a/conda/environments/all_cuda-133_arch-aarch64.yaml b/conda/environments/all_cuda-133_arch-aarch64.yaml index 91c482f..9b752aa 100644 --- a/conda/environments/all_cuda-133_arch-aarch64.yaml +++ b/conda/environments/all_cuda-133_arch-aarch64.yaml @@ -15,6 +15,7 @@ dependencies: - cuda-profiler-api - cuda-python>=13.0.1,<14.0a0 - cuda-version=13.3 +- cuml==26.8.*,>=0.0.0a0 - cupy>=14.0.1,!=14.1.0 - cxx-compiler - cython>=3.0.0 diff --git a/conda/environments/all_cuda-133_arch-x86_64.yaml b/conda/environments/all_cuda-133_arch-x86_64.yaml index 22289a0..e215830 100644 --- a/conda/environments/all_cuda-133_arch-x86_64.yaml +++ b/conda/environments/all_cuda-133_arch-x86_64.yaml @@ -15,6 +15,7 @@ dependencies: - cuda-profiler-api - cuda-python>=13.0.1,<14.0a0 - cuda-version=13.3 +- cuml==26.8.*,>=0.0.0a0 - cupy>=14.0.1,!=14.1.0 - cxx-compiler - cython>=3.0.0 diff --git a/dependencies.yaml b/dependencies.yaml index c1815f7..186bb94 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -354,6 +354,7 @@ dependencies: - output_types: conda packages: - doxygen + - cuml==26.8.*,>=0.0.0a0 py_version: specific: - output_types: conda diff --git a/docs/source/fil_migration.rst b/docs/source/fil_migration.rst index da3a6fa..74e2dac 100644 --- a/docs/source/fil_migration.rst +++ b/docs/source/fil_migration.rst @@ -5,41 +5,53 @@ Migration guide Basic workflow ============== +.. testsetup:: workflow + + import numpy as np + from sklearn.ensemble import RandomForestClassifier + + X = np.array([[1, 2], [-1, 2]], dtype="float32") + y = np.array([0, 1], dtype="int32") + + skl_model = RandomForestClassifier(n_estimators=1, max_depth=1) + skl_model.fit(X, y) + Call :py:meth:`~nvforest.load_model`, :py:meth:`~nvforest.load_from_sklearn`, or :py:meth:`~nvforest.load_from_treelite_model`. Note that it is no longer necessary to specify the ``is_classifier`` parameter. -.. code-block:: python +.. testcode:: workflow # BEFORE - fil_model = cuml.fil.ForestInference.load("xgb_model.ubj", is_classifier=True) + import cuml + fil_model = cuml.fil.ForestInference.load_from_sklearn(skl_model, is_classifier=True) fil_model.optimize(batch_size=1024) - predictions = fil_model.predict(X_test) - probabilities = fil_model.predict_proba(X_test) - per_tree_pred = fil_model.predict_per_tree(X_test) - lead_ids = fil_model.apply(X_test) + predictions = fil_model.predict(X) + probabilities = fil_model.predict_proba(X) + per_tree_pred = fil_model.predict_per_tree(X) + lead_ids = fil_model.apply(X) # AFTER - nvforest_model = nvforest.load_model("xgb_model.ubj") + import nvforest + nvforest_model = nvforest.load_from_sklearn(skl_model) nvforest_model = nvforest_model.optimize(batch_size=1024) - predictions = nvforest_model.predict(X_test) - probabilities = nvforest_model.predict_proba(X_test) - per_tree_pred = nvforest_model.predict_per_tree(X_test) - lead_ids = nvforest_model.apply(X_test) + predictions = nvforest_model.predict(X) + probabilities = nvforest_model.predict_proba(X) + per_tree_pred = nvforest_model.predict_per_tree(X) + lead_ids = nvforest_model.apply(X) Device selection ================ Specify the ``device`` parameter when calling :py:meth:`~nvforest.load_model`. -.. code-block:: python +.. testcode:: workflow # BEFORE - with set_fil_device_type("cpu"): - fil_model = cuml.fil.ForestInference.load("xgboost_model.ubj") - result = fil_model.predict(data) + with cuml.fil.set_fil_device_type("cpu"): + fil_model = cuml.fil.ForestInference.load_from_sklearn(skl_model) # AFTER - nvforest_model = nvforest.load_model("xgboost_model.ubj", device="cpu") + nvforest_model = nvforest.load_from_sklearn(skl_model) nvForest also differs from FIL when it comes to the behavior when no device is explicitly specified. The ``device`` parameter defaults to ``"auto"``. nvForest will attempt to From 168f429197f1e61b6f43c9ab79659cb73c1a2343 Mon Sep 17 00:00:00 2001 From: Hyunsu Cho Date: Tue, 30 Jun 2026 18:18:25 -0700 Subject: [PATCH 4/6] Remove circular dependency --- conda/environments/all_cuda-129_arch-aarch64.yaml | 1 - conda/environments/all_cuda-129_arch-x86_64.yaml | 1 - conda/environments/all_cuda-133_arch-aarch64.yaml | 1 - conda/environments/all_cuda-133_arch-x86_64.yaml | 1 - dependencies.yaml | 1 - docs/source/fil_migration.rst | 8 ++++++-- 6 files changed, 6 insertions(+), 7 deletions(-) diff --git a/conda/environments/all_cuda-129_arch-aarch64.yaml b/conda/environments/all_cuda-129_arch-aarch64.yaml index c7e5948..774117d 100644 --- a/conda/environments/all_cuda-129_arch-aarch64.yaml +++ b/conda/environments/all_cuda-129_arch-aarch64.yaml @@ -15,7 +15,6 @@ dependencies: - cuda-profiler-api - cuda-python>=12.9.2,<13.0a0 - cuda-version=12.9 -- cuml==26.8.*,>=0.0.0a0 - cupy>=14.0.1,!=14.1.0 - cxx-compiler - cython>=3.0.0 diff --git a/conda/environments/all_cuda-129_arch-x86_64.yaml b/conda/environments/all_cuda-129_arch-x86_64.yaml index e34884f..22a13c6 100644 --- a/conda/environments/all_cuda-129_arch-x86_64.yaml +++ b/conda/environments/all_cuda-129_arch-x86_64.yaml @@ -15,7 +15,6 @@ dependencies: - cuda-profiler-api - cuda-python>=12.9.2,<13.0a0 - cuda-version=12.9 -- cuml==26.8.*,>=0.0.0a0 - cupy>=14.0.1,!=14.1.0 - cxx-compiler - cython>=3.0.0 diff --git a/conda/environments/all_cuda-133_arch-aarch64.yaml b/conda/environments/all_cuda-133_arch-aarch64.yaml index 9b752aa..91c482f 100644 --- a/conda/environments/all_cuda-133_arch-aarch64.yaml +++ b/conda/environments/all_cuda-133_arch-aarch64.yaml @@ -15,7 +15,6 @@ dependencies: - cuda-profiler-api - cuda-python>=13.0.1,<14.0a0 - cuda-version=13.3 -- cuml==26.8.*,>=0.0.0a0 - cupy>=14.0.1,!=14.1.0 - cxx-compiler - cython>=3.0.0 diff --git a/conda/environments/all_cuda-133_arch-x86_64.yaml b/conda/environments/all_cuda-133_arch-x86_64.yaml index e215830..22289a0 100644 --- a/conda/environments/all_cuda-133_arch-x86_64.yaml +++ b/conda/environments/all_cuda-133_arch-x86_64.yaml @@ -15,7 +15,6 @@ dependencies: - cuda-profiler-api - cuda-python>=13.0.1,<14.0a0 - cuda-version=13.3 -- cuml==26.8.*,>=0.0.0a0 - cupy>=14.0.1,!=14.1.0 - cxx-compiler - cython>=3.0.0 diff --git a/dependencies.yaml b/dependencies.yaml index 186bb94..c1815f7 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -354,7 +354,6 @@ dependencies: - output_types: conda packages: - doxygen - - cuml==26.8.*,>=0.0.0a0 py_version: specific: - output_types: conda diff --git a/docs/source/fil_migration.rst b/docs/source/fil_migration.rst index 74e2dac..738eb6d 100644 --- a/docs/source/fil_migration.rst +++ b/docs/source/fil_migration.rst @@ -20,7 +20,7 @@ Call :py:meth:`~nvforest.load_model`, :py:meth:`~nvforest.load_from_sklearn`, or :py:meth:`~nvforest.load_from_treelite_model`. Note that it is no longer necessary to specify the ``is_classifier`` parameter. -.. testcode:: workflow +.. code-block:: python # BEFORE import cuml @@ -31,6 +31,8 @@ necessary to specify the ``is_classifier`` parameter. per_tree_pred = fil_model.predict_per_tree(X) lead_ids = fil_model.apply(X) +.. testcode:: workflow + # AFTER import nvforest nvforest_model = nvforest.load_from_sklearn(skl_model) @@ -44,12 +46,14 @@ Device selection ================ Specify the ``device`` parameter when calling :py:meth:`~nvforest.load_model`. -.. testcode:: workflow +.. code-block:: python # BEFORE with cuml.fil.set_fil_device_type("cpu"): fil_model = cuml.fil.ForestInference.load_from_sklearn(skl_model) +.. testcode:: workflow + # AFTER nvforest_model = nvforest.load_from_sklearn(skl_model) From 198745c4f681b35e17894720daf9332dd6b76681 Mon Sep 17 00:00:00 2001 From: Hyunsu Cho Date: Tue, 30 Jun 2026 18:20:20 -0700 Subject: [PATCH 5/6] Apply suggestions from @jameslamb Co-authored-by: James Lamb --- docs/source/getting_started.rst | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/source/getting_started.rst b/docs/source/getting_started.rst index 8d04e30..e0c0276 100644 --- a/docs/source/getting_started.rst +++ b/docs/source/getting_started.rst @@ -4,13 +4,17 @@ Getting started with nvForest Installation ============ -nvForest is available on PyPI and Conda. +You can install nvForest using Pip or Conda. .. code-block:: console + # Using Pip: need a suffix $ pip install nvforest-cu13 - $ conda install nvforest +.. code-block:: console + + # Using Conda: need to specify the rapidsai channel + $ conda install -c rapidsai -c conda-forge nvforest You can also install nvForest as part of RAPIDS, a collection of libraries for GPU accelerated data science. Visit https://docs.rapids.ai/install/ for more information. From 1d744980469e3cb79f9f464b06116d030f979a27 Mon Sep 17 00:00:00 2001 From: Hyunsu Cho Date: Thu, 2 Jul 2026 10:07:39 -0700 Subject: [PATCH 6/6] Address review comments --- docs/source/fil_migration.rst | 2 +- docs/source/getting_started.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/fil_migration.rst b/docs/source/fil_migration.rst index 738eb6d..97a415a 100644 --- a/docs/source/fil_migration.rst +++ b/docs/source/fil_migration.rst @@ -55,7 +55,7 @@ Specify the ``device`` parameter when calling :py:meth:`~nvforest.load_model`. .. testcode:: workflow # AFTER - nvforest_model = nvforest.load_from_sklearn(skl_model) + nvforest_model = nvforest.load_from_sklearn(skl_model, device="cpu") nvForest also differs from FIL when it comes to the behavior when no device is explicitly specified. The ``device`` parameter defaults to ``"auto"``. nvForest will attempt to diff --git a/docs/source/getting_started.rst b/docs/source/getting_started.rst index e0c0276..601d742 100644 --- a/docs/source/getting_started.rst +++ b/docs/source/getting_started.rst @@ -8,7 +8,7 @@ You can install nvForest using Pip or Conda. .. code-block:: console - # Using Pip: need a suffix + # Using Pip: need a suffix corresponding to your CUDA version, e.g. for CUDA 13: $ pip install nvforest-cu13 .. code-block:: console