Pickling cuML Models for Persistence

This notebook demonstrates simple pickling of both single-GPU and multi-GPU cuML models for persistence

[1]:
import warnings
warnings.filterwarnings("ignore", category=FutureWarning)

Single GPU Model Pickling

All single-GPU estimators are pickleable. The following example demonstrates the creation of a synthetic dataset, training, and pickling of the resulting model for storage. Trained single-GPU models can also be used to distribute the inference on a Dask cluster, which the Distributed Model Pickling section below demonstrates.

[2]:
from cuml.datasets import make_blobs

X, y = make_blobs(n_samples=50,
                  n_features=10,
                  centers=5,
                  cluster_std=0.4,
                  random_state=0)
[3]:
from cuml.cluster import KMeans

model = KMeans(n_clusters=5)

model.fit(X)
[3]:
KMeans()
[4]:
import pickle

pickle.dump(model, open("kmeans_model.pkl", "wb"))
[5]:
model = pickle.load(open("kmeans_model.pkl", "rb"))
[6]:
model.cluster_centers_
[6]:
array([[ 4.6749854 ,  8.213466  , -9.075721  ,  9.568374  ,  8.454808  ,
        -1.2327975 ,  3.3903713 , -7.828242  , -0.8454461 ,  0.62885725],
       [-4.2439985 ,  5.6107073 , -5.669777  , -1.7957245 , -9.255528  ,
         0.7177438 ,  4.4435906 , -2.8747153 , -5.090096  ,  9.684121  ],
       [ 5.2615476 , -4.0487256 ,  4.464928  , -2.9367518 ,  3.5061095 ,
        -4.0168314 , -3.463885  ,  6.0784483 , -6.953326  , -1.004144  ],
       [-3.008261  ,  4.625961  , -4.4832497 ,  2.228457  ,  1.643532  ,
        -2.4505193 , -5.258201  , -1.6679401 , -7.985754  ,  2.8311467 ],
       [-5.6072407 ,  2.2695985 , -3.7516537 , -1.8182003 , -5.143028  ,
         7.599363  ,  2.8252366 ,  8.773042  ,  1.6198314 ,  1.1772048 ]],
      dtype=float32)

Distributed Model Pickling

The distributed estimator wrappers inside of the cuml.dask are not intended to be pickled directly. The Dask cuML estimators provide a function get_combined_model(), which returns the trained single-GPU model for pickling. The combined model can be used for inference on a single-GPU, and the ParallelPostFit wrapper from the Dask-ML library can be used to perform distributed inference on a Dask cluster.

[7]:
from dask.distributed import Client
from dask_cuda import LocalCUDACluster

cluster = LocalCUDACluster()
client = Client(cluster)
client
2022-08-19 11:28:25,721 - distributed.preloading - INFO - Creating preload: dask_cuda.initialize
2022-08-19 11:28:25,721 - distributed.preloading - INFO - Import preload module: dask_cuda.initialize
[7]:

Client

Client-0aaac76b-1fb2-11ed-903e-0242ac110007

Connection method: Cluster object Cluster type: dask_cuda.LocalCUDACluster
Dashboard: http://127.0.0.1:8787/status

Cluster Info

[8]:
from cuml.dask.datasets import make_blobs

n_workers = len(client.scheduler_info()["workers"].keys())

X, y = make_blobs(n_samples=5000,
                  n_features=30,
                  centers=5,
                  cluster_std=0.4,
                  random_state=0,
                  n_parts=n_workers*5)

X = X.persist()
y = y.persist()
[9]:
from cuml.dask.cluster import KMeans

dist_model = KMeans(n_clusters=5)
[10]:
dist_model.fit(X)
2022-08-19 11:28:33,148 - distributed.worker - WARNING - Compute Failed
Key:       _get_model_attr-ff2c6f0c-51e0-4368-b96d-e8bb4ebd3e3c
Function:  _get_model_attr
args:      (KMeansMG(), '_ipython_canary_method_should_not_exist_')
kwargs:    {}
Exception: 'AttributeError("Attribute _ipython_canary_method_should_not_exist_ does not exist on model <class \'cuml.cluster.kmeans_mg.KMeansMG\'>")'

2022-08-19 11:28:33,170 - distributed.worker - WARNING - Compute Failed
Key:       _get_model_attr-de1145a2-03eb-4874-862b-274d31740466
Function:  _get_model_attr
args:      (KMeansMG(), '_ipython_display_')
kwargs:    {}
Exception: 'AttributeError("Attribute _ipython_display_ does not exist on model <class \'cuml.cluster.kmeans_mg.KMeansMG\'>")'

2022-08-19 11:28:33,188 - distributed.worker - WARNING - Compute Failed
Key:       _get_model_attr-de450df7-70d0-4a84-af4d-5a8213876737
Function:  _get_model_attr
args:      (KMeansMG(), '_ipython_canary_method_should_not_exist_')
kwargs:    {}
Exception: 'AttributeError("Attribute _ipython_canary_method_should_not_exist_ does not exist on model <class \'cuml.cluster.kmeans_mg.KMeansMG\'>")'

2022-08-19 11:28:33,206 - distributed.worker - WARNING - Compute Failed
Key:       _get_model_attr-bf9d640b-1b06-4466-9710-db3222f5d68a
Function:  _get_model_attr
args:      (KMeansMG(), '_repr_mimebundle_')
kwargs:    {}
Exception: 'AttributeError("Attribute _repr_mimebundle_ does not exist on model <class \'cuml.cluster.kmeans_mg.KMeansMG\'>")'

2022-08-19 11:28:33,223 - distributed.worker - WARNING - Compute Failed
Key:       _get_model_attr-bfd991cc-efd5-462f-b346-0c0ae0a2bd5d
Function:  _get_model_attr
args:      (KMeansMG(), '_ipython_canary_method_should_not_exist_')
kwargs:    {}
Exception: 'AttributeError("Attribute _ipython_canary_method_should_not_exist_ does not exist on model <class \'cuml.cluster.kmeans_mg.KMeansMG\'>")'

2022-08-19 11:28:33,243 - distributed.worker - WARNING - Compute Failed
Key:       _get_model_attr-19265334-501c-4d12-a216-8a66c995eeda
Function:  _get_model_attr
args:      (KMeansMG(), '_repr_html_')
kwargs:    {}
Exception: 'AttributeError("Attribute _repr_html_ does not exist on model <class \'cuml.cluster.kmeans_mg.KMeansMG\'>")'

2022-08-19 11:28:33,255 - distributed.worker - WARNING - Compute Failed
Key:       _get_model_attr-269e7c54-98c3-40c0-b7c5-04f16ca75422
Function:  _get_model_attr
args:      (KMeansMG(), '_ipython_canary_method_should_not_exist_')
kwargs:    {}
Exception: 'AttributeError("Attribute _ipython_canary_method_should_not_exist_ does not exist on model <class \'cuml.cluster.kmeans_mg.KMeansMG\'>")'

2022-08-19 11:28:33,267 - distributed.worker - WARNING - Compute Failed
Key:       _get_model_attr-9aed091a-5a06-46d9-8195-bd3b38aa99bf
Function:  _get_model_attr
args:      (KMeansMG(), '_repr_markdown_')
kwargs:    {}
Exception: 'AttributeError("Attribute _repr_markdown_ does not exist on model <class \'cuml.cluster.kmeans_mg.KMeansMG\'>")'

2022-08-19 11:28:33,282 - distributed.worker - WARNING - Compute Failed
Key:       _get_model_attr-4fe2f707-1e9e-42c6-affa-2a7bc8adf446
Function:  _get_model_attr
args:      (KMeansMG(), '_ipython_canary_method_should_not_exist_')
kwargs:    {}
Exception: 'AttributeError("Attribute _ipython_canary_method_should_not_exist_ does not exist on model <class \'cuml.cluster.kmeans_mg.KMeansMG\'>")'

2022-08-19 11:28:33,302 - distributed.worker - WARNING - Compute Failed
Key:       _get_model_attr-d0766d7d-6dfe-4072-b837-dcd9f0720361
Function:  _get_model_attr
args:      (KMeansMG(), '_repr_svg_')
kwargs:    {}
Exception: 'AttributeError("Attribute _repr_svg_ does not exist on model <class \'cuml.cluster.kmeans_mg.KMeansMG\'>")'

2022-08-19 11:28:33,324 - distributed.worker - WARNING - Compute Failed
Key:       _get_model_attr-aa4e18de-812d-4ff6-a302-5099c6505f3d
Function:  _get_model_attr
args:      (KMeansMG(), '_ipython_canary_method_should_not_exist_')
kwargs:    {}
Exception: 'AttributeError("Attribute _ipython_canary_method_should_not_exist_ does not exist on model <class \'cuml.cluster.kmeans_mg.KMeansMG\'>")'

2022-08-19 11:28:33,345 - distributed.worker - WARNING - Compute Failed
Key:       _get_model_attr-26f4afac-8cd6-47c3-8e26-4ba3e509532b
Function:  _get_model_attr
args:      (KMeansMG(), '_repr_png_')
kwargs:    {}
Exception: 'AttributeError("Attribute _repr_png_ does not exist on model <class \'cuml.cluster.kmeans_mg.KMeansMG\'>")'

2022-08-19 11:28:33,359 - distributed.worker - WARNING - Compute Failed
Key:       _get_model_attr-fda2ee2c-f689-4dd9-91da-f500c3186eb1
Function:  _get_model_attr
args:      (KMeansMG(), '_ipython_canary_method_should_not_exist_')
kwargs:    {}
Exception: 'AttributeError("Attribute _ipython_canary_method_should_not_exist_ does not exist on model <class \'cuml.cluster.kmeans_mg.KMeansMG\'>")'

2022-08-19 11:28:33,373 - distributed.worker - WARNING - Compute Failed
Key:       _get_model_attr-75997d69-1fcc-45fb-aff4-04351c84ab96
Function:  _get_model_attr
args:      (KMeansMG(), '_repr_pdf_')
kwargs:    {}
Exception: 'AttributeError("Attribute _repr_pdf_ does not exist on model <class \'cuml.cluster.kmeans_mg.KMeansMG\'>")'

2022-08-19 11:28:33,386 - distributed.worker - WARNING - Compute Failed
Key:       _get_model_attr-384edb89-c0a9-4cf9-a5e9-3f33a0885238
Function:  _get_model_attr
args:      (KMeansMG(), '_ipython_canary_method_should_not_exist_')
kwargs:    {}
Exception: 'AttributeError("Attribute _ipython_canary_method_should_not_exist_ does not exist on model <class \'cuml.cluster.kmeans_mg.KMeansMG\'>")'

2022-08-19 11:28:33,409 - distributed.worker - WARNING - Compute Failed
Key:       _get_model_attr-b2baa8aa-5b11-4584-9a90-29a41dfb5df1
Function:  _get_model_attr
args:      (KMeansMG(), '_repr_jpeg_')
kwargs:    {}
Exception: 'AttributeError("Attribute _repr_jpeg_ does not exist on model <class \'cuml.cluster.kmeans_mg.KMeansMG\'>")'

2022-08-19 11:28:33,430 - distributed.worker - WARNING - Compute Failed
Key:       _get_model_attr-546a4dfe-5cbd-4eda-8a1d-c816f953ffb3
Function:  _get_model_attr
args:      (KMeansMG(), '_ipython_canary_method_should_not_exist_')
kwargs:    {}
Exception: 'AttributeError("Attribute _ipython_canary_method_should_not_exist_ does not exist on model <class \'cuml.cluster.kmeans_mg.KMeansMG\'>")'

2022-08-19 11:28:33,443 - distributed.worker - WARNING - Compute Failed
Key:       _get_model_attr-2eafc8b5-a04f-4e93-9fed-e8126842a307
Function:  _get_model_attr
args:      (KMeansMG(), '_repr_latex_')
kwargs:    {}
Exception: 'AttributeError("Attribute _repr_latex_ does not exist on model <class \'cuml.cluster.kmeans_mg.KMeansMG\'>")'

2022-08-19 11:28:33,456 - distributed.worker - WARNING - Compute Failed
Key:       _get_model_attr-fe6a842f-302b-452b-87b0-ab4f9ae95133
Function:  _get_model_attr
args:      (KMeansMG(), '_ipython_canary_method_should_not_exist_')
kwargs:    {}
Exception: 'AttributeError("Attribute _ipython_canary_method_should_not_exist_ does not exist on model <class \'cuml.cluster.kmeans_mg.KMeansMG\'>")'

2022-08-19 11:28:33,470 - distributed.worker - WARNING - Compute Failed
Key:       _get_model_attr-984a4456-e492-4a7d-b25e-bc22d4e06c32
Function:  _get_model_attr
args:      (KMeansMG(), '_repr_json_')
kwargs:    {}
Exception: 'AttributeError("Attribute _repr_json_ does not exist on model <class \'cuml.cluster.kmeans_mg.KMeansMG\'>")'

2022-08-19 11:28:33,490 - distributed.worker - WARNING - Compute Failed
Key:       _get_model_attr-015c030f-b579-4075-a1fc-2eec2a001c4b
Function:  _get_model_attr
args:      (KMeansMG(), '_ipython_canary_method_should_not_exist_')
kwargs:    {}
Exception: 'AttributeError("Attribute _ipython_canary_method_should_not_exist_ does not exist on model <class \'cuml.cluster.kmeans_mg.KMeansMG\'>")'

2022-08-19 11:28:33,505 - distributed.worker - WARNING - Compute Failed
Key:       _get_model_attr-ceed6b76-a773-4c99-9346-636d0db199bc
Function:  _get_model_attr
args:      (KMeansMG(), '_repr_javascript_')
kwargs:    {}
Exception: 'AttributeError("Attribute _repr_javascript_ does not exist on model <class \'cuml.cluster.kmeans_mg.KMeansMG\'>")'

[10]:
<cuml.dask.cluster.kmeans.KMeans at 0x7f77a37546d0>
[11]:
import pickle

single_gpu_model = dist_model.get_combined_model()
pickle.dump(single_gpu_model, open("kmeans_model.pkl", "wb"))
[12]:
single_gpu_model = pickle.load(open("kmeans_model.pkl", "rb"))
[13]:
single_gpu_model.cluster_centers_
[13]:
array([[-4.6475401e+00, -9.5672169e+00,  6.6923523e+00,  4.4359245e+00,
         2.1902733e+00,  2.5834756e+00,  5.9448934e-01,  6.2568669e+00,
        -8.7821646e+00, -4.1232008e-01,  9.8151770e+00,  7.5641565e+00,
         1.0003009e+01, -5.8680429e+00, -1.2743109e+00, -2.5393455e+00,
        -1.0847499e+00, -5.2629204e+00, -9.3071022e+00,  4.6179361e+00,
        -9.7068958e-02, -3.9351206e+00,  6.1767278e+00, -7.4346881e+00,
         5.6496072e+00, -8.5544853e+00, -7.5265589e+00, -5.5195603e+00,
         4.8197632e+00,  2.5235438e+00],
       [ 6.2794294e+00,  9.2293949e+00,  8.3403711e+00,  9.0330496e+00,
         7.6893492e+00, -9.9538219e-01, -6.2780762e+00,  1.3599334e+00,
        -6.9744482e+00, -5.9463463e+00,  1.0695117e+00, -8.0422489e-03,
         2.8183143e+00,  1.8317667e+00, -8.2557344e+00,  3.0514317e+00,
        -8.4958029e+00,  9.7238483e+00, -7.7455091e+00,  3.4521689e+00,
        -3.9248335e+00, -4.1106420e+00,  2.6693091e+00,  1.2985630e+00,
         1.0421573e+00,  5.2490621e+00, -1.6496236e+00,  6.1451659e+00,
        -6.9103327e+00, -9.6390305e+00],
       [-2.8796387e+00,  4.4348764e+00, -4.4264808e+00,  2.3959143e+00,
         1.7286435e+00, -2.4991984e+00, -5.1794519e+00, -1.6771442e+00,
        -8.1329174e+00,  2.6659229e+00, -4.3131099e+00,  5.5827808e+00,
        -5.7318306e+00, -1.7427170e+00, -9.3456125e+00,  7.1365565e-01,
         4.4255495e+00, -2.9118378e+00, -4.9467440e+00,  9.6786404e+00,
         8.4222765e+00, -6.2710242e+00, -6.3596506e+00,  1.9645507e+00,
         4.1715999e+00, -9.1683645e+00,  4.6156688e+00,  8.7916489e+00,
         6.8754420e+00,  2.2288744e+00],
       [-6.9536948e+00, -9.7635880e+00, -6.5648255e+00, -4.3536150e-01,
         6.0998111e+00,  3.7550373e+00, -3.9558539e+00,  6.1595521e+00,
        -1.8599317e+00,  5.0400305e+00, -6.8397551e+00,  1.3435434e+00,
         8.9749012e+00, -9.9621785e-01,  9.6651936e+00,  9.8009653e+00,
        -8.6188335e+00,  5.9978361e+00,  2.2295933e+00, -3.6477711e+00,
         7.0758505e+00, -7.3772259e+00, -5.3214226e+00, -6.9927955e+00,
        -7.9296327e+00,  6.6705356e+00, -5.5850177e+00,  7.1526046e+00,
         6.5703206e+00, -8.3389378e+00],
       [ 4.8136687e+00,  8.3985281e+00, -9.2161245e+00,  9.4185514e+00,
         8.5280886e+00, -1.0969982e+00,  3.3253179e+00, -7.8064380e+00,
        -5.9660631e-01,  2.5423869e-01,  5.5004086e+00, -4.1162968e+00,
         4.2832379e+00, -2.8173416e+00,  3.6207724e+00, -4.1576219e+00,
        -3.6048703e+00,  6.2125401e+00, -6.9080992e+00, -1.0732133e+00,
        -5.8362112e+00,  2.2357666e+00, -3.8588789e+00, -1.6835877e+00,
        -5.3240366e+00,  7.5769200e+00,  2.9358530e+00,  8.5267372e+00,
         1.5667248e+00,  1.0779673e+00]], dtype=float32)

Exporting cuML Random Forest models for inferencing on machines without GPUs

Starting with cuML version 21.06, you can export cuML Random Forest models and run predictions with them on machines without an NVIDIA GPUs. The Treelite package defines an efficient exchange format that lets you portably move the cuML Random Forest models to other machines. We will refer to the exchange format as “checkpoints.”

Here are the steps to export the model:

  1. Call to_treelite_checkpoint() to obtain the checkpoint file from the cuML Random Forest model.

[14]:
from cuml.ensemble import RandomForestClassifier as cumlRandomForestClassifier
from sklearn.datasets import load_iris
import numpy as np

X, y = load_iris(return_X_y=True)
X, y = X.astype(np.float32), y.astype(np.int32)
clf = cumlRandomForestClassifier(max_depth=3, random_state=0, n_estimators=10)
clf.fit(X, y)

checkpoint_path = './checkpoint.tl'
# Export cuML RF model as Treelite checkpoint
clf.convert_to_treelite_model().to_treelite_checkpoint(checkpoint_path)
/opt/conda/envs/rapids/lib/python3.9/site-packages/cuml/internals/api_decorators.py:794: UserWarning: For reproducible results in Random Forest Classifier or for almost reproducible results in Random Forest Regressor, n_streams=1 is recommended. If n_streams is > 1, results may vary due to stream/thread timing differences, even when random_state is set
  return func(**kwargs)
  1. Copy the generated checkpoint file checkpoint.tl to another machine on which you’d like to run predictions.

  2. On the target machine, install Treelite by running pip install treelite or conda install -c conda-forge treelite. The machine does not need to have an NVIDIA GPUs and does not need to have cuML installed.

  3. You can now load the model from the checkpoint, by running the following on the target machine:

[15]:
import treelite

# The checkpoint file has been copied over
checkpoint_path = './checkpoint.tl'
tl_model = treelite.Model.deserialize(checkpoint_path)
out_prob = treelite.gtil.predict(tl_model, X, pred_margin=True)
print(out_prob)
[[1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [0.90789473 0.09210526 0.        ]
 [0.90789473 0.09210526 0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [0.90789473 0.09210526 0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [1.         0.         0.        ]
 [0.00789474 0.96374357 0.02836171]
 [0.00789474 0.96374357 0.02836171]
 [0.00789474 0.7819892  0.2101161 ]
 [0.         0.99018145 0.00981859]
 [0.00789474 0.96374357 0.02836171]
 [0.00789474 0.975835   0.01627021]
 [0.00789474 0.96374357 0.02836171]
 [0.         0.8568481  0.14315192]
 [0.00789474 0.96374357 0.02836171]
 [0.         0.99018145 0.00981859]
 [0.         0.99018145 0.00981859]
 [0.00789474 0.975835   0.01627021]
 [0.00789474 0.975835   0.01627021]
 [0.00789474 0.975835   0.01627021]
 [0.10789473 0.88228667 0.00981859]
 [0.00789474 0.96374357 0.02836171]
 [0.00789474 0.98228663 0.00981859]
 [0.00789474 0.975835   0.01627021]
 [0.00789474 0.975835   0.01627021]
 [0.10789473 0.88228667 0.00981859]
 [0.         0.25154537 0.7484547 ]
 [0.00789474 0.975835   0.01627021]
 [0.00789474 0.7819892  0.2101161 ]
 [0.00789474 0.975835   0.01627021]
 [0.00789474 0.96374357 0.02836171]
 [0.00789474 0.96374357 0.02836171]
 [0.00789474 0.79310024 0.199005  ]
 [0.         0.451291   0.54870903]
 [0.00789474 0.975835   0.01627021]
 [0.10789473 0.87583506 0.01627021]
 [0.         0.99018145 0.00981859]
 [0.         0.99018145 0.00981859]
 [0.10789473 0.87583506 0.01627021]
 [0.         0.18708128 0.8129188 ]
 [0.         0.99018145 0.00981859]
 [0.00789474 0.975835   0.01627021]
 [0.00789474 0.96374357 0.02836171]
 [0.00789474 0.96374357 0.02836171]
 [0.00789474 0.98228663 0.00981859]
 [0.         0.99018145 0.00981859]
 [0.         0.99018145 0.00981859]
 [0.00789474 0.975835   0.01627021]
 [0.00789474 0.975835   0.01627021]
 [0.         0.99018145 0.00981859]
 [0.00789474 0.98228663 0.00981859]
 [0.00789474 0.975835   0.01627021]
 [0.00789474 0.975835   0.01627021]
 [0.00789474 0.975835   0.01627021]
 [0.         0.99018145 0.00981859]
 [0.00789474 0.975835   0.01627021]
 [0.         0.01258634 0.9874137 ]
 [0.         0.0481924  0.9518076 ]
 [0.         0.01258634 0.9874137 ]
 [0.         0.01258634 0.9874137 ]
 [0.         0.01258634 0.9874137 ]
 [0.         0.01258634 0.9874137 ]
 [0.         0.6901814  0.3098186 ]
 [0.         0.01258634 0.9874137 ]
 [0.         0.01258634 0.9874137 ]
 [0.         0.01258634 0.9874137 ]
 [0.         0.01258634 0.9874137 ]
 [0.         0.01258634 0.9874137 ]
 [0.         0.01258634 0.9874137 ]
 [0.         0.15504913 0.84495085]
 [0.         0.0481924  0.9518076 ]
 [0.         0.01258634 0.9874137 ]
 [0.         0.01258634 0.9874137 ]
 [0.         0.01258634 0.9874137 ]
 [0.         0.01258634 0.9874137 ]
 [0.         0.40701494 0.59298503]
 [0.         0.01258634 0.9874137 ]
 [0.         0.14688587 0.8531141 ]
 [0.         0.01258634 0.9874137 ]
 [0.         0.28718114 0.71281886]
 [0.         0.01258634 0.9874137 ]
 [0.         0.01258634 0.9874137 ]
 [0.         0.22427265 0.7757274 ]
 [0.         0.21316154 0.7868384 ]
 [0.         0.01258634 0.9874137 ]
 [0.         0.17874795 0.82125205]
 [0.         0.01258634 0.9874137 ]
 [0.         0.01258634 0.9874137 ]
 [0.         0.01258634 0.9874137 ]
 [0.         0.21682489 0.7831751 ]
 [0.         0.22515821 0.77484185]
 [0.         0.01258634 0.9874137 ]
 [0.         0.01258634 0.9874137 ]
 [0.         0.01258634 0.9874137 ]
 [0.         0.22427265 0.7757274 ]
 [0.         0.01258634 0.9874137 ]
 [0.         0.01258634 0.9874137 ]
 [0.         0.01258634 0.9874137 ]
 [0.         0.0481924  0.9518076 ]
 [0.         0.01258634 0.9874137 ]
 [0.         0.01258634 0.9874137 ]
 [0.         0.01258634 0.9874137 ]
 [0.         0.20179601 0.798204  ]
 [0.         0.01258634 0.9874137 ]
 [0.         0.02091968 0.9790803 ]
 [0.         0.0481924  0.9518076 ]]