├── dev-requirements.txt
├── benchmark
├── benchmark-requirements.txt
├── ray_deploy.py
├── locustfile.py
├── fastapi_main_load_model.py
├── fastapi_main_local_runner.py
├── README.md
├── service.py
├── service_local_runner.py
└── sample.py
├── train.sh
├── submit_test_requests.sh
├── bentofile.yaml
├── inference_graph_demo
├── bentofile.yaml
├── service.py
└── sample.py
├── download_data.sh
├── bentofile-gpu.yaml
├── service.py
├── .gitignore
├── README.md
├── sample.py
└── LICENSE
/dev-requirements.txt:
--------------------------------------------------------------------------------
1 | notebook
2 | kaggle
3 | jupyter
4 | numpy
5 | pandas
6 | xgboost
7 | scikit-learn
8 | nbconvert
9 |
--------------------------------------------------------------------------------
/benchmark/benchmark-requirements.txt:
--------------------------------------------------------------------------------
1 | numpy
2 | pandas
3 | xgboost
4 | scikit-learn
5 | fastapi
6 | uvicorn[standard]
7 | locust
8 |
--------------------------------------------------------------------------------
/train.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | jupyter nbconvert --to notebook --inplace --execute ./IEEE-CIS-Fraud-Detection.ipynb --debug 2>&1 | grep -v '^\[NbConvertApp\]'
4 |
--------------------------------------------------------------------------------
/submit_test_requests.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | head --lines=200 ./data/test_transaction.csv | curl -X POST -H 'Content-Type: text/csv' --data-binary @- http://0.0.0.0:3000/is_fraud
4 |
--------------------------------------------------------------------------------
/bentofile.yaml:
--------------------------------------------------------------------------------
1 | service: "service:svc"
2 | include:
3 | - "service.py"
4 | - "sample.py"
5 | python:
6 | packages:
7 | - numpy
8 | - pandas
9 | - xgboost
10 | - scikit-learn
11 |
--------------------------------------------------------------------------------
/inference_graph_demo/bentofile.yaml:
--------------------------------------------------------------------------------
1 | service: "inference_graph_service:svc"
2 | include:
3 | - "*.py"
4 | python:
5 | packages:
6 | - numpy
7 | - pandas
8 | - xgboost
9 | - scikit-learn
10 |
--------------------------------------------------------------------------------
/download_data.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -ex
4 |
5 | kaggle competitions download -c ieee-fraud-detection
6 | rm -rf ./data/
7 | unzip -o -d ./data/ ieee-fraud-detection.zip && rm ieee-fraud-detection.zip
8 |
--------------------------------------------------------------------------------
/bentofile-gpu.yaml:
--------------------------------------------------------------------------------
1 | service: "service:svc"
2 | include:
3 | - "service.py"
4 | - "sample.py"
5 | docker:
6 | cuda_version: "11.6.2"
7 | python:
8 | packages:
9 | - numpy
10 | - pandas
11 | - xgboost
12 | - scikit-learn
13 |
--------------------------------------------------------------------------------
/benchmark/ray_deploy.py:
--------------------------------------------------------------------------------
1 | import bentoml
2 |
3 | deploy = bentoml.ray.deployment(
4 | "fraud_detection:latest",
5 | {"num_replicas": 5, "ray_actor_options": {"num_cpus": 1}},
6 | {
7 | "ieee-fraud-detection-sm": {
8 | "num_replicas": 1,
9 | "ray_actor_options": {"num_cpus": 5},
10 | }
11 | },
12 | enable_batching=True,
13 | batching_config={
14 | "ieee-fraud-detection-sm": {
15 | "predict_proba": {"max_batch_size": 5, "batch_wait_timeout_s": 0.2}
16 | }
17 | },
18 | )
19 |
--------------------------------------------------------------------------------
/benchmark/locustfile.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import pandas as pd
3 | from locust import task
4 | from locust import between
5 | from locust import HttpUser
6 |
7 | NUM_OF_ROWS = 500
8 | test_transactions = pd.read_csv("../data/test_transaction.csv")[0:NUM_OF_ROWS]
9 |
10 | endpoint = "/is_fraud"
11 | # endpoint = "/is_fraud_async"
12 |
13 |
14 | class FraudDetectionUser(HttpUser):
15 | @task
16 | def is_fraud(self):
17 | index = np.random.choice(NUM_OF_ROWS)
18 | input_data = test_transactions[index : index + 1]
19 | self.client.post(endpoint, data=input_data.to_json())
20 |
21 | wait_time = between(0.01, 2)
22 |
--------------------------------------------------------------------------------
/service.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import pandas as pd
3 | from sample import sample_input
4 |
5 | import bentoml
6 | from bentoml.io import JSON
7 | from bentoml.io import PandasDataFrame
8 |
9 | model_ref = bentoml.xgboost.get("ieee-fraud-detection-lg:latest")
10 | preprocessor = model_ref.custom_objects["preprocessor"]
11 | fraud_model_runner = model_ref.to_runner()
12 |
13 | svc = bentoml.Service("fraud_detection", runners=[fraud_model_runner])
14 |
15 | input_spec = PandasDataFrame.from_sample(sample_input)
16 |
17 |
18 | @svc.api(input=input_spec, output=JSON())
19 | async def is_fraud(input_df: pd.DataFrame):
20 | input_df = input_df.astype(sample_input.dtypes)
21 | input_features = preprocessor.transform(input_df)
22 | results = await fraud_model_runner.predict_proba.async_run(input_features)
23 | predictions = np.argmax(results, axis=1) # 0 is not fraud, 1 is fraud
24 | return {"is_fraud": list(map(bool, predictions)), "is_fraud_prob": results[:, 1]}
25 |
--------------------------------------------------------------------------------
/benchmark/fastapi_main_load_model.py:
--------------------------------------------------------------------------------
1 | import io
2 |
3 | import numpy as np
4 | import pandas as pd
5 | from sample import sample_input
6 | from fastapi import FastAPI
7 | from fastapi import Request
8 |
9 | import bentoml
10 |
11 | model_tag = "ieee-fraud-detection-lg:latest"
12 | preprocessor = bentoml.xgboost.get(model_tag).custom_objects["preprocessor"]
13 | fraud_model = bentoml.xgboost.load_model(model_tag)
14 |
15 | app = FastAPI()
16 |
17 |
18 | @app.post("/is_fraud")
19 | async def is_fraud(request: Request):
20 | body = await request.body()
21 | input_df = pd.read_json(io.BytesIO(body), dtype=True, orient="records")
22 | input_df = input_df.astype(sample_input.dtypes)
23 | input_features = preprocessor.transform(input_df)
24 | results = fraud_model.predict_proba(input_features)
25 | predictions = np.argmax(results, axis=1) # 0 is not fraud, 1 is fraud
26 | return {
27 | "is_fraud": list(map(bool, predictions)),
28 | "is_fraud_prob": results[:, 1].tolist(),
29 | }
30 |
--------------------------------------------------------------------------------
/benchmark/fastapi_main_local_runner.py:
--------------------------------------------------------------------------------
1 | import io
2 |
3 | import numpy as np
4 | import pandas as pd
5 | from sample import sample_input
6 | from fastapi import FastAPI
7 | from fastapi import Request
8 |
9 | import bentoml
10 |
11 | model_ref = bentoml.xgboost.get("ieee-fraud-detection-lg:latest")
12 | preprocessor = model_ref.custom_objects["preprocessor"]
13 | fraud_model_runner = model_ref.to_runner()
14 | fraud_model_runner.init_local()
15 |
16 | app = FastAPI()
17 |
18 |
19 | @app.post("/is_fraud")
20 | async def is_fraud(request: Request):
21 | body = await request.body()
22 | input_df = pd.read_json(io.BytesIO(body), dtype=True, orient="records")
23 | input_df = input_df.astype(sample_input.dtypes)
24 | input_features = preprocessor.transform(input_df)
25 | results = await fraud_model_runner.predict_proba.async_run(input_features)
26 | predictions = np.argmax(results, axis=1) # 0 is not fraud, 1 is fraud
27 | return {
28 | "is_fraud": list(map(bool, predictions)),
29 | "is_fraud_prob": results[:, 1].tolist(),
30 | }
31 |
--------------------------------------------------------------------------------
/benchmark/README.md:
--------------------------------------------------------------------------------
1 | # Benchmark
2 |
3 | 1. Install dependencies:
4 | ```bash
5 | pip install -r ./dev-requirements.txt
6 | ```
7 |
8 | 2. Benchmark with Locust
9 | ```bash
10 | bentoml serve service:svc --production
11 | ```
12 | ```bash
13 | locust -H http://0.0.0.0:3000 -u 200 -r 10
14 | ```
15 |
16 | Visit http://0.0.0.0:8089/ and start the test.
17 |
18 | 3. Testing other serving methods
19 |
20 | * BentoML with distributed Runner architecture (default, recommended for most use cases)
21 | ```bash
22 | bentoml serve service:svc --production
23 | ```
24 |
25 | * BentoML with embedded local Runner (recommended for light-weight models)
26 | ```bash
27 | bentoml serve service_local_runner:svc --production
28 | ```
29 |
30 | * A typical FastAPI implementation with XGBoost syncrounous API for inference:
31 |
32 | ```bash
33 | uvicorn fastapi_main_load_model:app --workers=10 --port=3000
34 | ```
35 |
36 | * FastAPI endpoint with BentoML runner async API for inference:
37 |
38 | ```bash
39 | uvicorn fastapi_main_local_runner:app --workers=10 --port=3000
40 | ```
41 |
42 | * BentoML deployed on Ray
43 |
44 | serve run ray_deploy:deploy -p 3000
45 |
--------------------------------------------------------------------------------
/benchmark/service.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import pandas as pd
3 | from sample import sample_input
4 |
5 | import bentoml
6 | from bentoml.io import JSON
7 | from bentoml.io import PandasDataFrame
8 |
9 | model_ref = bentoml.xgboost.get("ieee-fraud-detection-lg:latest")
10 | preprocessor = model_ref.custom_objects["preprocessor"]
11 | fraud_model_runner = model_ref.to_runner()
12 |
13 | svc = bentoml.Service("fraud_detection", runners=[fraud_model_runner])
14 |
15 | input_spec = PandasDataFrame.from_sample(sample_input)
16 |
17 |
18 | @svc.api(input=input_spec, output=JSON())
19 | def is_fraud(input_df: pd.DataFrame):
20 | input_df = input_df.astype(sample_input.dtypes)
21 | input_features = preprocessor.transform(input_df)
22 | results = fraud_model_runner.predict_proba.run(input_features)
23 | predictions = np.argmax(results, axis=1) # 0 is not fraud, 1 is fraud
24 | return {"is_fraud": list(map(bool, predictions)), "is_fraud_prob": results[:, 1]}
25 |
26 |
27 | @svc.api(input=input_spec, output=JSON())
28 | async def is_fraud_async(input_df: pd.DataFrame):
29 | input_df = input_df.astype(sample_input.dtypes)
30 | input_features = preprocessor.transform(input_df)
31 | results = await fraud_model_runner.predict_proba.async_run(input_features)
32 | predictions = np.argmax(results, axis=1) # 0 is not fraud, 1 is fraud
33 | return {"is_fraud": list(map(bool, predictions)), "is_fraud_prob": results[:, 1]}
34 |
--------------------------------------------------------------------------------
/benchmark/service_local_runner.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import pandas as pd
3 | from sample import sample_input
4 |
5 | import bentoml
6 | from bentoml.io import JSON
7 | from bentoml.io import PandasDataFrame
8 |
9 | model_ref = bentoml.xgboost.get("ieee-fraud-detection-lg:latest")
10 | preprocessor = model_ref.custom_objects["preprocessor"]
11 | fraud_model_runner = model_ref.to_runner()
12 | fraud_model_runner.init_local()
13 |
14 | svc = bentoml.Service("fraud_detection")
15 |
16 | input_spec = PandasDataFrame.from_sample(sample_input)
17 |
18 |
19 | @svc.api(input=input_spec, output=JSON())
20 | def is_fraud(input_df: pd.DataFrame):
21 | input_df = input_df.astype(sample_input.dtypes)
22 | input_features = preprocessor.transform(input_df)
23 | results = fraud_model_runner.predict_proba.run(input_features)
24 | predictions = np.argmax(results, axis=1) # 0 is not fraud, 1 is fraud
25 | return {"is_fraud": list(map(bool, predictions)), "is_fraud_prob": results[:, 1]}
26 |
27 |
28 | @svc.api(input=input_spec, output=JSON())
29 | async def is_fraud_async(input_df: pd.DataFrame):
30 | input_df = input_df.astype(sample_input.dtypes)
31 | input_features = preprocessor.transform(input_df)
32 | results = await fraud_model_runner.predict_proba.async_run(input_features)
33 | predictions = np.argmax(results, axis=1) # 0 is not fraud, 1 is fraud
34 | return {"is_fraud": list(map(bool, predictions)), "is_fraud_prob": results[:, 1]}
35 |
--------------------------------------------------------------------------------
/inference_graph_demo/service.py:
--------------------------------------------------------------------------------
1 | import asyncio
2 |
3 | import numpy as np
4 | import pandas as pd
5 | from sample import sample_input
6 |
7 | import bentoml
8 | from bentoml.io import JSON
9 | from bentoml.io import PandasDataFrame
10 |
11 | model_ref = bentoml.xgboost.get("ieee-fraud-detection-lg:latest")
12 | preprocessor = model_ref.custom_objects["preprocessor"]
13 |
14 | fraud_model_tiny_runner = bentoml.xgboost.get(
15 | "ieee-fraud-detection-tiny:latest"
16 | ).to_runner()
17 | fraud_model_small_runner = bentoml.xgboost.get(
18 | "ieee-fraud-detection-sm:latest"
19 | ).to_runner()
20 | fraud_model_large_runner = bentoml.xgboost.get(
21 | "ieee-fraud-detection-lg:latest"
22 | ).to_runner()
23 |
24 | svc = bentoml.Service(
25 | "fraud_detection_inference_graph",
26 | runners=[
27 | fraud_model_tiny_runner,
28 | fraud_model_small_runner,
29 | fraud_model_large_runner,
30 | ],
31 | )
32 |
33 | input_spec = PandasDataFrame.from_sample(sample_input)
34 |
35 |
36 | async def _is_fraud_async(
37 | runner: bentoml.Runner,
38 | input_df: pd.DataFrame,
39 | ):
40 | results = await runner.predict_proba.async_run(input_df)
41 | predictions = np.argmax(results, axis=1) # 0 is not fraud, 1 is fraud
42 | return {"is_fraud": list(map(bool, predictions)), "is_fraud_prob": results[:, 1]}
43 |
44 |
45 | @svc.api(input=input_spec, output=JSON())
46 | async def is_fraud(input_df: pd.DataFrame):
47 | input_df = input_df.astype(sample_input.dtypes)
48 | input_df = preprocessor.transform(input_df)
49 | return await asyncio.gather(
50 | _is_fraud_async(fraud_model_tiny_runner, input_df),
51 | _is_fraud_async(fraud_model_small_runner, input_df),
52 | _is_fraud_async(fraud_model_large_runner, input_df),
53 | )
54 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | share/python-wheels/
24 | *.egg-info/
25 | .installed.cfg
26 | *.egg
27 | MANIFEST
28 |
29 | # PyInstaller
30 | # Usually these files are written by a python script from a template
31 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
32 | *.manifest
33 | *.spec
34 |
35 | # Installer logs
36 | pip-log.txt
37 | pip-delete-this-directory.txt
38 |
39 | # Unit test / coverage reports
40 | htmlcov/
41 | .tox/
42 | .nox/
43 | .coverage
44 | .coverage.*
45 | .cache
46 | nosetests.xml
47 | coverage.xml
48 | *.cover
49 | *.py,cover
50 | .hypothesis/
51 | .pytest_cache/
52 | cover/
53 |
54 | # Translations
55 | *.mo
56 | *.pot
57 |
58 | # Django stuff:
59 | *.log
60 | local_settings.py
61 | db.sqlite3
62 | db.sqlite3-journal
63 |
64 | # Flask stuff:
65 | instance/
66 | .webassets-cache
67 |
68 | # Scrapy stuff:
69 | .scrapy
70 |
71 | # Sphinx documentation
72 | docs/_build/
73 |
74 | # PyBuilder
75 | .pybuilder/
76 | target/
77 |
78 | # Jupyter Notebook
79 | .ipynb_checkpoints
80 |
81 | # IPython
82 | profile_default/
83 | ipython_config.py
84 |
85 | # pyenv
86 | # For a library or package, you might want to ignore these files since the code is
87 | # intended to run in multiple environments; otherwise, check them in:
88 | # .python-version
89 |
90 | # pipenv
91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
94 | # install all needed dependencies.
95 | #Pipfile.lock
96 |
97 | # poetry
98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
99 | # This is especially recommended for binary packages to ensure reproducibility, and is more
100 | # commonly ignored for libraries.
101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
102 | #poetry.lock
103 |
104 | # pdm
105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
106 | #pdm.lock
107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
108 | # in version control.
109 | # https://pdm.fming.dev/#use-with-ide
110 | .pdm.toml
111 |
112 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
113 | __pypackages__/
114 |
115 | # Celery stuff
116 | celerybeat-schedule
117 | celerybeat.pid
118 |
119 | # SageMath parsed files
120 | *.sage.py
121 |
122 | # Environments
123 | .env
124 | .venv
125 | env/
126 | venv/
127 | ENV/
128 | env.bak/
129 | venv.bak/
130 |
131 | # Spyder project settings
132 | .spyderproject
133 | .spyproject
134 |
135 | # Rope project settings
136 | .ropeproject
137 |
138 | # mkdocs documentation
139 | /site
140 |
141 | # mypy
142 | .mypy_cache/
143 | .dmypy.json
144 | dmypy.json
145 |
146 | # Pyre type checker
147 | .pyre/
148 |
149 | # pytype static type analyzer
150 | .pytype/
151 |
152 | # Cython debug symbols
153 | cython_debug/
154 |
155 | # PyCharm
156 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
157 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
158 | # and can be added to the global gitignore or merged into this file. For a more nuclear
159 | # option (not recommended) you can uncomment the following to ignore the entire idea folder.
160 | #.idea/
161 |
162 | data/
163 | .DS_Store
164 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
Fraud Detection Models Serving
3 |
4 | Online model serving with Fraud Detection model trained with XGBoost on IEEE-CIS dataset
5 | Powered by BentoML 🍱
6 |
7 |
8 |
9 |
10 | ## 📖 Introduction 📖
11 | This project demonstrates how to serve a fraud detection model trained with [XGBoost]() on the
12 | dataset from the [IEEE-CIS Fraud Detection competition](https://www.kaggle.com/competitions/ieee-fraud-detection/data).
13 |
14 |
15 | ## 🏃♂️ Getting Started 🏃♂️
16 |
17 | ### 0. Clone the Repository:
18 |
19 | ```bash
20 | git clone git@github.com:bentoml/Fraud-Detection-Model-Serving.git
21 | cd Fraud-Detection-Model-Serving
22 | ```
23 |
24 | ### 1. Install Dependencies:
25 | ```bash
26 | pip install -r ./dev-requirements.txt
27 | ```
28 |
29 | ### 2. Download dataset
30 |
31 | Before downloading, set up your Kaggle API Credentials following instructions
32 | [here](https://github.com/Kaggle/kaggle-api#api-credentials) and accept the [dataset
33 | rules on Kaggle](https://www.kaggle.com/competitions/ieee-fraud-detection/data)
34 |
35 | ```bash
36 | ./download_data.sh
37 | ```
38 |
39 | ### 3. Model Training
40 |
41 | Execute the `./IEEE-CIS-Fraud-Detection.ipynb` notebook with the `train.sh` script:
42 | ```bash
43 | ./train.sh
44 | ```
45 |
46 | This will create 3 variations of the model, you can view and manage those models via the
47 | `bentoml models` CLI commnad:
48 |
49 | ```bash
50 | $ bentoml models list
51 |
52 | Tag Module Size Creation Time
53 | ieee-fraud-detection-tiny:qli6n3f6jcta3uqj bentoml.xgboost 141.40 KiB 2023-03-08 23:03:36
54 | ieee-fraud-detection-lg:o7wqb5f6jcta3uqj bentoml.xgboost 18.07 MiB 2023-03-08 23:03:17
55 | ieee-fraud-detection-sm:5yblgmf6i2ta3uqj bentoml.xgboost 723.00 KiB 2023-03-08 22:52:16
56 | ```
57 |
58 | Saved models can also be accessed via the BentoML Python API, e.g.:
59 |
60 | ```python
61 | import bentoml
62 | import pandas as pd
63 | import numpy as np
64 |
65 | model_ref = bentoml.xgboost.get("ieee-fraud-detection-sm:latest")
66 | model_runner = model_ref.to_runner()
67 | model_runner.init_local()
68 | model_preprocessor = model_ref.custom_objects["preprocessor"]
69 |
70 | test_transactions = pd.read_csv("./data/test_transaction.csv")[0:500]
71 | test_transactions = model_preprocessor.transform(test_transactions)
72 | result = model_runner.predict_proba.run(test_transactions)
73 | print(np.argmax(result, axis=1))
74 | ```
75 |
76 |
77 | ### 4. Serving the model
78 |
79 | The `service.py` file contains the source code for defining an ML service:
80 |
81 | ```python
82 | import numpy as np
83 | import pandas as pd
84 | from sample import sample_input
85 |
86 | import bentoml
87 | from bentoml.io import JSON
88 | from bentoml.io import PandasDataFrame
89 |
90 | model_ref = bentoml.xgboost.get("ieee-fraud-detection-lg:latest")
91 | preprocessor = model_ref.custom_objects["preprocessor"]
92 | fraud_model_runner = model_ref.to_runner()
93 |
94 | svc = bentoml.Service("fraud_detection", runners=[fraud_model_runner])
95 |
96 | input_spec = PandasDataFrame.from_sample(sample_input)
97 |
98 | @svc.api(input=input_spec, output=JSON())
99 | async def is_fraud(input_df: pd.DataFrame):
100 | input_df = input_df.astype(sample_input.dtypes)
101 | input_features = preprocessor.transform(input_df)
102 | results = await fraud_model_runner.predict_proba.async_run(input_features)
103 | predictions = np.argmax(results, axis=1) # 0 is not fraud, 1 is fraud
104 | return {"is_fraud": list(map(bool, predictions)), "is_fraud_prob": results[:, 1]}
105 | ```
106 |
107 |
108 | Run `bentoml serve` command to launch the server locally:
109 |
110 | ```bash
111 | bentoml serve
112 | ```
113 |
114 | ## 🌐 Interacting with the Service 🌐
115 | The default mode of BentoML's model serving is via HTTP server. Here, we showcase a few examples of how one can interact with the service:
116 | ### Swagger UI
117 | Visit `http://localhost:3000/` in a browser and send test requests via the UI.
118 |
119 | ### cURL
120 | Via the command `curl`, you can:
121 | ```bash
122 | head --lines=200 ./data/test_transaction.csv | curl -X POST -H 'Content-Type: text/csv' --data-binary @- http://0.0.0.0:3000/is_fraud
123 | ```
124 |
125 | ### Via BentoClient 🐍
126 | ```python
127 | import pandas as pd
128 | from bentoml.client import Client
129 |
130 | test_transactions = pd.read_csv("./data/test_transaction.csv")[0:500]
131 | client = Client.from_url('localhost:3000')
132 |
133 | results = client.is_fraud(test_transaction)
134 | print(results)
135 | ```
136 |
137 |
138 | ## 🚀 Deploying to Production 🚀
139 | Effortlessly transition your project into a production-ready application using [BentoCloud](https://www.bentoml.com/bento-cloud/), the production-ready platform for managing and deploying machine learning models.
140 |
141 | Start by creating a BentoCloud account. Once you've signed up, log in to your BentoCloud account using the command:
142 |
143 | ```bash
144 | bentoml cloud login --api-token --endpoint
145 | ```
146 | > Note: Replace `` and `` with your specific API token and the BentoCloud endpoint respectively.
147 |
148 | Next, build your BentoML service using the `build` command:
149 |
150 | ```bash
151 | bentoml build
152 | ```
153 |
154 | Then, push your freshly-built Bento service to BentoCloud using the `push` command:
155 |
156 | ```bash
157 | bentoml push
158 | ```
159 |
160 | Lastly, deploy this application to BentoCloud with a single `bentoml deployment create` command following the [deployment instructions](https://docs.bentoml.org/en/latest/reference/cli.html#bentoml-deployment-create).
161 |
162 | BentoML offers a number of options for deploying and hosting online ML services into production, learn more at [Deploying a Bento](https://docs.bentoml.org/en/latest/concepts/deploy.html).
163 |
164 | ---
165 |
166 | In this README, we will also go over a basic deployment strategy with Docker containers.
167 |
168 |
169 | ### 1. Build a docker image
170 |
171 | Build a Bento to lock the model version and dependency tree:
172 | ```bash
173 | bentoml build
174 | ```
175 |
176 | Ensure docker is installed and running, build a docker image with `bentoml containerize`
177 | ```bash
178 | bentoml containerize fraud_detection:latest
179 | ```
180 |
181 | Test out the docker image built:
182 |
183 | ```bash
184 | docker run -it --rm -p 3000:3000 fraud_detection:{YOUR BENTO VERSION}
185 | ```
186 |
187 | ### 2. Inference on GPU
188 |
189 | Use `bentofile-gpu.yaml` to build a new Bento, which adds the following two lines to the YAML.
190 | This ensures the docker image comes with GPU libraries installed and BentoML will automatically
191 | load models on GPU when running the docker image with GPU devices available.
192 |
193 | ```yaml
194 | docker:
195 | cuda_version: "11.6.2"
196 | ```
197 |
198 | Build Bento with GPU support:
199 | ```bash
200 | bentoml build -f ./bentofile-gpu.yaml
201 | ```
202 |
203 | Build and run docker image with GPU enabled:
204 | ```bash
205 | bentoml containerize fraud_detection:latest
206 |
207 | docker run --gpus all --device /dev/nvidia0 \
208 | --device /dev/nvidia-uvm --device /dev/nvidia-uvm-tools \
209 | --device /dev/nvidia-modeset --device /dev/nvidiactl \
210 | fraud_detection:{YOUR BENTO VERSION}
211 | ```
212 |
213 | ### 3. Multi-model Inference Pipeline/Graph
214 |
215 | BentoML makes it efficient to create ML service with multiple ML models, which is often used for combining
216 | multiple fraud detection models and getting an aggregated result. With BentoML, users can choose to run
217 | models sequentially or in parallel using the Python AsyncIO APIs along with Runners APIs. This makes
218 | it possible create inference graphes or multi-stage inference pipeline all from Python APIs.
219 |
220 | An example can be found under `inference_graph_demo` that runs all three models simutaneously and
221 | aggregate their results:
222 |
223 | ```bash
224 | cd inference_graph_demo
225 |
226 | bentoml serve
227 | ```
228 |
229 | Learn more about BentoML Runner usage [here](https://docs.bentoml.org/en/latest/concepts/runner.html)
230 |
231 |
232 | ### 4. Benchmark Testing
233 |
234 | Visit the `/benchmark/README.md` for how to run benchmark tests on your fraud detection service and
235 | understanding its throughput and latency on your deployment target.
236 |
237 |
238 | ## 👥Join our Community 👥
239 |
240 | BentoML has a thriving open source community where thousands of ML/AI practitioners are contributing to the project, helping other users and discussing the future of AI. [👉 Join us on slack today!](https://l.bentoml.com/join-slack)
241 |
--------------------------------------------------------------------------------
/sample.py:
--------------------------------------------------------------------------------
1 | import pandas as pd
2 |
3 | sample_json = [
4 | {
5 | "TransactionID": 2987000,
6 | "TransactionDT": 86400,
7 | "TransactionAmt": 68.5,
8 | "ProductCD": "W",
9 | "card1": 13926,
10 | "card2": None,
11 | "card3": 150.0,
12 | "card4": "discover",
13 | "card5": 142.0,
14 | "card6": "credit",
15 | "addr1": 315.0,
16 | "addr2": 87.0,
17 | "dist1": 19.0,
18 | "dist2": None,
19 | "P_emaildomain": None,
20 | "R_emaildomain": None,
21 | "C1": 1.0,
22 | "C2": 1.0,
23 | "C3": 0.0,
24 | "C4": 0.0,
25 | "C5": 0.0,
26 | "C6": 1.0,
27 | "C7": 0.0,
28 | "C8": 0.0,
29 | "C9": 1.0,
30 | "C10": 0.0,
31 | "C11": 2.0,
32 | "C12": 0.0,
33 | "C13": 1.0,
34 | "C14": 1.0,
35 | "D1": 14.0,
36 | "D2": None,
37 | "D3": 13.0,
38 | "D4": None,
39 | "D5": None,
40 | "D6": None,
41 | "D7": None,
42 | "D8": None,
43 | "D9": None,
44 | "D10": 13.0,
45 | "D11": 13.0,
46 | "D12": None,
47 | "D13": None,
48 | "D14": None,
49 | "D15": 0.0,
50 | "M1": "T",
51 | "M2": "T",
52 | "M3": "T",
53 | "M4": "M2",
54 | "M5": "F",
55 | "M6": "T",
56 | "M7": None,
57 | "M8": None,
58 | "M9": None,
59 | "V1": 1.0,
60 | "V2": 1.0,
61 | "V3": 1.0,
62 | "V4": 1.0,
63 | "V5": 1.0,
64 | "V6": 1.0,
65 | "V7": 1.0,
66 | "V8": 1.0,
67 | "V9": 1.0,
68 | "V10": 0.0,
69 | "V11": 0.0,
70 | "V12": 1.0,
71 | "V13": 1.0,
72 | "V14": 1.0,
73 | "V15": 0.0,
74 | "V16": 0.0,
75 | "V17": 0.0,
76 | "V18": 0.0,
77 | "V19": 1.0,
78 | "V20": 1.0,
79 | "V21": 0.0,
80 | "V22": 0.0,
81 | "V23": 1.0,
82 | "V24": 1.0,
83 | "V25": 1.0,
84 | "V26": 1.0,
85 | "V27": 0.0,
86 | "V28": 0.0,
87 | "V29": 0.0,
88 | "V30": 0.0,
89 | "V31": 0.0,
90 | "V32": 0.0,
91 | "V33": 0.0,
92 | "V34": 0.0,
93 | "V35": None,
94 | "V36": None,
95 | "V37": None,
96 | "V38": None,
97 | "V39": None,
98 | "V40": None,
99 | "V41": None,
100 | "V42": None,
101 | "V43": None,
102 | "V44": None,
103 | "V45": None,
104 | "V46": None,
105 | "V47": None,
106 | "V48": None,
107 | "V49": None,
108 | "V50": None,
109 | "V51": None,
110 | "V52": None,
111 | "V53": 1.0,
112 | "V54": 1.0,
113 | "V55": 1.0,
114 | "V56": 1.0,
115 | "V57": 0.0,
116 | "V58": 0.0,
117 | "V59": 0.0,
118 | "V60": 0.0,
119 | "V61": 1.0,
120 | "V62": 1.0,
121 | "V63": 0.0,
122 | "V64": 0.0,
123 | "V65": 1.0,
124 | "V66": 1.0,
125 | "V67": 1.0,
126 | "V68": 0.0,
127 | "V69": 0.0,
128 | "V70": 0.0,
129 | "V71": 0.0,
130 | "V72": 0.0,
131 | "V73": 0.0,
132 | "V74": 0.0,
133 | "V75": 1.0,
134 | "V76": 1.0,
135 | "V77": 1.0,
136 | "V78": 1.0,
137 | "V79": 0.0,
138 | "V80": 0.0,
139 | "V81": 0.0,
140 | "V82": 0.0,
141 | "V83": 0.0,
142 | "V84": 0.0,
143 | "V85": 0.0,
144 | "V86": 1.0,
145 | "V87": 1.0,
146 | "V88": 1.0,
147 | "V89": 0.0,
148 | "V90": 0.0,
149 | "V91": 0.0,
150 | "V92": 0.0,
151 | "V93": 0.0,
152 | "V94": 0.0,
153 | "V95": 0.0,
154 | "V96": 1.0,
155 | "V97": 0.0,
156 | "V98": 0.0,
157 | "V99": 0.0,
158 | "V100": 0.0,
159 | "V101": 0.0,
160 | "V102": 1.0,
161 | "V103": 0.0,
162 | "V104": 0.0,
163 | "V105": 0.0,
164 | "V106": 0.0,
165 | "V107": 1.0,
166 | "V108": 1.0,
167 | "V109": 1.0,
168 | "V110": 1.0,
169 | "V111": 1.0,
170 | "V112": 1.0,
171 | "V113": 1.0,
172 | "V114": 1.0,
173 | "V115": 1.0,
174 | "V116": 1.0,
175 | "V117": 1.0,
176 | "V118": 1.0,
177 | "V119": 1.0,
178 | "V120": 1.0,
179 | "V121": 1.0,
180 | "V122": 1.0,
181 | "V123": 1.0,
182 | "V124": 1.0,
183 | "V125": 1.0,
184 | "V126": 0.0,
185 | "V127": 117.0,
186 | "V128": 0.0,
187 | "V129": 0.0,
188 | "V130": 0.0,
189 | "V131": 0.0,
190 | "V132": 0.0,
191 | "V133": 117.0,
192 | "V134": 0.0,
193 | "V135": 0.0,
194 | "V136": 0.0,
195 | "V137": 0.0,
196 | "V138": None,
197 | "V139": None,
198 | "V140": None,
199 | "V141": None,
200 | "V142": None,
201 | "V143": None,
202 | "V144": None,
203 | "V145": None,
204 | "V146": None,
205 | "V147": None,
206 | "V148": None,
207 | "V149": None,
208 | "V150": None,
209 | "V151": None,
210 | "V152": None,
211 | "V153": None,
212 | "V154": None,
213 | "V155": None,
214 | "V156": None,
215 | "V157": None,
216 | "V158": None,
217 | "V159": None,
218 | "V160": None,
219 | "V161": None,
220 | "V162": None,
221 | "V163": None,
222 | "V164": None,
223 | "V165": None,
224 | "V166": None,
225 | "V167": None,
226 | "V168": None,
227 | "V169": None,
228 | "V170": None,
229 | "V171": None,
230 | "V172": None,
231 | "V173": None,
232 | "V174": None,
233 | "V175": None,
234 | "V176": None,
235 | "V177": None,
236 | "V178": None,
237 | "V179": None,
238 | "V180": None,
239 | "V181": None,
240 | "V182": None,
241 | "V183": None,
242 | "V184": None,
243 | "V185": None,
244 | "V186": None,
245 | "V187": None,
246 | "V188": None,
247 | "V189": None,
248 | "V190": None,
249 | "V191": None,
250 | "V192": None,
251 | "V193": None,
252 | "V194": None,
253 | "V195": None,
254 | "V196": None,
255 | "V197": None,
256 | "V198": None,
257 | "V199": None,
258 | "V200": None,
259 | "V201": None,
260 | "V202": None,
261 | "V203": None,
262 | "V204": None,
263 | "V205": None,
264 | "V206": None,
265 | "V207": None,
266 | "V208": None,
267 | "V209": None,
268 | "V210": None,
269 | "V211": None,
270 | "V212": None,
271 | "V213": None,
272 | "V214": None,
273 | "V215": None,
274 | "V216": None,
275 | "V217": None,
276 | "V218": None,
277 | "V219": None,
278 | "V220": None,
279 | "V221": None,
280 | "V222": None,
281 | "V223": None,
282 | "V224": None,
283 | "V225": None,
284 | "V226": None,
285 | "V227": None,
286 | "V228": None,
287 | "V229": None,
288 | "V230": None,
289 | "V231": None,
290 | "V232": None,
291 | "V233": None,
292 | "V234": None,
293 | "V235": None,
294 | "V236": None,
295 | "V237": None,
296 | "V238": None,
297 | "V239": None,
298 | "V240": None,
299 | "V241": None,
300 | "V242": None,
301 | "V243": None,
302 | "V244": None,
303 | "V245": None,
304 | "V246": None,
305 | "V247": None,
306 | "V248": None,
307 | "V249": None,
308 | "V250": None,
309 | "V251": None,
310 | "V252": None,
311 | "V253": None,
312 | "V254": None,
313 | "V255": None,
314 | "V256": None,
315 | "V257": None,
316 | "V258": None,
317 | "V259": None,
318 | "V260": None,
319 | "V261": None,
320 | "V262": None,
321 | "V263": None,
322 | "V264": None,
323 | "V265": None,
324 | "V266": None,
325 | "V267": None,
326 | "V268": None,
327 | "V269": None,
328 | "V270": None,
329 | "V271": None,
330 | "V272": None,
331 | "V273": None,
332 | "V274": None,
333 | "V275": None,
334 | "V276": None,
335 | "V277": None,
336 | "V278": None,
337 | "V279": 0.0,
338 | "V280": 0.0,
339 | "V281": 0.0,
340 | "V282": 1.0,
341 | "V283": 1.0,
342 | "V284": 0.0,
343 | "V285": 0.0,
344 | "V286": 0.0,
345 | "V287": 0.0,
346 | "V288": 0.0,
347 | "V289": 0.0,
348 | "V290": 1.0,
349 | "V291": 1.0,
350 | "V292": 1.0,
351 | "V293": 0.0,
352 | "V294": 1.0,
353 | "V295": 0.0,
354 | "V296": 0.0,
355 | "V297": 0.0,
356 | "V298": 0.0,
357 | "V299": 0.0,
358 | "V300": 0.0,
359 | "V301": 0.0,
360 | "V302": 0.0,
361 | "V303": 0.0,
362 | "V304": 0.0,
363 | "V305": 1.0,
364 | "V306": 0.0,
365 | "V307": 117.0,
366 | "V308": 0.0,
367 | "V309": 0.0,
368 | "V310": 0.0,
369 | "V311": 0.0,
370 | "V312": 0.0,
371 | "V313": 0.0,
372 | "V314": 0.0,
373 | "V315": 0.0,
374 | "V316": 0.0,
375 | "V317": 117.0,
376 | "V318": 0.0,
377 | "V319": 0.0,
378 | "V320": 0.0,
379 | "V321": 0.0,
380 | "V322": None,
381 | "V323": None,
382 | "V324": None,
383 | "V325": None,
384 | "V326": None,
385 | "V327": None,
386 | "V328": None,
387 | "V329": None,
388 | "V330": None,
389 | "V331": None,
390 | "V332": None,
391 | "V333": None,
392 | "V334": None,
393 | "V335": None,
394 | "V336": None,
395 | "V337": None,
396 | "V338": None,
397 | "V339": None,
398 | }
399 | ]
400 |
401 | sample_input = pd.DataFrame(sample_json)
402 |
--------------------------------------------------------------------------------
/benchmark/sample.py:
--------------------------------------------------------------------------------
1 | import pandas as pd
2 |
3 | sample_json = [
4 | {
5 | "TransactionID": 2987000,
6 | "TransactionDT": 86400,
7 | "TransactionAmt": 68.5,
8 | "ProductCD": "W",
9 | "card1": 13926,
10 | "card2": None,
11 | "card3": 150.0,
12 | "card4": "discover",
13 | "card5": 142.0,
14 | "card6": "credit",
15 | "addr1": 315.0,
16 | "addr2": 87.0,
17 | "dist1": 19.0,
18 | "dist2": None,
19 | "P_emaildomain": None,
20 | "R_emaildomain": None,
21 | "C1": 1.0,
22 | "C2": 1.0,
23 | "C3": 0.0,
24 | "C4": 0.0,
25 | "C5": 0.0,
26 | "C6": 1.0,
27 | "C7": 0.0,
28 | "C8": 0.0,
29 | "C9": 1.0,
30 | "C10": 0.0,
31 | "C11": 2.0,
32 | "C12": 0.0,
33 | "C13": 1.0,
34 | "C14": 1.0,
35 | "D1": 14.0,
36 | "D2": None,
37 | "D3": 13.0,
38 | "D4": None,
39 | "D5": None,
40 | "D6": None,
41 | "D7": None,
42 | "D8": None,
43 | "D9": None,
44 | "D10": 13.0,
45 | "D11": 13.0,
46 | "D12": None,
47 | "D13": None,
48 | "D14": None,
49 | "D15": 0.0,
50 | "M1": "T",
51 | "M2": "T",
52 | "M3": "T",
53 | "M4": "M2",
54 | "M5": "F",
55 | "M6": "T",
56 | "M7": None,
57 | "M8": None,
58 | "M9": None,
59 | "V1": 1.0,
60 | "V2": 1.0,
61 | "V3": 1.0,
62 | "V4": 1.0,
63 | "V5": 1.0,
64 | "V6": 1.0,
65 | "V7": 1.0,
66 | "V8": 1.0,
67 | "V9": 1.0,
68 | "V10": 0.0,
69 | "V11": 0.0,
70 | "V12": 1.0,
71 | "V13": 1.0,
72 | "V14": 1.0,
73 | "V15": 0.0,
74 | "V16": 0.0,
75 | "V17": 0.0,
76 | "V18": 0.0,
77 | "V19": 1.0,
78 | "V20": 1.0,
79 | "V21": 0.0,
80 | "V22": 0.0,
81 | "V23": 1.0,
82 | "V24": 1.0,
83 | "V25": 1.0,
84 | "V26": 1.0,
85 | "V27": 0.0,
86 | "V28": 0.0,
87 | "V29": 0.0,
88 | "V30": 0.0,
89 | "V31": 0.0,
90 | "V32": 0.0,
91 | "V33": 0.0,
92 | "V34": 0.0,
93 | "V35": None,
94 | "V36": None,
95 | "V37": None,
96 | "V38": None,
97 | "V39": None,
98 | "V40": None,
99 | "V41": None,
100 | "V42": None,
101 | "V43": None,
102 | "V44": None,
103 | "V45": None,
104 | "V46": None,
105 | "V47": None,
106 | "V48": None,
107 | "V49": None,
108 | "V50": None,
109 | "V51": None,
110 | "V52": None,
111 | "V53": 1.0,
112 | "V54": 1.0,
113 | "V55": 1.0,
114 | "V56": 1.0,
115 | "V57": 0.0,
116 | "V58": 0.0,
117 | "V59": 0.0,
118 | "V60": 0.0,
119 | "V61": 1.0,
120 | "V62": 1.0,
121 | "V63": 0.0,
122 | "V64": 0.0,
123 | "V65": 1.0,
124 | "V66": 1.0,
125 | "V67": 1.0,
126 | "V68": 0.0,
127 | "V69": 0.0,
128 | "V70": 0.0,
129 | "V71": 0.0,
130 | "V72": 0.0,
131 | "V73": 0.0,
132 | "V74": 0.0,
133 | "V75": 1.0,
134 | "V76": 1.0,
135 | "V77": 1.0,
136 | "V78": 1.0,
137 | "V79": 0.0,
138 | "V80": 0.0,
139 | "V81": 0.0,
140 | "V82": 0.0,
141 | "V83": 0.0,
142 | "V84": 0.0,
143 | "V85": 0.0,
144 | "V86": 1.0,
145 | "V87": 1.0,
146 | "V88": 1.0,
147 | "V89": 0.0,
148 | "V90": 0.0,
149 | "V91": 0.0,
150 | "V92": 0.0,
151 | "V93": 0.0,
152 | "V94": 0.0,
153 | "V95": 0.0,
154 | "V96": 1.0,
155 | "V97": 0.0,
156 | "V98": 0.0,
157 | "V99": 0.0,
158 | "V100": 0.0,
159 | "V101": 0.0,
160 | "V102": 1.0,
161 | "V103": 0.0,
162 | "V104": 0.0,
163 | "V105": 0.0,
164 | "V106": 0.0,
165 | "V107": 1.0,
166 | "V108": 1.0,
167 | "V109": 1.0,
168 | "V110": 1.0,
169 | "V111": 1.0,
170 | "V112": 1.0,
171 | "V113": 1.0,
172 | "V114": 1.0,
173 | "V115": 1.0,
174 | "V116": 1.0,
175 | "V117": 1.0,
176 | "V118": 1.0,
177 | "V119": 1.0,
178 | "V120": 1.0,
179 | "V121": 1.0,
180 | "V122": 1.0,
181 | "V123": 1.0,
182 | "V124": 1.0,
183 | "V125": 1.0,
184 | "V126": 0.0,
185 | "V127": 117.0,
186 | "V128": 0.0,
187 | "V129": 0.0,
188 | "V130": 0.0,
189 | "V131": 0.0,
190 | "V132": 0.0,
191 | "V133": 117.0,
192 | "V134": 0.0,
193 | "V135": 0.0,
194 | "V136": 0.0,
195 | "V137": 0.0,
196 | "V138": None,
197 | "V139": None,
198 | "V140": None,
199 | "V141": None,
200 | "V142": None,
201 | "V143": None,
202 | "V144": None,
203 | "V145": None,
204 | "V146": None,
205 | "V147": None,
206 | "V148": None,
207 | "V149": None,
208 | "V150": None,
209 | "V151": None,
210 | "V152": None,
211 | "V153": None,
212 | "V154": None,
213 | "V155": None,
214 | "V156": None,
215 | "V157": None,
216 | "V158": None,
217 | "V159": None,
218 | "V160": None,
219 | "V161": None,
220 | "V162": None,
221 | "V163": None,
222 | "V164": None,
223 | "V165": None,
224 | "V166": None,
225 | "V167": None,
226 | "V168": None,
227 | "V169": None,
228 | "V170": None,
229 | "V171": None,
230 | "V172": None,
231 | "V173": None,
232 | "V174": None,
233 | "V175": None,
234 | "V176": None,
235 | "V177": None,
236 | "V178": None,
237 | "V179": None,
238 | "V180": None,
239 | "V181": None,
240 | "V182": None,
241 | "V183": None,
242 | "V184": None,
243 | "V185": None,
244 | "V186": None,
245 | "V187": None,
246 | "V188": None,
247 | "V189": None,
248 | "V190": None,
249 | "V191": None,
250 | "V192": None,
251 | "V193": None,
252 | "V194": None,
253 | "V195": None,
254 | "V196": None,
255 | "V197": None,
256 | "V198": None,
257 | "V199": None,
258 | "V200": None,
259 | "V201": None,
260 | "V202": None,
261 | "V203": None,
262 | "V204": None,
263 | "V205": None,
264 | "V206": None,
265 | "V207": None,
266 | "V208": None,
267 | "V209": None,
268 | "V210": None,
269 | "V211": None,
270 | "V212": None,
271 | "V213": None,
272 | "V214": None,
273 | "V215": None,
274 | "V216": None,
275 | "V217": None,
276 | "V218": None,
277 | "V219": None,
278 | "V220": None,
279 | "V221": None,
280 | "V222": None,
281 | "V223": None,
282 | "V224": None,
283 | "V225": None,
284 | "V226": None,
285 | "V227": None,
286 | "V228": None,
287 | "V229": None,
288 | "V230": None,
289 | "V231": None,
290 | "V232": None,
291 | "V233": None,
292 | "V234": None,
293 | "V235": None,
294 | "V236": None,
295 | "V237": None,
296 | "V238": None,
297 | "V239": None,
298 | "V240": None,
299 | "V241": None,
300 | "V242": None,
301 | "V243": None,
302 | "V244": None,
303 | "V245": None,
304 | "V246": None,
305 | "V247": None,
306 | "V248": None,
307 | "V249": None,
308 | "V250": None,
309 | "V251": None,
310 | "V252": None,
311 | "V253": None,
312 | "V254": None,
313 | "V255": None,
314 | "V256": None,
315 | "V257": None,
316 | "V258": None,
317 | "V259": None,
318 | "V260": None,
319 | "V261": None,
320 | "V262": None,
321 | "V263": None,
322 | "V264": None,
323 | "V265": None,
324 | "V266": None,
325 | "V267": None,
326 | "V268": None,
327 | "V269": None,
328 | "V270": None,
329 | "V271": None,
330 | "V272": None,
331 | "V273": None,
332 | "V274": None,
333 | "V275": None,
334 | "V276": None,
335 | "V277": None,
336 | "V278": None,
337 | "V279": 0.0,
338 | "V280": 0.0,
339 | "V281": 0.0,
340 | "V282": 1.0,
341 | "V283": 1.0,
342 | "V284": 0.0,
343 | "V285": 0.0,
344 | "V286": 0.0,
345 | "V287": 0.0,
346 | "V288": 0.0,
347 | "V289": 0.0,
348 | "V290": 1.0,
349 | "V291": 1.0,
350 | "V292": 1.0,
351 | "V293": 0.0,
352 | "V294": 1.0,
353 | "V295": 0.0,
354 | "V296": 0.0,
355 | "V297": 0.0,
356 | "V298": 0.0,
357 | "V299": 0.0,
358 | "V300": 0.0,
359 | "V301": 0.0,
360 | "V302": 0.0,
361 | "V303": 0.0,
362 | "V304": 0.0,
363 | "V305": 1.0,
364 | "V306": 0.0,
365 | "V307": 117.0,
366 | "V308": 0.0,
367 | "V309": 0.0,
368 | "V310": 0.0,
369 | "V311": 0.0,
370 | "V312": 0.0,
371 | "V313": 0.0,
372 | "V314": 0.0,
373 | "V315": 0.0,
374 | "V316": 0.0,
375 | "V317": 117.0,
376 | "V318": 0.0,
377 | "V319": 0.0,
378 | "V320": 0.0,
379 | "V321": 0.0,
380 | "V322": None,
381 | "V323": None,
382 | "V324": None,
383 | "V325": None,
384 | "V326": None,
385 | "V327": None,
386 | "V328": None,
387 | "V329": None,
388 | "V330": None,
389 | "V331": None,
390 | "V332": None,
391 | "V333": None,
392 | "V334": None,
393 | "V335": None,
394 | "V336": None,
395 | "V337": None,
396 | "V338": None,
397 | "V339": None,
398 | }
399 | ]
400 |
401 | sample_input = pd.DataFrame(sample_json)
402 |
--------------------------------------------------------------------------------
/inference_graph_demo/sample.py:
--------------------------------------------------------------------------------
1 | import pandas as pd
2 |
3 | sample_json = [
4 | {
5 | "TransactionID": 2987000,
6 | "TransactionDT": 86400,
7 | "TransactionAmt": 68.5,
8 | "ProductCD": "W",
9 | "card1": 13926,
10 | "card2": None,
11 | "card3": 150.0,
12 | "card4": "discover",
13 | "card5": 142.0,
14 | "card6": "credit",
15 | "addr1": 315.0,
16 | "addr2": 87.0,
17 | "dist1": 19.0,
18 | "dist2": None,
19 | "P_emaildomain": None,
20 | "R_emaildomain": None,
21 | "C1": 1.0,
22 | "C2": 1.0,
23 | "C3": 0.0,
24 | "C4": 0.0,
25 | "C5": 0.0,
26 | "C6": 1.0,
27 | "C7": 0.0,
28 | "C8": 0.0,
29 | "C9": 1.0,
30 | "C10": 0.0,
31 | "C11": 2.0,
32 | "C12": 0.0,
33 | "C13": 1.0,
34 | "C14": 1.0,
35 | "D1": 14.0,
36 | "D2": None,
37 | "D3": 13.0,
38 | "D4": None,
39 | "D5": None,
40 | "D6": None,
41 | "D7": None,
42 | "D8": None,
43 | "D9": None,
44 | "D10": 13.0,
45 | "D11": 13.0,
46 | "D12": None,
47 | "D13": None,
48 | "D14": None,
49 | "D15": 0.0,
50 | "M1": "T",
51 | "M2": "T",
52 | "M3": "T",
53 | "M4": "M2",
54 | "M5": "F",
55 | "M6": "T",
56 | "M7": None,
57 | "M8": None,
58 | "M9": None,
59 | "V1": 1.0,
60 | "V2": 1.0,
61 | "V3": 1.0,
62 | "V4": 1.0,
63 | "V5": 1.0,
64 | "V6": 1.0,
65 | "V7": 1.0,
66 | "V8": 1.0,
67 | "V9": 1.0,
68 | "V10": 0.0,
69 | "V11": 0.0,
70 | "V12": 1.0,
71 | "V13": 1.0,
72 | "V14": 1.0,
73 | "V15": 0.0,
74 | "V16": 0.0,
75 | "V17": 0.0,
76 | "V18": 0.0,
77 | "V19": 1.0,
78 | "V20": 1.0,
79 | "V21": 0.0,
80 | "V22": 0.0,
81 | "V23": 1.0,
82 | "V24": 1.0,
83 | "V25": 1.0,
84 | "V26": 1.0,
85 | "V27": 0.0,
86 | "V28": 0.0,
87 | "V29": 0.0,
88 | "V30": 0.0,
89 | "V31": 0.0,
90 | "V32": 0.0,
91 | "V33": 0.0,
92 | "V34": 0.0,
93 | "V35": None,
94 | "V36": None,
95 | "V37": None,
96 | "V38": None,
97 | "V39": None,
98 | "V40": None,
99 | "V41": None,
100 | "V42": None,
101 | "V43": None,
102 | "V44": None,
103 | "V45": None,
104 | "V46": None,
105 | "V47": None,
106 | "V48": None,
107 | "V49": None,
108 | "V50": None,
109 | "V51": None,
110 | "V52": None,
111 | "V53": 1.0,
112 | "V54": 1.0,
113 | "V55": 1.0,
114 | "V56": 1.0,
115 | "V57": 0.0,
116 | "V58": 0.0,
117 | "V59": 0.0,
118 | "V60": 0.0,
119 | "V61": 1.0,
120 | "V62": 1.0,
121 | "V63": 0.0,
122 | "V64": 0.0,
123 | "V65": 1.0,
124 | "V66": 1.0,
125 | "V67": 1.0,
126 | "V68": 0.0,
127 | "V69": 0.0,
128 | "V70": 0.0,
129 | "V71": 0.0,
130 | "V72": 0.0,
131 | "V73": 0.0,
132 | "V74": 0.0,
133 | "V75": 1.0,
134 | "V76": 1.0,
135 | "V77": 1.0,
136 | "V78": 1.0,
137 | "V79": 0.0,
138 | "V80": 0.0,
139 | "V81": 0.0,
140 | "V82": 0.0,
141 | "V83": 0.0,
142 | "V84": 0.0,
143 | "V85": 0.0,
144 | "V86": 1.0,
145 | "V87": 1.0,
146 | "V88": 1.0,
147 | "V89": 0.0,
148 | "V90": 0.0,
149 | "V91": 0.0,
150 | "V92": 0.0,
151 | "V93": 0.0,
152 | "V94": 0.0,
153 | "V95": 0.0,
154 | "V96": 1.0,
155 | "V97": 0.0,
156 | "V98": 0.0,
157 | "V99": 0.0,
158 | "V100": 0.0,
159 | "V101": 0.0,
160 | "V102": 1.0,
161 | "V103": 0.0,
162 | "V104": 0.0,
163 | "V105": 0.0,
164 | "V106": 0.0,
165 | "V107": 1.0,
166 | "V108": 1.0,
167 | "V109": 1.0,
168 | "V110": 1.0,
169 | "V111": 1.0,
170 | "V112": 1.0,
171 | "V113": 1.0,
172 | "V114": 1.0,
173 | "V115": 1.0,
174 | "V116": 1.0,
175 | "V117": 1.0,
176 | "V118": 1.0,
177 | "V119": 1.0,
178 | "V120": 1.0,
179 | "V121": 1.0,
180 | "V122": 1.0,
181 | "V123": 1.0,
182 | "V124": 1.0,
183 | "V125": 1.0,
184 | "V126": 0.0,
185 | "V127": 117.0,
186 | "V128": 0.0,
187 | "V129": 0.0,
188 | "V130": 0.0,
189 | "V131": 0.0,
190 | "V132": 0.0,
191 | "V133": 117.0,
192 | "V134": 0.0,
193 | "V135": 0.0,
194 | "V136": 0.0,
195 | "V137": 0.0,
196 | "V138": None,
197 | "V139": None,
198 | "V140": None,
199 | "V141": None,
200 | "V142": None,
201 | "V143": None,
202 | "V144": None,
203 | "V145": None,
204 | "V146": None,
205 | "V147": None,
206 | "V148": None,
207 | "V149": None,
208 | "V150": None,
209 | "V151": None,
210 | "V152": None,
211 | "V153": None,
212 | "V154": None,
213 | "V155": None,
214 | "V156": None,
215 | "V157": None,
216 | "V158": None,
217 | "V159": None,
218 | "V160": None,
219 | "V161": None,
220 | "V162": None,
221 | "V163": None,
222 | "V164": None,
223 | "V165": None,
224 | "V166": None,
225 | "V167": None,
226 | "V168": None,
227 | "V169": None,
228 | "V170": None,
229 | "V171": None,
230 | "V172": None,
231 | "V173": None,
232 | "V174": None,
233 | "V175": None,
234 | "V176": None,
235 | "V177": None,
236 | "V178": None,
237 | "V179": None,
238 | "V180": None,
239 | "V181": None,
240 | "V182": None,
241 | "V183": None,
242 | "V184": None,
243 | "V185": None,
244 | "V186": None,
245 | "V187": None,
246 | "V188": None,
247 | "V189": None,
248 | "V190": None,
249 | "V191": None,
250 | "V192": None,
251 | "V193": None,
252 | "V194": None,
253 | "V195": None,
254 | "V196": None,
255 | "V197": None,
256 | "V198": None,
257 | "V199": None,
258 | "V200": None,
259 | "V201": None,
260 | "V202": None,
261 | "V203": None,
262 | "V204": None,
263 | "V205": None,
264 | "V206": None,
265 | "V207": None,
266 | "V208": None,
267 | "V209": None,
268 | "V210": None,
269 | "V211": None,
270 | "V212": None,
271 | "V213": None,
272 | "V214": None,
273 | "V215": None,
274 | "V216": None,
275 | "V217": None,
276 | "V218": None,
277 | "V219": None,
278 | "V220": None,
279 | "V221": None,
280 | "V222": None,
281 | "V223": None,
282 | "V224": None,
283 | "V225": None,
284 | "V226": None,
285 | "V227": None,
286 | "V228": None,
287 | "V229": None,
288 | "V230": None,
289 | "V231": None,
290 | "V232": None,
291 | "V233": None,
292 | "V234": None,
293 | "V235": None,
294 | "V236": None,
295 | "V237": None,
296 | "V238": None,
297 | "V239": None,
298 | "V240": None,
299 | "V241": None,
300 | "V242": None,
301 | "V243": None,
302 | "V244": None,
303 | "V245": None,
304 | "V246": None,
305 | "V247": None,
306 | "V248": None,
307 | "V249": None,
308 | "V250": None,
309 | "V251": None,
310 | "V252": None,
311 | "V253": None,
312 | "V254": None,
313 | "V255": None,
314 | "V256": None,
315 | "V257": None,
316 | "V258": None,
317 | "V259": None,
318 | "V260": None,
319 | "V261": None,
320 | "V262": None,
321 | "V263": None,
322 | "V264": None,
323 | "V265": None,
324 | "V266": None,
325 | "V267": None,
326 | "V268": None,
327 | "V269": None,
328 | "V270": None,
329 | "V271": None,
330 | "V272": None,
331 | "V273": None,
332 | "V274": None,
333 | "V275": None,
334 | "V276": None,
335 | "V277": None,
336 | "V278": None,
337 | "V279": 0.0,
338 | "V280": 0.0,
339 | "V281": 0.0,
340 | "V282": 1.0,
341 | "V283": 1.0,
342 | "V284": 0.0,
343 | "V285": 0.0,
344 | "V286": 0.0,
345 | "V287": 0.0,
346 | "V288": 0.0,
347 | "V289": 0.0,
348 | "V290": 1.0,
349 | "V291": 1.0,
350 | "V292": 1.0,
351 | "V293": 0.0,
352 | "V294": 1.0,
353 | "V295": 0.0,
354 | "V296": 0.0,
355 | "V297": 0.0,
356 | "V298": 0.0,
357 | "V299": 0.0,
358 | "V300": 0.0,
359 | "V301": 0.0,
360 | "V302": 0.0,
361 | "V303": 0.0,
362 | "V304": 0.0,
363 | "V305": 1.0,
364 | "V306": 0.0,
365 | "V307": 117.0,
366 | "V308": 0.0,
367 | "V309": 0.0,
368 | "V310": 0.0,
369 | "V311": 0.0,
370 | "V312": 0.0,
371 | "V313": 0.0,
372 | "V314": 0.0,
373 | "V315": 0.0,
374 | "V316": 0.0,
375 | "V317": 117.0,
376 | "V318": 0.0,
377 | "V319": 0.0,
378 | "V320": 0.0,
379 | "V321": 0.0,
380 | "V322": None,
381 | "V323": None,
382 | "V324": None,
383 | "V325": None,
384 | "V326": None,
385 | "V327": None,
386 | "V328": None,
387 | "V329": None,
388 | "V330": None,
389 | "V331": None,
390 | "V332": None,
391 | "V333": None,
392 | "V334": None,
393 | "V335": None,
394 | "V336": None,
395 | "V337": None,
396 | "V338": None,
397 | "V339": None,
398 | }
399 | ]
400 |
401 | sample_input = pd.DataFrame(sample_json)
402 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------