This notebook shows the 66.66% reduction in latency on the credit card fraud dataset from https://www.kaggle.com/datasets/mlg-ulb/creditcardfraud. The method is early-exiting and building a cascaded system of models and this notebook demonstrates that reductions in compute-time are possible while preserving accuracy.
import pandas as pd
from sklearn.neural_network import MLPClassifier
from utils import optimize, HyperplaneDecisionRealTime, Router
from sklearn.model_selection import train_test_split
import time
import os
import numpy as np
from tqdm import tqdm
import warnings
# Suppress only RuntimeWarning
warnings.filterwarnings("ignore", category=RuntimeWarning)
def load_dataset():
df = pd.read_csv('/Users/samrandall/Downloads/creditcard.csv')
X = df[[col for col in df.columns if col.startswith('V')]].to_numpy()
y = df['Class'].to_numpy()
return X, y
Load the dataset and train a simple MLPClassifier. This will take 10 seconds.
X, y = load_dataset()
X_train, X_test, y_train, y_test = train_test_split(X, y)
model = MLPClassifier()
model.fit(X_train, y_train)
MLPClassifier()In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
MLPClassifier()
json_save_path = "creditcard_hyperplane.json"
if False:
hd = HyperplaneDecisionRealTime.load(json_save_path)
router = Router(hd, lambda x: 0, lambda x: model.predict(x).item())
else:
router = optimize(model, X_train)
router.decision.save(json_save_path)
Response <Response [200]> response status code 200
for i in range(len(X)):
model.predict(X[i:i+1])
start = time.time()
for i in tqdm(range(len(X))):
router.forward(X[i:i+1])
end = time.time()
early_exit_time = end - start
for i in range(len(X)):
model.predict(X[i:i+1])
start = time.time()
for i in tqdm(range(len(X))):
model.predict(X[i:i+1])
end = time.time()
original_time = end - start
print("Original Time", original_time) # 13.354 seconds
print("Early Exit Time", early_exit_time) # 10.707 seconds
100%|██████████| 284807/284807 [00:04<00:00, 60876.30it/s] 100%|██████████| 284807/284807 [00:14<00:00, 20286.29it/s]
Original Time 14.041443109512329 Early Exit Time 4.680275917053223
Counting how many data points avoided full model execution (were exited early)
decisions = []
for item in X:
decisions.append(router.decision.forward(item[np.newaxis, :]))
decisions = np.array(decisions)
decisions.mean()
np.float64(0.7104846439869806)
Latency¶
The results in this run are that the original model took 14.04 seconds to run through the entire dataset of 284807 seconds. Compare this to Early Exit Latency of 4.68 seconds. This is a 66.7% reduction in CPU-time. Results vary based on the run of the algorithm. This is because 71% of the data points avoided model execution.
Accuracy¶
This section shows below that the predictions in the routed model are 100% across the test set.
p = []
for item in X_test:
p.append(router.forward(item[np.newaxis, :]))
early_exit_predictions = np.array(p)
original_predictions = model.predict(X_test)
np.mean(early_exit_predictions == original_predictions)
np.float64(1.0)