mirror of
https://github.com/luxfhe/docs.git
synced 2026-10-30 18:13:39 +00:00
126 KiB
126 KiB
In [1]:
import time
import numpy as np
import torch
import torch.utils
from concrete.compiler import check_gpu_available
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
from torch import nn
from torch.utils.data import DataLoader, TensorDataset
from tqdm import tqdm
from concrete.ml.torch.compile import compile_torch_model
# And some helpers for visualization.
%matplotlib inline
import matplotlib.pyplot as pltIn [2]:
X, y = load_digits(return_X_y=True)
# The sklearn Digits data-set, though it contains digit images, keeps these images in vectors
# so we need to reshape them to 2D first. The images are 8x8 px in size and monochrome
X = np.expand_dims(X.reshape((-1, 8, 8)), 1)
nplot = 4
fig, ax = plt.subplots(nplot, nplot, figsize=(6, 6))
for i in range(0, nplot):
for j in range(0, nplot):
ax[i, j].imshow(X[i * nplot + j, ::].squeeze())
plt.show()
x_train, x_test, y_train, y_test = train_test_split(
X, y, test_size=0.25, shuffle=True, random_state=42
)In [3]:
class TinyCNN(nn.Module):
"""A very small CNN to classify the sklearn digits data-set."""
def __init__(self, n_classes) -> None:
"""Construct the CNN with a configurable number of classes."""
super().__init__()
# This network has a total complexity of 1216 MAC
self.conv1 = nn.Conv2d(1, 8, 3, stride=1, padding=0)
self.conv2 = nn.Conv2d(8, 16, 3, stride=2, padding=0)
self.conv3 = nn.Conv2d(16, 32, 2, stride=1, padding=0)
self.fc1 = nn.Linear(32, n_classes)
def forward(self, x):
"""Run inference on the tiny CNN, apply the decision layer on the reshaped conv output."""
x = self.conv1(x)
x = torch.relu(x)
x = self.conv2(x)
x = torch.relu(x)
x = self.conv3(x)
x = torch.relu(x)
x = x.flatten(1)
x = self.fc1(x)
return xIn [4]:
torch.manual_seed(42)
def train_one_epoch(net, optimizer, train_loader):
# Cross Entropy loss for classification when not using a softmax layer in the network
loss = nn.CrossEntropyLoss()
net.train()
avg_loss = 0
for data, target in train_loader:
optimizer.zero_grad()
output = net(data)
loss_net = loss(output, target.long())
loss_net.backward()
optimizer.step()
avg_loss += loss_net.item()
return avg_loss / len(train_loader)
# Create the tiny CNN with 10 output classes
N_EPOCHS = 150
# Create a train data loader
train_dataset = TensorDataset(torch.Tensor(x_train), torch.Tensor(y_train))
train_dataloader = DataLoader(train_dataset, batch_size=64)
# Create a test data loader to supply batches for network evaluation (test)
test_dataset = TensorDataset(torch.Tensor(x_test), torch.Tensor(y_test))
test_dataloader = DataLoader(test_dataset)
# Train the network with Adam, output the test set accuracy every epoch
net = TinyCNN(10)
losses_bits = []
optimizer = torch.optim.Adam(net.parameters())
for _ in tqdm(range(N_EPOCHS), desc="Training"):
losses_bits.append(train_one_epoch(net, optimizer, train_dataloader))
fig = plt.figure(figsize=(8, 4))
plt.plot(losses_bits)
plt.ylabel("Cross Entropy Loss")
plt.xlabel("Epoch")
plt.title("Training set loss during training")
plt.grid(True)
plt.show()Training: 0%| | 0/150 [00:00<?, ?it/s]
Training: 1%| | 1/150 [00:00<00:19, 7.58it/s]
Training: 1%|▏ | 2/150 [00:00<00:18, 7.82it/s]
Training: 2%|▏ | 3/150 [00:00<00:18, 7.83it/s]
Training: 3%|▎ | 4/150 [00:00<00:18, 7.85it/s]
Training: 3%|▎ | 5/150 [00:00<00:18, 7.97it/s]
Training: 4%|▍ | 6/150 [00:00<00:17, 8.04it/s]
Training: 5%|▍ | 7/150 [00:00<00:17, 8.08it/s]
Training: 5%|▌ | 8/150 [00:00<00:17, 8.13it/s]
Training: 6%|▌ | 9/150 [00:01<00:17, 8.19it/s]
Training: 7%|▋ | 10/150 [00:01<00:17, 8.23it/s]
Training: 7%|▋ | 11/150 [00:01<00:16, 8.27it/s]
Training: 8%|▊ | 12/150 [00:01<00:16, 8.30it/s]
Training: 9%|▊ | 13/150 [00:01<00:16, 8.30it/s]
Training: 9%|▉ | 14/150 [00:01<00:16, 8.31it/s]
Training: 10%|█ | 15/150 [00:01<00:16, 8.12it/s]
Training: 11%|█ | 16/150 [00:01<00:16, 8.17it/s]
Training: 11%|█▏ | 17/150 [00:02<00:16, 8.22it/s]
Training: 12%|█▏ | 18/150 [00:02<00:16, 8.24it/s]
Training: 13%|█▎ | 19/150 [00:02<00:16, 8.18it/s]
Training: 13%|█▎ | 20/150 [00:02<00:15, 8.21it/s]
Training: 14%|█▍ | 21/150 [00:02<00:15, 8.25it/s]
Training: 15%|█▍ | 22/150 [00:02<00:15, 8.03it/s]
Training: 15%|█▌ | 23/150 [00:02<00:16, 7.89it/s]
Training: 16%|█▌ | 24/150 [00:02<00:16, 7.84it/s]
Training: 17%|█▋ | 25/150 [00:03<00:15, 7.87it/s]
Training: 17%|█▋ | 26/150 [00:03<00:15, 7.85it/s]
Training: 18%|█▊ | 27/150 [00:03<00:15, 7.82it/s]
Training: 19%|█▊ | 28/150 [00:03<00:15, 7.82it/s]
Training: 19%|█▉ | 29/150 [00:03<00:15, 7.84it/s]
Training: 20%|██ | 30/150 [00:03<00:15, 7.87it/s]
Training: 21%|██ | 31/150 [00:03<00:15, 7.85it/s]
Training: 21%|██▏ | 32/150 [00:03<00:14, 7.89it/s]
Training: 22%|██▏ | 33/150 [00:04<00:14, 7.92it/s]
Training: 23%|██▎ | 34/150 [00:04<00:14, 7.92it/s]
Training: 23%|██▎ | 35/150 [00:04<00:14, 7.92it/s]
Training: 24%|██▍ | 36/150 [00:04<00:14, 7.94it/s]
Training: 25%|██▍ | 37/150 [00:04<00:14, 7.96it/s]
Training: 25%|██▌ | 38/150 [00:04<00:14, 7.93it/s]
Training: 26%|██▌ | 39/150 [00:04<00:13, 7.93it/s]
Training: 27%|██▋ | 40/150 [00:04<00:13, 7.93it/s]
Training: 27%|██▋ | 41/150 [00:05<00:13, 7.91it/s]
Training: 28%|██▊ | 42/150 [00:05<00:13, 7.89it/s]
Training: 29%|██▊ | 43/150 [00:05<00:13, 7.89it/s]
Training: 29%|██▉ | 44/150 [00:05<00:13, 7.90it/s]
Training: 30%|███ | 45/150 [00:05<00:13, 7.95it/s]
Training: 31%|███ | 46/150 [00:05<00:13, 7.95it/s]
Training: 31%|███▏ | 47/150 [00:05<00:13, 7.92it/s]
Training: 32%|███▏ | 48/150 [00:06<00:12, 7.96it/s]
Training: 33%|███▎ | 49/150 [00:06<00:12, 7.92it/s]
Training: 33%|███▎ | 50/150 [00:06<00:12, 7.93it/s]
Training: 34%|███▍ | 51/150 [00:06<00:12, 7.94it/s]
Training: 35%|███▍ | 52/150 [00:06<00:12, 7.97it/s]
Training: 35%|███▌ | 53/150 [00:06<00:12, 7.99it/s]
Training: 36%|███▌ | 54/150 [00:06<00:12, 7.99it/s]
Training: 37%|███▋ | 55/150 [00:06<00:11, 7.93it/s]
Training: 37%|███▋ | 56/150 [00:07<00:11, 7.94it/s]
Training: 38%|███▊ | 57/150 [00:07<00:11, 7.86it/s]
Training: 39%|███▊ | 58/150 [00:07<00:11, 7.87it/s]
Training: 39%|███▉ | 59/150 [00:07<00:11, 7.88it/s]
Training: 40%|████ | 60/150 [00:07<00:11, 7.88it/s]
Training: 41%|████ | 61/150 [00:07<00:11, 7.88it/s]
Training: 41%|████▏ | 62/150 [00:07<00:11, 7.90it/s]
Training: 42%|████▏ | 63/150 [00:07<00:11, 7.75it/s]
Training: 43%|████▎ | 64/150 [00:08<00:11, 7.78it/s]
Training: 43%|████▎ | 65/150 [00:08<00:10, 7.81it/s]
Training: 44%|████▍ | 66/150 [00:08<00:10, 7.82it/s]
Training: 45%|████▍ | 67/150 [00:08<00:10, 7.84it/s]
Training: 45%|████▌ | 68/150 [00:08<00:10, 7.87it/s]
Training: 46%|████▌ | 69/150 [00:08<00:10, 7.84it/s]
Training: 47%|████▋ | 70/150 [00:08<00:10, 7.79it/s]
Training: 47%|████▋ | 71/150 [00:08<00:10, 7.73it/s]
Training: 48%|████▊ | 72/150 [00:09<00:10, 7.75it/s]
Training: 49%|████▊ | 73/150 [00:09<00:09, 7.82it/s]
Training: 49%|████▉ | 74/150 [00:09<00:09, 7.86it/s]
Training: 50%|█████ | 75/150 [00:09<00:09, 7.88it/s]
Training: 51%|█████ | 76/150 [00:09<00:09, 7.90it/s]
Training: 51%|█████▏ | 77/150 [00:09<00:09, 7.91it/s]
Training: 52%|█████▏ | 78/150 [00:09<00:09, 7.93it/s]
Training: 53%|█████▎ | 79/150 [00:09<00:08, 7.94it/s]
Training: 53%|█████▎ | 80/150 [00:10<00:08, 7.92it/s]
Training: 54%|█████▍ | 81/150 [00:10<00:08, 7.92it/s]
Training: 55%|█████▍ | 82/150 [00:10<00:08, 7.91it/s]
Training: 55%|█████▌ | 83/150 [00:10<00:08, 7.92it/s]
Training: 56%|█████▌ | 84/150 [00:10<00:08, 7.94it/s]
Training: 57%|█████▋ | 85/150 [00:10<00:08, 7.95it/s]
Training: 57%|█████▋ | 86/150 [00:10<00:08, 7.88it/s]
Training: 58%|█████▊ | 87/150 [00:10<00:07, 7.88it/s]
Training: 59%|█████▊ | 88/150 [00:11<00:07, 7.92it/s]
Training: 59%|█████▉ | 89/150 [00:11<00:07, 7.94it/s]
Training: 60%|██████ | 90/150 [00:11<00:07, 7.92it/s]
Training: 61%|██████ | 91/150 [00:11<00:07, 7.96it/s]
Training: 61%|██████▏ | 92/150 [00:11<00:07, 7.96it/s]
Training: 62%|██████▏ | 93/150 [00:11<00:07, 7.96it/s]
Training: 63%|██████▎ | 94/150 [00:11<00:07, 7.94it/s]
Training: 63%|██████▎ | 95/150 [00:11<00:06, 7.92it/s]
Training: 64%|██████▍ | 96/150 [00:12<00:06, 7.90it/s]
Training: 65%|██████▍ | 97/150 [00:12<00:06, 7.93it/s]
Training: 65%|██████▌ | 98/150 [00:12<00:06, 7.95it/s]
Training: 66%|██████▌ | 99/150 [00:12<00:06, 7.95it/s]
Training: 67%|██████▋ | 100/150 [00:12<00:06, 7.94it/s]
Training: 67%|██████▋ | 101/150 [00:12<00:06, 7.96it/s]
Training: 68%|██████▊ | 102/150 [00:12<00:06, 7.94it/s]
Training: 69%|██████▊ | 103/150 [00:12<00:05, 7.91it/s]
Training: 69%|██████▉ | 104/150 [00:13<00:05, 7.89it/s]
Training: 70%|███████ | 105/150 [00:13<00:05, 7.90it/s]
Training: 71%|███████ | 106/150 [00:13<00:05, 7.89it/s]
Training: 71%|███████▏ | 107/150 [00:13<00:05, 7.91it/s]
Training: 72%|███████▏ | 108/150 [00:13<00:05, 7.92it/s]
Training: 73%|███████▎ | 109/150 [00:13<00:05, 7.92it/s]
Training: 73%|███████▎ | 110/150 [00:13<00:05, 7.86it/s]
Training: 74%|███████▍ | 111/150 [00:13<00:04, 8.00it/s]
Training: 75%|███████▍ | 112/150 [00:14<00:04, 8.02it/s]
Training: 75%|███████▌ | 113/150 [00:14<00:04, 8.02it/s]
Training: 76%|███████▌ | 114/150 [00:14<00:04, 8.01it/s]
Training: 77%|███████▋ | 115/150 [00:14<00:04, 8.04it/s]
Training: 77%|███████▋ | 116/150 [00:14<00:04, 8.00it/s]
Training: 78%|███████▊ | 117/150 [00:14<00:04, 7.96it/s]
Training: 79%|███████▊ | 118/150 [00:14<00:04, 7.91it/s]
Training: 79%|███████▉ | 119/150 [00:14<00:03, 7.92it/s]
Training: 80%|████████ | 120/150 [00:15<00:03, 7.94it/s]
Training: 81%|████████ | 121/150 [00:15<00:03, 7.94it/s]
Training: 81%|████████▏ | 122/150 [00:15<00:03, 7.98it/s]
Training: 82%|████████▏ | 123/150 [00:15<00:03, 7.99it/s]
Training: 83%|████████▎ | 124/150 [00:15<00:03, 7.97it/s]
Training: 83%|████████▎ | 125/150 [00:15<00:03, 7.94it/s]
Training: 84%|████████▍ | 126/150 [00:15<00:03, 7.92it/s]
Training: 85%|████████▍ | 127/150 [00:15<00:02, 7.93it/s]
Training: 85%|████████▌ | 128/150 [00:16<00:02, 8.04it/s]
Training: 86%|████████▌ | 129/150 [00:16<00:02, 8.04it/s]
Training: 87%|████████▋ | 130/150 [00:16<00:02, 8.02it/s]
Training: 87%|████████▋ | 131/150 [00:16<00:02, 8.03it/s]
Training: 88%|████████▊ | 132/150 [00:16<00:02, 7.97it/s]
Training: 89%|████████▊ | 133/150 [00:16<00:02, 7.96it/s]
Training: 89%|████████▉ | 134/150 [00:16<00:02, 7.94it/s]
Training: 90%|█████████ | 135/150 [00:16<00:01, 7.95it/s]
Training: 91%|█████████ | 136/150 [00:17<00:01, 7.95it/s]
Training: 91%|█████████▏| 137/150 [00:17<00:01, 7.94it/s]
Training: 92%|█████████▏| 138/150 [00:17<00:01, 7.92it/s]
Training: 93%|█████████▎| 139/150 [00:17<00:01, 7.95it/s]
Training: 93%|█████████▎| 140/150 [00:17<00:01, 7.93it/s]
Training: 94%|█████████▍| 141/150 [00:17<00:01, 7.94it/s]
Training: 95%|█████████▍| 142/150 [00:17<00:01, 7.90it/s]
Training: 95%|█████████▌| 143/150 [00:17<00:00, 7.94it/s]
Training: 96%|█████████▌| 144/150 [00:18<00:00, 7.95it/s]
Training: 97%|█████████▋| 145/150 [00:18<00:00, 7.93it/s]
Training: 97%|█████████▋| 146/150 [00:18<00:00, 7.95it/s]
Training: 98%|█████████▊| 147/150 [00:18<00:00, 7.95it/s]
Training: 99%|█████████▊| 148/150 [00:18<00:00, 7.96it/s]
Training: 99%|█████████▉| 149/150 [00:18<00:00, 7.95it/s]
Training: 100%|██████████| 150/150 [00:18<00:00, 7.93it/s]
Training: 100%|██████████| 150/150 [00:18<00:00, 7.95it/s]
In [5]:
def test_torch(net, test_loader):
"""Test the network: measure accuracy on the test set."""
# Freeze normalization layers
net.eval()
all_y_pred = np.zeros((len(test_loader)), dtype=np.int64)
all_targets = np.zeros((len(test_loader)), dtype=np.int64)
# Iterate over the batches
idx = 0
for data, target in test_loader:
# Accumulate the ground truth labels
endidx = idx + target.shape[0]
all_targets[idx:endidx] = target.numpy()
# Run forward and get the predicted class id
output = net(data).argmax(1).detach().numpy()
all_y_pred[idx:endidx] = output
idx += target.shape[0]
# Print out the accuracy as a percentage
n_correct = np.sum(all_targets == all_y_pred)
print(
f"Test accuracy for fp32 weights and activations: "
f"{n_correct / len(test_loader) * 100:.2f}%"
)
test_torch(net, test_dataloader)Test accuracy for fp32 weights and activations: 98.22%
In [6]:
def test_with_concrete(quantized_module, test_loader, use_sim):
"""Test a neural network that is quantized and compiled with Concrete ML."""
# Casting the inputs into int64 is recommended
all_y_pred = np.zeros((len(test_loader)), dtype=np.int64)
all_targets = np.zeros((len(test_loader)), dtype=np.int64)
# Iterate over the test batches and accumulate predictions and ground truth labels in a vector
idx = 0
for data, target in tqdm(test_loader):
data = data.numpy()
target = target.numpy()
fhe_mode = "simulate" if use_sim else "execute"
# Quantize the inputs and cast to appropriate data type
y_pred = quantized_module.forward(data, fhe=fhe_mode)
endidx = idx + target.shape[0]
# Accumulate the ground truth labels
all_targets[idx:endidx] = target
# Get the predicted class id and accumulate the predictions
y_pred = np.argmax(y_pred, axis=1)
all_y_pred[idx:endidx] = y_pred
# Update the index
idx += target.shape[0]
# Compute and report results
n_correct = np.sum(all_targets == all_y_pred)
return n_correct / len(test_loader)In [7]:
n_bits = 6
use_gpu_if_available = False
device = "cuda" if use_gpu_if_available and check_gpu_available() else "cpu"
q_module = compile_torch_model(net, x_train, rounding_threshold_bits=6, p_error=0.1, device=device)
start_time = time.time()
accs = test_with_concrete(
q_module,
test_dataloader,
use_sim=True,
)
sim_time = time.time() - start_time
print(f"Simulated FHE execution for {n_bits} bit network accuracy: {accs:.2f}%")0%| | 0/450 [00:00<?, ?it/s]
0%| | 1/450 [00:00<03:13, 2.32it/s]
1%| | 3/450 [00:00<01:14, 6.04it/s]
1%|▏ | 6/450 [00:00<00:38, 11.64it/s]
2%|▏ | 9/450 [00:00<00:27, 16.03it/s]
3%|▎ | 12/450 [00:00<00:22, 19.30it/s]
3%|▎ | 15/450 [00:01<00:19, 21.77it/s]
4%|▍ | 18/450 [00:01<00:18, 23.58it/s]
5%|▍ | 21/450 [00:01<00:17, 24.91it/s]
5%|▌ | 24/450 [00:01<00:16, 25.84it/s]
6%|▌ | 27/450 [00:01<00:15, 26.54it/s]
7%|▋ | 30/450 [00:01<00:15, 27.01it/s]
7%|▋ | 33/450 [00:01<00:15, 27.34it/s]
8%|▊ | 36/450 [00:01<00:15, 27.57it/s]
9%|▊ | 39/450 [00:01<00:14, 27.72it/s]
9%|▉ | 42/450 [00:01<00:14, 27.82it/s]
10%|█ | 45/450 [00:02<00:14, 27.93it/s]
11%|█ | 48/450 [00:02<00:14, 28.01it/s]
11%|█▏ | 51/450 [00:02<00:14, 28.07it/s]
12%|█▏ | 54/450 [00:02<00:14, 28.12it/s]
13%|█▎ | 57/450 [00:02<00:13, 28.13it/s]
13%|█▎ | 60/450 [00:02<00:13, 28.12it/s]
14%|█▍ | 63/450 [00:02<00:13, 28.09it/s]
15%|█▍ | 66/450 [00:02<00:13, 28.10it/s]
15%|█▌ | 69/450 [00:02<00:13, 28.12it/s]
16%|█▌ | 72/450 [00:03<00:13, 28.15it/s]
17%|█▋ | 75/450 [00:03<00:13, 28.17it/s]
17%|█▋ | 78/450 [00:03<00:13, 28.16it/s]
18%|█▊ | 81/450 [00:03<00:13, 28.21it/s]
19%|█▊ | 84/450 [00:03<00:12, 28.17it/s]
19%|█▉ | 87/450 [00:03<00:13, 27.82it/s]
20%|██ | 90/450 [00:03<00:12, 27.95it/s]
21%|██ | 93/450 [00:03<00:12, 28.01it/s]
21%|██▏ | 96/450 [00:03<00:12, 28.05it/s]
22%|██▏ | 99/450 [00:03<00:12, 28.11it/s]
23%|██▎ | 102/450 [00:04<00:12, 28.14it/s]
23%|██▎ | 105/450 [00:04<00:12, 28.10it/s]
24%|██▍ | 108/450 [00:04<00:12, 28.13it/s]
25%|██▍ | 111/450 [00:04<00:12, 28.20it/s]
25%|██▌ | 114/450 [00:04<00:11, 28.21it/s]
26%|██▌ | 117/450 [00:04<00:11, 28.25it/s]
27%|██▋ | 120/450 [00:04<00:11, 28.41it/s]
27%|██▋ | 123/450 [00:04<00:11, 28.41it/s]
28%|██▊ | 126/450 [00:04<00:11, 28.45it/s]
29%|██▊ | 129/450 [00:05<00:11, 28.57it/s]
29%|██▉ | 132/450 [00:05<00:11, 28.56it/s]
30%|███ | 135/450 [00:05<00:11, 28.54it/s]
31%|███ | 138/450 [00:05<00:10, 28.65it/s]
31%|███▏ | 141/450 [00:05<00:10, 28.70it/s]
32%|███▏ | 144/450 [00:05<00:10, 28.66it/s]
33%|███▎ | 147/450 [00:05<00:10, 28.75it/s]
33%|███▎ | 150/450 [00:05<00:10, 28.85it/s]
34%|███▍ | 153/450 [00:05<00:10, 28.90it/s]
35%|███▍ | 156/450 [00:05<00:10, 28.91it/s]
35%|███▌ | 159/450 [00:06<00:10, 28.91it/s]
36%|███▌ | 162/450 [00:06<00:09, 28.93it/s]
37%|███▋ | 165/450 [00:06<00:09, 28.94it/s]
37%|███▋ | 168/450 [00:06<00:09, 28.92it/s]
38%|███▊ | 171/450 [00:06<00:09, 28.91it/s]
39%|███▊ | 174/450 [00:06<00:09, 28.91it/s]
39%|███▉ | 177/450 [00:06<00:09, 28.94it/s]
40%|████ | 180/450 [00:06<00:09, 28.95it/s]
41%|████ | 183/450 [00:06<00:09, 28.96it/s]
41%|████▏ | 186/450 [00:07<00:09, 28.84it/s]
42%|████▏ | 189/450 [00:07<00:09, 28.85it/s]
43%|████▎ | 192/450 [00:07<00:08, 28.88it/s]
43%|████▎ | 195/450 [00:07<00:08, 28.91it/s]
44%|████▍ | 198/450 [00:07<00:08, 28.92it/s]
45%|████▍ | 201/450 [00:07<00:08, 28.93it/s]
45%|████▌ | 204/450 [00:07<00:08, 28.95it/s]
46%|████▌ | 207/450 [00:07<00:08, 28.96it/s]
47%|████▋ | 210/450 [00:07<00:08, 28.98it/s]
47%|████▋ | 213/450 [00:07<00:08, 28.99it/s]
48%|████▊ | 216/450 [00:08<00:08, 28.98it/s]
49%|████▊ | 219/450 [00:08<00:07, 29.04it/s]
49%|████▉ | 222/450 [00:08<00:07, 29.16it/s]
50%|█████ | 225/450 [00:08<00:07, 29.24it/s]
51%|█████ | 228/450 [00:08<00:07, 29.29it/s]
51%|█████▏ | 231/450 [00:08<00:07, 29.33it/s]
52%|█████▏ | 234/450 [00:08<00:07, 29.35it/s]
53%|█████▎ | 237/450 [00:08<00:07, 29.38it/s]
53%|█████▎ | 240/450 [00:08<00:07, 29.40it/s]
54%|█████▍ | 243/450 [00:08<00:07, 29.42it/s]
55%|█████▍ | 246/450 [00:09<00:06, 29.43it/s]
55%|█████▌ | 249/450 [00:09<00:06, 29.43it/s]
56%|█████▌ | 252/450 [00:09<00:06, 29.43it/s]
57%|█████▋ | 255/450 [00:09<00:06, 29.42it/s]
57%|█████▋ | 258/450 [00:09<00:06, 29.43it/s]
58%|█████▊ | 261/450 [00:09<00:06, 29.43it/s]
59%|█████▊ | 264/450 [00:09<00:06, 29.42it/s]
59%|█████▉ | 267/450 [00:09<00:06, 29.42it/s]
60%|██████ | 270/450 [00:09<00:06, 29.42it/s]
61%|██████ | 273/450 [00:09<00:06, 29.42it/s]
61%|██████▏ | 276/450 [00:10<00:05, 29.39it/s]
62%|██████▏ | 279/450 [00:10<00:05, 29.38it/s]
63%|██████▎ | 282/450 [00:10<00:05, 29.40it/s]
63%|██████▎ | 285/450 [00:10<00:05, 29.41it/s]
64%|██████▍ | 288/450 [00:10<00:05, 29.40it/s]
65%|██████▍ | 291/450 [00:10<00:05, 29.40it/s]
65%|██████▌ | 294/450 [00:10<00:05, 29.41it/s]
66%|██████▌ | 297/450 [00:10<00:05, 29.41it/s]
67%|██████▋ | 300/450 [00:10<00:05, 29.41it/s]
67%|██████▋ | 303/450 [00:11<00:04, 29.42it/s]
68%|██████▊ | 306/450 [00:11<00:04, 29.41it/s]
69%|██████▊ | 309/450 [00:11<00:04, 29.41it/s]
69%|██████▉ | 312/450 [00:11<00:04, 29.42it/s]
70%|███████ | 315/450 [00:11<00:04, 29.41it/s]
71%|███████ | 318/450 [00:11<00:04, 29.42it/s]
71%|███████▏ | 321/450 [00:11<00:04, 29.41it/s]
72%|███████▏ | 324/450 [00:11<00:04, 29.41it/s]
73%|███████▎ | 327/450 [00:11<00:04, 29.42it/s]
73%|███████▎ | 330/450 [00:11<00:04, 29.43it/s]
74%|███████▍ | 333/450 [00:12<00:03, 29.43it/s]
75%|███████▍ | 336/450 [00:12<00:03, 29.40it/s]
75%|███████▌ | 339/450 [00:12<00:03, 29.39it/s]
76%|███████▌ | 342/450 [00:12<00:03, 29.40it/s]
77%|███████▋ | 345/450 [00:12<00:03, 29.41it/s]
77%|███████▋ | 348/450 [00:12<00:03, 29.42it/s]
78%|███████▊ | 351/450 [00:12<00:03, 29.41it/s]
79%|███████▊ | 354/450 [00:12<00:03, 29.43it/s]
79%|███████▉ | 357/450 [00:12<00:03, 29.43it/s]
80%|████████ | 360/450 [00:12<00:03, 29.45it/s]
81%|████████ | 363/450 [00:13<00:02, 29.45it/s]
81%|████████▏ | 366/450 [00:13<00:02, 29.44it/s]
82%|████████▏ | 369/450 [00:13<00:02, 29.44it/s]
83%|████████▎ | 372/450 [00:13<00:02, 29.44it/s]
83%|████████▎ | 375/450 [00:13<00:02, 29.43it/s]
84%|████████▍ | 378/450 [00:13<00:02, 29.43it/s]
85%|████████▍ | 381/450 [00:13<00:02, 28.83it/s]
85%|████████▌ | 384/450 [00:13<00:02, 29.00it/s]
86%|████████▌ | 387/450 [00:13<00:02, 29.14it/s]
87%|████████▋ | 390/450 [00:13<00:02, 29.23it/s]
87%|████████▋ | 393/450 [00:14<00:01, 29.29it/s]
88%|████████▊ | 396/450 [00:14<00:01, 29.34it/s]
89%|████████▊ | 399/450 [00:14<00:01, 29.34it/s]
89%|████████▉ | 402/450 [00:14<00:01, 29.37it/s]
90%|█████████ | 405/450 [00:14<00:01, 29.39it/s]
91%|█████████ | 408/450 [00:14<00:01, 29.40it/s]
91%|█████████▏| 411/450 [00:14<00:01, 29.41it/s]
92%|█████████▏| 414/450 [00:14<00:01, 29.42it/s]
93%|█████████▎| 417/450 [00:14<00:01, 29.42it/s]
93%|█████████▎| 420/450 [00:15<00:01, 29.42it/s]
94%|█████████▍| 423/450 [00:15<00:00, 29.42it/s]
95%|█████████▍| 426/450 [00:15<00:00, 29.43it/s]
95%|█████████▌| 429/450 [00:15<00:00, 29.44it/s]
96%|█████████▌| 432/450 [00:15<00:00, 29.42it/s]
97%|█████████▋| 435/450 [00:15<00:00, 29.44it/s]
97%|█████████▋| 438/450 [00:15<00:00, 29.43it/s]
98%|█████████▊| 441/450 [00:15<00:00, 29.44it/s]
99%|█████████▊| 444/450 [00:15<00:00, 29.44it/s]
99%|█████████▉| 447/450 [00:15<00:00, 29.45it/s]
100%|██████████| 450/450 [00:16<00:00, 29.45it/s]
100%|██████████| 450/450 [00:16<00:00, 28.09it/s]
Simulated FHE execution for 6 bit network accuracy: 0.97%
In [8]:
# Generate keys first
t = time.time()
q_module.fhe_circuit.keygen()
print(f"Keygen time: {time.time()-t:.2f}s")Keygen time: 1.88s
In [9]:
# Run inference in FHE on a single encrypted example
mini_test_dataset = TensorDataset(torch.Tensor(x_test[:100, :]), torch.Tensor(y_test[:100]))
mini_test_dataloader = DataLoader(mini_test_dataset)
t = time.time()
accuracy_test = test_with_concrete(
q_module,
mini_test_dataloader,
use_sim=False,
)
elapsed_time = time.time() - t
time_per_inference = elapsed_time / len(mini_test_dataset)
accuracy_percentage = 100 * accuracy_test
print(
f"Time per inference in FHE: {time_per_inference:.2f} "
f"with {accuracy_percentage:.2f}% accuracy"
)0%| | 0/100 [00:00<?, ?it/s]
1%| | 1/100 [00:02<04:29, 2.73s/it]
2%|▏ | 2/100 [00:04<03:55, 2.41s/it]
3%|▎ | 3/100 [00:14<08:51, 5.48s/it]
4%|▍ | 4/100 [00:18<07:51, 4.91s/it]
5%|▌ | 5/100 [00:20<06:14, 3.95s/it]
6%|▌ | 6/100 [00:22<05:19, 3.40s/it]
7%|▋ | 7/100 [00:24<04:40, 3.02s/it]
8%|▊ | 8/100 [00:27<04:14, 2.76s/it]
9%|▉ | 9/100 [00:31<05:07, 3.38s/it]
10%|█ | 10/100 [00:36<05:34, 3.72s/it]
11%|█ | 11/100 [00:38<04:53, 3.29s/it]
12%|█▏ | 12/100 [00:41<04:25, 3.02s/it]
13%|█▎ | 13/100 [00:43<04:03, 2.80s/it]
14%|█▍ | 14/100 [00:45<03:47, 2.65s/it]
15%|█▌ | 15/100 [00:47<03:35, 2.53s/it]
16%|█▌ | 16/100 [00:50<03:25, 2.45s/it]
17%|█▋ | 17/100 [00:52<03:18, 2.40s/it]
18%|█▊ | 18/100 [00:54<03:13, 2.36s/it]
19%|█▉ | 19/100 [00:58<03:47, 2.81s/it]
20%|██ | 20/100 [01:00<03:35, 2.69s/it]
21%|██ | 21/100 [01:04<03:57, 3.00s/it]
22%|██▏ | 22/100 [01:08<04:12, 3.24s/it]
23%|██▎ | 23/100 [01:10<03:47, 2.95s/it]
24%|██▍ | 24/100 [01:13<03:28, 2.75s/it]
25%|██▌ | 25/100 [01:15<03:17, 2.63s/it]
26%|██▌ | 26/100 [01:17<03:06, 2.52s/it]
27%|██▋ | 27/100 [01:19<02:58, 2.44s/it]
28%|██▊ | 28/100 [01:22<02:51, 2.38s/it]
29%|██▉ | 29/100 [01:24<02:46, 2.35s/it]
30%|███ | 30/100 [01:26<02:42, 2.32s/it]
31%|███ | 31/100 [01:28<02:38, 2.30s/it]
32%|███▏ | 32/100 [01:32<02:53, 2.56s/it]
33%|███▎ | 33/100 [01:34<02:45, 2.47s/it]
34%|███▍ | 34/100 [01:36<02:39, 2.41s/it]
35%|███▌ | 35/100 [01:41<03:25, 3.16s/it]
36%|███▌ | 36/100 [01:43<03:05, 2.89s/it]
37%|███▋ | 37/100 [01:46<02:49, 2.70s/it]
38%|███▊ | 38/100 [01:48<02:38, 2.56s/it]
39%|███▉ | 39/100 [01:52<02:57, 2.91s/it]
40%|████ | 40/100 [01:54<02:43, 2.73s/it]
41%|████ | 41/100 [01:56<02:32, 2.59s/it]
42%|████▏ | 42/100 [01:58<02:24, 2.49s/it]
43%|████▎ | 43/100 [02:01<02:17, 2.42s/it]
44%|████▍ | 44/100 [02:04<02:26, 2.62s/it]
45%|████▌ | 45/100 [02:06<02:18, 2.51s/it]
46%|████▌ | 46/100 [02:08<02:11, 2.44s/it]
47%|████▋ | 47/100 [02:10<02:06, 2.38s/it]
48%|████▊ | 48/100 [02:14<02:15, 2.61s/it]
49%|████▉ | 49/100 [02:16<02:12, 2.61s/it]
50%|█████ | 50/100 [02:19<02:09, 2.59s/it]
51%|█████ | 51/100 [02:22<02:09, 2.64s/it]
52%|█████▏ | 52/100 [02:24<02:00, 2.52s/it]
53%|█████▎ | 53/100 [02:26<01:54, 2.43s/it]
54%|█████▍ | 54/100 [02:28<01:49, 2.38s/it]
55%|█████▌ | 55/100 [02:30<01:45, 2.34s/it]
56%|█████▌ | 56/100 [02:33<01:41, 2.31s/it]
57%|█████▋ | 57/100 [02:35<01:39, 2.32s/it]
58%|█████▊ | 58/100 [02:37<01:36, 2.30s/it]
59%|█████▉ | 59/100 [02:40<01:33, 2.29s/it]
60%|██████ | 60/100 [02:42<01:31, 2.29s/it]
61%|██████ | 61/100 [02:44<01:29, 2.29s/it]
62%|██████▏ | 62/100 [02:46<01:26, 2.28s/it]
63%|██████▎ | 63/100 [02:49<01:24, 2.27s/it]
64%|██████▍ | 64/100 [02:51<01:21, 2.27s/it]
65%|██████▌ | 65/100 [02:53<01:19, 2.26s/it]
66%|██████▌ | 66/100 [02:55<01:16, 2.25s/it]
67%|██████▋ | 67/100 [02:58<01:14, 2.25s/it]
68%|██████▊ | 68/100 [03:00<01:12, 2.26s/it]
69%|██████▉ | 69/100 [03:02<01:10, 2.26s/it]
70%|███████ | 70/100 [03:05<01:08, 2.28s/it]
71%|███████ | 71/100 [03:07<01:05, 2.27s/it]
72%|███████▏ | 72/100 [03:09<01:03, 2.27s/it]
73%|███████▎ | 73/100 [03:12<01:10, 2.61s/it]
74%|███████▍ | 74/100 [03:15<01:05, 2.53s/it]
75%|███████▌ | 75/100 [03:17<01:01, 2.45s/it]
76%|███████▌ | 76/100 [03:19<00:57, 2.39s/it]
77%|███████▋ | 77/100 [03:22<00:54, 2.35s/it]
78%|███████▊ | 78/100 [03:24<00:51, 2.34s/it]
79%|███████▉ | 79/100 [03:26<00:48, 2.32s/it]
80%|████████ | 80/100 [03:28<00:45, 2.30s/it]
81%|████████ | 81/100 [03:31<00:43, 2.28s/it]
82%|████████▏ | 82/100 [03:33<00:43, 2.44s/it]
83%|████████▎ | 83/100 [03:36<00:40, 2.40s/it]
84%|████████▍ | 84/100 [03:38<00:38, 2.42s/it]
85%|████████▌ | 85/100 [03:40<00:35, 2.38s/it]
86%|████████▌ | 86/100 [03:44<00:35, 2.57s/it]
87%|████████▋ | 87/100 [03:46<00:32, 2.48s/it]
88%|████████▊ | 88/100 [03:48<00:28, 2.41s/it]
89%|████████▉ | 89/100 [03:50<00:25, 2.36s/it]
90%|█████████ | 90/100 [03:53<00:23, 2.38s/it]
91%|█████████ | 91/100 [03:55<00:21, 2.34s/it]
92%|█████████▏| 92/100 [03:57<00:18, 2.31s/it]
93%|█████████▎| 93/100 [03:59<00:16, 2.30s/it]
94%|█████████▍| 94/100 [04:02<00:13, 2.29s/it]
95%|█████████▌| 95/100 [04:04<00:11, 2.28s/it]
96%|█████████▌| 96/100 [04:06<00:09, 2.27s/it]
97%|█████████▋| 97/100 [04:08<00:06, 2.27s/it]
98%|█████████▊| 98/100 [04:11<00:04, 2.26s/it]
99%|█████████▉| 99/100 [04:13<00:02, 2.26s/it]
100%|██████████| 100/100 [04:15<00:00, 2.26s/it]
100%|██████████| 100/100 [04:15<00:00, 2.56s/it]
Time per inference in FHE: 2.56 with 99.00% accuracy