mirror of
https://github.com/luxfhe/examples.git
synced 2026-10-30 18:13:15 +00:00
ML examples: - credit_scoring: Credit risk prediction with HMEQ data - disease_prediction: Healthcare ML on encrypted records - cifar: Encrypted image classification - federated_learning: Distributed FHE training - hybrid_model: Mixed FHE/plaintext inference Deployment: - breast_cancer: Cancer detection API - sentiment_analysis: Encrypted NLP - server: FHE inference server Blockchain: - hardhat-template: Solidity + FHE - react-template: Full dApp with FHE
434 KiB
434 KiB
In [1]:
import concrete.compiler
import torch
from cifar_utils import (
fhe_compatibility,
get_dataloader,
mapping_keys,
plot_baseline,
plot_dataset,
torch_inference,
train,
)
# As we follow the same methodology for quantization aware training for CIFAR-10 and CIFAR-100.
# Let's import some generic functions.
from models import QuantVGG11
from torchvision import datasetsIn [2]:
bit = 5
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Device Type: {device}")Device Type: cpu
In [ ]:
compilation_device = "cuda" if concrete.compiler.check_gpu_available() else "cpu"
print(f"Is GPU enabled: {concrete.compiler.check_gpu_enabled()}")
print(f"Is GPU available: {concrete.compiler.check_gpu_available()}")In [3]:
param_c100 = {
"output_size": 100,
"batch_size": 128,
"training": "quant",
"dataset_name": "CIFAR_100",
"dataset": datasets.CIFAR100,
"mean": [0.485, 0.456, 0.406],
"std": [0.229, 0.224, 0.225],
"lr": 6e-5,
"seed": 727,
"epochs": 10,
"gamma": 0.01,
"milestones": [3, 5],
"criterion": torch.nn.CrossEntropyLoss(),
"accuracy_test": [],
"accuracy_train": [],
"loss_test_history": [],
"loss_train_history": [],
"dir": "./checkpoints/CIFAR_100",
"pre_trained_path": "fp32/CIFAR_100_fp32_state_dict.pt",
}In [4]:
# Load CIFAR-100 data-set.
train_loader_c100, test_loader_c100 = get_dataloader(param=param_c100)
# Let’s visualize `n` images from CIFAR-100 data-set.
plot_dataset(test_loader_c100, param_c100)Files already downloaded and verified Files already downloaded and verified
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
In [5]:
quant_vgg = QuantVGG11(bit=bit, output_size=param_c100["output_size"])In [6]:
checkpoint = torch.load(
f"{param_c100['dir']}/{param_c100['pre_trained_path']}", map_location=device
)In [7]:
quant_vgg = mapping_keys(checkpoint, quant_vgg, device)In [9]:
# It's better than a random classifier.
acc_before_ft = torch_inference(quant_vgg, test_loader_c100, device=device)
param_c100["accuracy_test"].append(acc_before_ft)
print(f"Top 1 accuracy before fine-tuning = {acc_before_ft * 100:.4f}%")Top 1 accuracy before fine-tuning = 7.3217%
In [10]:
# The user can either provide the entire train data-set or a smaller but representative subset.
# As each batch is shuffled and contains 128 samples, it's a potential subset.
data_calibration, _ = next(iter(train_loader_c100))
qmodel = fhe_compatibility(quant_vgg, data_calibration, device=compilation_device)
print(
f"With {param_c100['dataset_name']}, the maximum bit-width in the circuit = "
f"{qmodel.fhe_circuit.graph.maximum_integer_bit_width()}"
)In [10]:
quant_vgg = train(quant_vgg, train_loader_c100, test_loader_c100, param_c100, device=device)Epoch 0: Train loss = 0.5070 VS Test loss = 1.3996 - Accuracy train: 0.8428 VS Accuracy test: 0.6791 Epoch 1: Train loss = 0.3827 VS Test loss = 1.4884 - Accuracy train: 0.8800 VS Accuracy test: 0.6805 Epoch 2: Train loss = 0.3163 VS Test loss = 1.5556 - Accuracy train: 0.8996 VS Accuracy test: 0.6873 Epoch 3: Train loss = 0.2609 VS Test loss = 1.5615 - Accuracy train: 0.9170 VS Accuracy test: 0.6855 Epoch 4: Train loss = 0.2505 VS Test loss = 1.5604 - Accuracy train: 0.9189 VS Accuracy test: 0.6877 Epoch 5: Train loss = 0.2497 VS Test loss = 1.5592 - Accuracy train: 0.9218 VS Accuracy test: 0.6889 Epoch 6: Train loss = 0.2498 VS Test loss = 1.5576 - Accuracy train: 0.9219 VS Accuracy test: 0.6882 Epoch 7: Train loss = 0.2442 VS Test loss = 1.5540 - Accuracy train: 0.9222 VS Accuracy test: 0.6894 Epoch 8: Train loss = 0.2434 VS Test loss = 1.5576 - Accuracy train: 0.9228 VS Accuracy test: 0.6879 Epoch 9: Train loss = 0.2504 VS Test loss = 1.5537 - Accuracy train: 0.9205 VS Accuracy test: 0.6897 100%|██████████| 10/10 [11:03<00:00, 66.38s/it]
In [11]:
plot_baseline(param_c100, test_loader_c100, device)100%|██████████| 78/78 [00:02<00:00, 32.94it/s]
Running time: 0.0002 sec.
In [12]:
param_c10 = {
"output_size": 10,
"batch_size": 128,
"training": "quant",
"dataset_name": "CIFAR_10",
"dataset": datasets.CIFAR10,
"std": [0.247, 0.243, 0.261],
"mean": [0.4914, 0.4822, 0.4465],
"seed": 42,
"lr": 1e-5,
"epochs": 9,
"gamma": 0.1,
"milestones": [4],
"criterion": torch.nn.CrossEntropyLoss(),
"accuracy_test": [],
"accuracy_train": [],
"loss_test_history": [],
"loss_train_history": [],
"dir": "./checkpoints/CIFAR_10",
"pre_trained_path": "fp32/CIFAR_10_fp32_state_dict.pt",
}In [13]:
# Load CIFAR-10 data-set.
train_loader_c10, test_loader_c10 = get_dataloader(param=param_c10)
# Let’s visualize `n` images from CIFAR-100 data-set.
plot_dataset(test_loader_c10, param_c10)Files already downloaded and verified Files already downloaded and verified
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
In [14]:
# Instantiate our custom vgg11 network.
quant_vgg = QuantVGG11(bit=bit, output_size=param_c10["output_size"]).to(device)
checkpoint = torch.load(f"{param_c10['dir']}/{param_c10['pre_trained_path']}", map_location=device)
# checkpoint = torch.load("./checkpoints/CIFAR_10/fp32/CIFAR10_fp32_weights_acc_0.9013.pt")
# Mapping keys.
quant_vgg = mapping_keys(checkpoint, quant_vgg, device)In [15]:
# It's better than a random classifier.
acc_before_ft = torch_inference(quant_vgg, test_loader_c10, device=device)
param_c10["accuracy_test"].append(acc_before_ft)
print(f"Top-1 accuracy before fine-tuning = {acc_before_ft * 100:.4f}%")100%|██████████| 78/78 [00:05<00:00, 15.04it/s]
Running time: 0.0005 sec. Top-1 accuracy before fine-tuning = 29.3570%
In [16]:
# Check the FHE-compatibility.
data, _ = next(iter(train_loader_c10))
qmodel = fhe_compatibility(quant_vgg, data, device=compilation_device)
print(
f"With {param_c10['dataset_name']}, the circuit has a maximum bit-width of "
f"{qmodel.fhe_circuit.graph.maximum_integer_bit_width()}-bits."
)With CIFAR_10, the circuit has a maximum bit-width of 14-bits.
In [17]:
# Quantization Aware Training.
quant_vgg = train(quant_vgg, train_loader_c10, test_loader_c10, param_c10, device=device)Epoch 0: Train loss = 0.2612 VS Test loss = 0.3473 - Accuracy train: 0.9084 VS Accuracy test: 0.8895 Epoch 1: Train loss = 0.2136 VS Test loss = 0.3421 - Accuracy train: 0.9252 VS Accuracy test: 0.8902 Epoch 2: Train loss = 0.1629 VS Test loss = 0.3267 - Accuracy train: 0.9443 VS Accuracy test: 0.8986 Epoch 3: Train loss = 0.1578 VS Test loss = 0.3236 - Accuracy train: 0.9467 VS Accuracy test: 0.8999 Epoch 4: Train loss = 0.1521 VS Test loss = 0.3227 - Accuracy train: 0.9470 VS Accuracy test: 0.9006 Epoch 5: Train loss = 0.1520 VS Test loss = 0.3185 - Accuracy train: 0.9472 VS Accuracy test: 0.9042 100%|██████████| 6/6 [07:19<00:00, 73.27s/it]
In [18]:
plot_baseline(param_c10, test_loader_c10, device)