mirror of
https://github.com/luxfhe/workshop.git
synced 2026-10-30 17:06:44 +00:00
929 KiB
929 KiB
In [1]:
import time
import numpy as np
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression as SklearnLogisticRegression
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler, StandardScaler
from torus.ml.sklearn import LogisticRegression as TorusLogisticRegressionIn [2]:
%matplotlib inline
import matplotlib.pyplot as plt
from IPython.display import displayIn [3]:
X, y = make_classification(
n_samples=200,
n_features=2,
n_redundant=0,
n_informative=2,
random_state=2,
n_clusters_per_class=1,
)
rng = np.random.RandomState(2)
X += 2 * rng.uniform(size=X.shape)
b_min = np.min(X, axis=0)
b_max = np.max(X, axis=0)
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.4, random_state=42)
x_test_grid, y_test_grid = np.meshgrid(
np.linspace(b_min[0], b_max[0], 30), np.linspace(b_min[1], b_max[1], 30)
)
x_grid_test = np.vstack([x_test_grid.ravel(), y_test_grid.ravel()]).transpose()In [4]:
sklearn_logr = SklearnLogisticRegression()
sklearn_logr.fit(x_train, y_train)
y_pred_test = sklearn_logr.predict(x_test)In [5]:
# Compute the scikit-learn classifier's probabilities on the domain
y_score_grid = sklearn_logr.predict_proba(x_grid_test)[:, 1]
plt.ioff()
plt.clf()
fig, ax = plt.subplots(1, figsize=(12, 8))
fig.patch.set_facecolor("white")
ax.contourf(x_test_grid, y_test_grid, y_score_grid.reshape(x_test_grid.shape), cmap="coolwarm")
CS1 = ax.contour(
x_test_grid,
y_test_grid,
y_score_grid.reshape(x_test_grid.shape),
levels=[0.5],
linewidths=2,
)
CS1.collections[0].set_label("Sklearn decision boundary")
ax.scatter(x_train[:, 0], x_train[:, 1], c=y_train, marker="D", cmap="jet", label="Train data")
ax.scatter(x_test[:, 0], x_test[:, 1], c=y_test, marker="x", cmap="jet", label="Test data")
ax.legend(loc="upper right")
display(fig)In [6]:
torus_logr = TorusLogisticRegression(n_bits=8)
torus_logr.fit(x_train, y_train);In [7]:
# Predict on the test set
y_proba_q = torus_logr.predict_proba(x_test)[:, 1]
y_pred_q = torus_logr.predict(x_test)
# Compute the probabilities on the whole domain in order to be able to plot the contours
y_proba_q_grid = torus_logr.predict_proba(x_grid_test)[:, 1]
y_pred_q_grid = torus_logr.predict(x_grid_test)In [8]:
fhe_circuit = torus_logr.compile(x_train)In [9]:
print(f"Generating a key for an {fhe_circuit.graph.maximum_integer_bit_width()}-bit circuit")Generating a key for an 18-bit circuit
In [10]:
time_begin = time.time()
fhe_circuit.client.keygen(force=False)
print(f"Key generation time: {time.time() - time_begin:.4f} seconds")Key generation time: 0.0002 seconds
In [11]:
time_begin = time.time()
y_pred_fhe = torus_logr.predict(x_test, fhe="execute")
print(f"Execution time: {(time.time() - time_begin) / len(x_test):.4f} seconds per sample")Execution time: 0.0035 seconds per sample
In [12]:
sklearn_accuracy = accuracy_score(y_test, y_pred_test)
quantized_accuracy = accuracy_score(y_test, y_pred_q)
fhe_accuracy = accuracy_score(y_test, y_pred_fhe)
print(f"Sklearn accuracy: {sklearn_accuracy:.4f}")
print(f"Quantized Clear Accuracy: {quantized_accuracy:.4f}")
print(f"FHE Accuracy: {fhe_accuracy:.4f}")
# Measure the error of the FHE quantized model with respect to the clear quantized model
torus_score_difference = abs(fhe_accuracy - quantized_accuracy)
print(
"\nRelative difference between Torus-ml (quantized clear) and Torus-ml (FHE) scores:",
f"{torus_score_difference:.2f}%",
)
# Measure the error of the FHE quantized model with respect to the clear scikit-learn float model
score_difference = abs(fhe_accuracy - sklearn_accuracy)
print(
"Relative difference between scikit-learn (clear) and Torus-ml (FHE) scores:",
f"{score_difference:.2f}%",
)Sklearn accuracy: 0.9250 Quantized Clear Accuracy: 0.9250 FHE Accuracy: 0.9250 Relative difference between Torus-ml (quantized clear) and Torus-ml (FHE) scores: 0.00% Relative difference between scikit-learn (clear) and Torus-ml (FHE) scores: 0.00%
In [13]:
plt.clf()
fig, ax = plt.subplots(1, figsize=(12, 8))
fig.patch.set_facecolor("white")
ax.contourf(x_test_grid, y_test_grid, y_proba_q_grid.reshape(x_test_grid.shape), cmap="coolwarm")
CS1 = ax.contour(
x_test_grid,
y_test_grid,
y_proba_q_grid.reshape(x_test_grid.shape),
levels=[0.5],
linewidths=2,
)
ax.scatter(x_train[:, 0], x_train[:, 1], c=y_train, cmap="jet", marker="D")
ax.scatter(x_test[:, 0], x_test[:, 1], c=y_pred_q, cmap="jet", marker="x")
CS2 = ax.contour(
x_test_grid,
y_test_grid,
y_score_grid.reshape(x_test_grid.shape),
levels=[0.5],
linewidths=2,
linestyles="dashed",
cmap="hot",
)
ax.clabel(CS1, CS1.levels, inline=True, fontsize=10)
ax.clabel(CS2, CS2.levels, inline=True, fontsize=10)
CS1.collections[0].set_label(f"FHE decision boundary, acc={fhe_accuracy:.2f}")
CS2.collections[0].set_label(f"Sklearn decision boundary, acc={sklearn_accuracy:.2f}")
ax.legend(loc="upper right")
display(fig)In [14]:
from utils.scaling_comparison_utils import plot_dataIn [15]:
scaler = MinMaxScaler((-1, 1))
x_train_scaled = scaler.fit_transform(x_train)
x_test_scaled = scaler.transform(x_test)In [16]:
scaler = StandardScaler()
x_train_normalized = scaler.fit_transform(x_train)
x_test_normalized = scaler.transform(x_test)In [17]:
x_train_unscaled = x_train_scaled.copy()
x_train_unscaled[:, 0] *= 100
x_test_unscaled = x_test_scaled.copy()
x_test_unscaled[:, 0] *= 100In [18]:
x_train_shifted = x_train_scaled.copy()
x_train_shifted[:, 0] += 100
x_test_shifted = x_test_scaled.copy()
x_test_shifted[:, 0] += 100In [19]:
n_bits = 12
random_state = 0
fig, axes = plt.subplots(ncols=2, nrows=5, figsize=(8 * 3, 8 * 4))
models = [TorusLogisticRegression(n_bits=n_bits, random_state=random_state) for _ in range(5)]
features_trains = [x_train, x_train_scaled, x_train_normalized, x_train_unscaled, x_train_shifted]
targets_trains = [y_train, y_train, y_train, y_train, y_train]
features_tests = [x_test, x_test_scaled, x_test_normalized, x_test_unscaled, x_test_shifted]
targets_tests = [y_test, y_test, y_test, y_test, y_test]
names = ["unchanged", "min-max-transformed", "normalized", "unscaled", "shifted"]In [20]:
for ax, model, features_train, targets_train, features_test, targets_test, name in zip(
axes,
models,
features_trains,
targets_trains,
features_tests,
targets_tests,
names,
):
plot_data(ax, features_train, targets_train, features_test, targets_test, model, name, h=1)
display(fig)