forked from kubeflow/pipelines
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request kubeflow#75 from animeshsingh/sklearn-server
Sklearn server
- Loading branch information
Showing
8 changed files
with
141 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
## Creating your own model and testing the SKLearn server. | ||
|
||
To test the Scikit-learn Server, first we need to generate a simple scikit-learn model using Python. Sample model is also added in this directory to reuse if needed. | ||
|
||
```python | ||
from sklearn import svm | ||
from sklearn import datasets | ||
from joblib import dump | ||
clf = svm.SVC(gamma='scale') | ||
iris = datasets.load_iris() | ||
X, y = iris.data, iris.target | ||
clf.fit(X, y) | ||
dump(clf, 'model.joblib') | ||
``` | ||
|
||
Then, we can run the Scikit-learn Server using the generated model and test for prediction. Models can be on local filesystem, S3 compatible object storage or Google Cloud Storage. | ||
|
||
```shell | ||
python -m sklearnserver --model_dir model.joblib --model_name svm | ||
``` | ||
|
||
We can also use the inbuilt sklearn support for sample datasets and do some simple predictions | ||
|
||
```python | ||
from sklearn import datasets | ||
import requests | ||
iris = datasets.load_iris() | ||
X, y = iris.data, iris.target | ||
formData = { | ||
'instances': X[0:1].tolist() | ||
} | ||
res = requests.post('http://localhost:8080/models/svm:predict', json=formData) | ||
print(res) | ||
print(res.text) | ||
``` |
Binary file not shown.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# Scikit-Learn Server | ||
|
||
[Scikit-Learn](https://scikit-learn.org/stable/) server is an implementation of KFServing for serving Scikit-learn models, and provides a Scikit-learn model implementation for prediction, pre and post processing. | ||
|
||
To start the server locally for development needs, run the following command under this folder in your github repository. | ||
|
||
``` | ||
pip install -e . | ||
``` | ||
|
||
The following output indicates a successful install. | ||
|
||
``` | ||
Obtaining file://kfserving/python/sklearn | ||
Requirement already satisfied: kfserver==0.1.0 in /Users/username/Desktop/kfserving/python/kfserving (from sklearnserver==0.1.0) (0.1.0) | ||
Requirement already satisfied: scikit-learn==0.20.3 in /anaconda3/lib/python3.6/site-packages (from sklearnserver==0.1.0) (0.20.3) | ||
Requirement already satisfied: argparse>=1.4.0 in /anaconda3/lib/python3.6/site-packages (from sklearnserver==0.1.0) (1.4.0) | ||
Requirement already satisfied: numpy>=1.8.2 in /anaconda3/lib/python3.6/site-packages (from sklearnserver==0.1.0) (1.16.2) | ||
Requirement already satisfied: tornado>=1.4.1 in /anaconda3/lib/python3.6/site-packages (from kfserver==0.1.0->sklearnserver==0.1.0) (5.0.2) | ||
Requirement already satisfied: scipy>=0.13.3 in /anaconda3/lib/python3.6/site-packages (from scikit-learn==0.20.3->sklearnserver==0.1.0) (1.1.0) | ||
Installing collected packages: sklearnserver | ||
Found existing installation: sklearnserver 0.1.0 | ||
Uninstalling sklearnserver-0.1.0: | ||
Successfully uninstalled sklearnserver-0.1.0 | ||
Running setup.py develop for sklearnserver | ||
Successfully installed sklearnserver | ||
``` | ||
|
||
Once Scikit-learn server is up and running, you can check for successful installation by running the following command | ||
|
||
``` | ||
python3 -m sklearnserver | ||
usage: __main__.py [-h] [--http_port HTTP_PORT] [--grpc_port GRPC_PORT] | ||
--model_dir MODEL_DIR [--model_name MODEL_NAME] | ||
__main__.py: error: the following arguments are required: --model_dir | ||
``` | ||
|
||
You can now point to your `joblib` model file and use the server to load the model and test for prediction. Models can be on local filesystem, S3 compatible object storage or Google Cloud Storage. Please follow [this sample](https://github.com/kubeflow/kfserving/tree/master/docs/samples/sklearn) to test your server by generating your own model. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
from setuptools import setup, find_packages | ||
|
||
setup( | ||
name='sklearnserver', | ||
version='0.1.0', | ||
author_email='singhan@us.ibm.com', | ||
license='https://github.com/kubeflow/kfserving/LICENSE', | ||
url='https://github.com/kubeflow/kfserving/python/sklearnserver', | ||
description='Model Server implementation for scikit-learn. Not intended for use outside KFServing Frameworks Images', | ||
long_description=open('README.md').read(), | ||
python_requires='>3.4', | ||
packages=find_packages("sklearnserver"), | ||
install_requires=[ | ||
"kfserver==0.1.0", | ||
"scikit-learn == 0.20.3", | ||
"argparse >= 1.4.0", | ||
"numpy >= 1.8.2", | ||
"joblib >= 0.13.0" | ||
], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from .model import SKLearnModel |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import kfserving | ||
import argparse | ||
|
||
|
||
from sklearnserver import SKLearnModel | ||
|
||
DEFAULT_MODEL_NAME = "model" | ||
DEFAULT_LOCAL_MODEL_DIR = "/tmp/model" | ||
|
||
parser = argparse.ArgumentParser(parents=[kfserving.server.parser]) | ||
parser.add_argument('--model_dir', required=True, | ||
help='A URI pointer to the model binary') | ||
parser.add_argument('--model_name', default=DEFAULT_MODEL_NAME, | ||
help='The name that the model is served under.') | ||
args, _ = parser.parse_known_args() | ||
|
||
if __name__ == "__main__": | ||
model = SKLearnModel(args.model_name, args.model_dir) | ||
model.load() | ||
kfserving.KFServer().start([model]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import kfserving | ||
import joblib | ||
import numpy as np | ||
import os | ||
|
||
class SKLearnModel(kfserving.KFModel): | ||
def __init__(self, name, model_dir): | ||
self.name = name | ||
self.model_dir = model_dir | ||
self.ready = False | ||
|
||
def load(self): | ||
model_file = kfserving.Storage.download(self.model_dir) | ||
self._joblib = joblib.load(model_file) | ||
self.ready = True | ||
|
||
def predict(self, inputs): | ||
try: | ||
inputs = np.array(inputs) | ||
except Exception as e: | ||
raise Exception( | ||
"Failed to initialize NumPy array from inputs: %s, %s" % (e, inputs)) | ||
try: | ||
result = self._joblib.predict(inputs).tolist() | ||
return result | ||
except Exception as e: | ||
raise Exception("Failed to predict %s" % e) |