Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions conda/environments/all_cuda-129_arch-aarch64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ dependencies:
- numpydoc
- numpydoc<1.9
- nvidia-ml-py>=12
- onnxruntime
- packaging
- pre-commit
- pydata-sphinx-theme!=0.14.2
Expand All @@ -73,6 +74,7 @@ dependencies:
- scikit-learn>=1.5
- scipy>=1.13.0
- seaborn
- skl2onnx
- sphinx
- sphinx-copybutton
- sphinx-markdown-tables
Expand Down
2 changes: 2 additions & 0 deletions conda/environments/all_cuda-129_arch-x86_64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ dependencies:
- numpydoc
- numpydoc<1.9
- nvidia-ml-py>=12
- onnxruntime
- packaging
- pre-commit
- pydata-sphinx-theme!=0.14.2
Expand All @@ -73,6 +74,7 @@ dependencies:
- scikit-learn>=1.5
- scipy>=1.13.0
- seaborn
- skl2onnx
- sphinx
- sphinx-copybutton
- sphinx-markdown-tables
Expand Down
2 changes: 2 additions & 0 deletions conda/environments/all_cuda-131_arch-aarch64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ dependencies:
- numpydoc
- numpydoc<1.9
- nvidia-ml-py>=12
- onnxruntime
- packaging
- pre-commit
- pydata-sphinx-theme!=0.14.2
Expand All @@ -73,6 +74,7 @@ dependencies:
- scikit-learn>=1.5
- scipy>=1.13.0
- seaborn
- skl2onnx
- sphinx
- sphinx-copybutton
- sphinx-markdown-tables
Expand Down
2 changes: 2 additions & 0 deletions conda/environments/all_cuda-131_arch-x86_64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ dependencies:
- numpydoc
- numpydoc<1.9
- nvidia-ml-py>=12
- onnxruntime
- packaging
- pre-commit
- pydata-sphinx-theme!=0.14.2
Expand All @@ -73,6 +74,7 @@ dependencies:
- scikit-learn>=1.5
- scipy>=1.13.0
- seaborn
- skl2onnx
- sphinx
- sphinx-copybutton
- sphinx-markdown-tables
Expand Down
4 changes: 4 additions & 0 deletions dependencies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -401,10 +401,12 @@ dependencies:
- ipykernel
- nbsphinx
- numpydoc
- &onnxruntime onnxruntime
# https://github.com/pydata/pydata-sphinx-theme/issues/1539
- pydata-sphinx-theme!=0.14.2
- recommonmark
- *scikit_learn
- &skl2onnx skl2onnx
- sphinx
- sphinx-copybutton
- sphinx-markdown-tables
Expand Down Expand Up @@ -500,6 +502,8 @@ dependencies:
- numpydoc<1.9
# 'nvidia-ml-py' provides the 'pynvml' module
- nvidia-ml-py>=12
- *onnxruntime
- *skl2onnx
- pyyaml
- pytest<9.0
- pytest-benchmark
Expand Down
1 change: 1 addition & 0 deletions docs/source/cuml-accel/examples/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ examples in this section is available in the cuML GitHub repository at `examples
getting_started.ipynb
profiling.ipynb
plot_kmeans_digits.ipynb
onnx_export.ipynb
148 changes: 148 additions & 0 deletions docs/source/cuml-accel/examples/onnx_export.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Exporting cuml.accel Models to ONNX"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Models trained under `cuml.accel` can be exported to the [ONNX](https://onnx.ai/) format using [sklearn-onnx](https://onnx.ai/sklearn-onnx/). Because `cuml.accel` proxy objects are recognized by `sklearn-onnx` as scikit-learn estimators, you can pass them directly to `convert_sklearn()` without any conversion step.\n",
"\n",
"The resulting `.onnx` file can then be loaded with [ONNX Runtime](https://onnxruntime.ai/) for inference on both CPU and GPU, with no cuML dependency at inference time.\n",
"\n",
"### Supported Estimators\n",
"\n",
"The following `cuml.accel` estimators have been tested with `sklearn-onnx`:\n",
"\n",
"- **Classifiers:** `RandomForestClassifier`, `KNeighborsClassifier`, `LinearSVC`\n",
"- **Regressors:** `RandomForestRegressor`, `KNeighborsRegressor`, `LinearSVR`\n",
"- **Transformers/Clusterers:** `PCA`, `TruncatedSVD`, `KMeans`\n",
"\n",
"Estimators not listed here (e.g. `SVC`, `SVR`, `DBSCAN`, `TSNE`, `HDBSCAN`, `UMAP`) are **not currently supported** for ONNX export."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%load_ext cuml.accel"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Training a Model\n",
"\n",
"Train a `RandomForestClassifier` on the Iris dataset. Under `cuml.accel`, this runs on the GPU."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"from sklearn.datasets import load_iris\n",
"from sklearn.ensemble import RandomForestClassifier\n",
"from sklearn.model_selection import train_test_split\n",
"\n",
"# ONNX requires float32 input\n",
"X, y = load_iris(return_X_y=True)\n",
"X = X.astype(np.float32)\n",
"\n",
"X_train, X_test, y_train, y_test = train_test_split(\n",
" X, y, test_size=0.2, random_state=42\n",
")\n",
"\n",
"clf = RandomForestClassifier(n_estimators=10, max_depth=3, random_state=0)\n",
"clf.fit(X_train, y_train)\n",
"\n",
"accel_predictions = clf.predict(X_test)\n",
"print(f\"Training accuracy: {clf.score(X_train, y_train):.4f}\")\n",
"print(f\"Test accuracy: {clf.score(X_test, y_test):.4f}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Exporting to ONNX\n",
"\n",
"Convert the fitted model to ONNX using `skl2onnx.convert_sklearn()`. The proxy object is passed directly — no `as_sklearn()` call needed."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from skl2onnx import convert_sklearn\n",
"from skl2onnx.common.data_types import FloatTensorType\n",
"\n",
"# zipmap=False returns class probabilities as a 2D array instead of a\n",
"# list of dicts. This option only applies to classifiers with predict_proba.\n",
"initial_type = [(\"float_input\", FloatTensorType([None, X_train.shape[1]]))]\n",
"onnx_model = convert_sklearn(\n",
" clf, initial_types=initial_type, options={\"zipmap\": False}\n",
")\n",
"\n",
"onnx_path = \"./rf_classifier.onnx\"\n",
"with open(onnx_path, \"wb\") as f:\n",
" f.write(onnx_model.SerializeToString())\n",
"\n",
"print(f\"ONNX model saved to {onnx_path} ({len(onnx_model.SerializeToString())} bytes)\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Inference with ONNX Runtime\n",
"\n",
"The saved `.onnx` file can be loaded on any machine with `onnxruntime` installed — no cuML or `sklearn-onnx` needed. Use `onnxruntime` for CPU inference, or `onnxruntime-gpu` for GPU inference."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import onnxruntime as ort\n",
"\n",
"sess = ort.InferenceSession(onnx_path)\n",
"input_name = sess.get_inputs()[0].name\n",
"onnx_results = sess.run(None, {input_name: X_test})\n",
"\n",
"onnx_predictions = onnx_results[0]\n",
"onnx_probabilities = onnx_results[1]\n",
"\n",
"print(f\"ONNX predictions shape: {onnx_predictions.shape}\")\n",
"print(f\"ONNX probabilities shape: {onnx_probabilities.shape}\")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python",
"version": "3.13.7"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
25 changes: 25 additions & 0 deletions docs/source/cuml-accel/limitations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ Additional notes:
- The ``HDBSCAN`` in ``cuml`` uses a parallel MST implementation, which means
the results are not deterministic when there are duplicates in the mutual
reachability graph.
- ONNX export via ``skl2onnx`` is not supported for this estimator.


sklearn.cluster
Expand Down Expand Up @@ -114,6 +115,9 @@ DBSCAN
- If ``metric`` isn't one of the supported metrics (``"l2"``, ``"euclidean"``, ``"cosine"``, ``"precomputed"``).
- If ``X`` is sparse.

Additional notes:

- ONNX export via ``skl2onnx`` is not supported for this estimator.

sklearn.decomposition
---------------------
Expand Down Expand Up @@ -304,6 +308,7 @@ Additional notes:

- Even with a ``random_state``, the TSNE implementation used by ``cuml.accel``
isn't completely deterministic.
- ONNX export via ``skl2onnx`` is not supported for this estimator.

While the exact numerical output for TSNE may differ from that obtained without
``cuml.accel``, we expect the *quality* of results will be approximately as
Expand All @@ -326,6 +331,10 @@ The following fitted attributes are currently not computed:

- ``affinity_matrix_``

Additional notes:

- ONNX export via ``skl2onnx`` is not supported for this estimator.


sklearn.neighbors
-----------------
Expand All @@ -349,6 +358,8 @@ Additional notes:
- The ``radius_neighbors`` method isn't implemented in cuml and will always
fall back to CPU.

- ONNX export via ``skl2onnx`` is not supported for this estimator.

KNeighborsClassifier
^^^^^^^^^^^^^^^^^^^^

Expand Down Expand Up @@ -454,13 +465,25 @@ SVC
- If ``y`` is multiclass.
- If ``probability=True`` and ``y`` doesn't have at least 5 samples per class.

Additional notes:

- ONNX export via ``skl2onnx`` is not supported for this estimator.
- Using ``SVC`` in the same process as ``LinearSVC`` under ``cuml.accel`` can
cause a segfault.

SVR
^^^

``SVR`` will fall back to CPU in the following cases:

- If ``kernel="precomputed"`` or is a callable.

Additional notes:

- ONNX export via ``skl2onnx`` is not supported for this estimator.
- Using ``SVR`` in the same process as ``LinearSVR`` under ``cuml.accel`` can
cause a segfault.

LinearSVC
^^^^^^^^^

Expand Down Expand Up @@ -511,6 +534,8 @@ Additional notes:
- Parallelism during the optimization stage implies numerical imprecisions,
which can lead to difference in the results between CPU and GPU in general.

- ONNX export via ``skl2onnx`` is not supported for this estimator.

While the exact numerical output for UMAP may differ from that obtained without
``cuml.accel``, we expect the *quality* of results will be approximately as
good in most cases. Beyond comparing the visual representation, you may find
Expand Down
Loading