mirror of
https://github.com/luxfhe/ml-sdk.git
synced 2026-10-30 18:13:04 +00:00
Brand-only sweep. Touches READMEs, docs, package metadata, comments,
notebook markdown, requirements.txt files; does NOT yet touch Python
`concrete.*` imports (those are module-level dependencies requiring the
phase-2 Python module port from `concrete` → `torus`).
Substitutions applied:
Concrete ML → TorusML
concrete-ml → torus-ml
Concrete-ML → Torus-ML
concrete_ml → torus_ml
zama-ai/concrete-ml → luxfhe/ml-sdk
zama-ai/concrete → luxfhe/torus
github.com/zama-ai → github.com/luxfhe
docs.zama.ai/concrete-ml → docs.luxfhe.com/ml-sdk
docs.zama.ai/concrete → docs.luxfhe.com/torus
Zama Concrete ML → Lux TorusML
Zama Concrete → Lux Torus
Zama tfhe-rs / Zama TFHE-rs → Lux-FHE
tfhe-rs / TFHE-rs → Lux-FHE
Zama fhEVM / fhEVM → TorusEVM
Concrete framework → Torus framework
Concrete compiler → Torus compiler
Concrete by Zama → Torus by Lux
the Zama team → the Lux Industries team
Zama's → Lux Industries'
(Zama) → (Lux)
CoFHE / Fhenix → (removed)
LICENSE: original Zama copyright RETAINED per BSD-3-Clause-Clear §1-§2
requirements; Lux Industries modifications copyright added. Per §3 no
name of ZAMA used to endorse the derived work — product marketed
exclusively as TorusML.
README image URLs migrated to github.com/luxfhe/ml-sdk/assets to break
the dependency on Zama's CDN.
Hit count: 350 → 295. Residual hits are Python `from concrete.fhe import`
imports referencing the upstream Zama `concrete` PyPI package; these
require module-level port (phase 2):
Phase 2 plan:
1. Fork zama-ai/concrete (the Python compiler) to luxfhe/torus
2. Rename Python module `concrete` → `torus`; PyPI publish as `torus-fhe`
3. Update ml-sdk imports from `concrete.fhe` → `torus.fhe`, etc.
4. Wire `torus.compiler` GPU dispatch through `luxcpp/gpu` vtbl
(lux-private/gpu-kernels for CUDA/Metal/WebGPU/FPGA targets)
5. Port concrete-cuda + concrete-mlir kernels to
lux-private/gpu-kernels/{cuda,metal,wgsl}/ckks/ (matrix-vector
mul, rescale, rotate, bootstrap for TorusML inference)
Phase 3 plan (kernels):
- CKKS/BGV/BFV GPU kernels in lux-private/gpu-kernels/
(currently only TFHE PBS / keyswitch / blind-rotate exist)
- FPGA bitstreams in lux-private/fpga/ (currently scaffold only)
Phase 1 = docs/branding sweep. PR not opened; user reviews and merges.
399 KiB
399 KiB
In [1]:
import random
import warnings
from copy import deepcopy
import torch
from cifar_utils import get_dataloader, plot_dataset, plot_history, torch_inference, train
from models import Fp32VGG11
warnings.filterwarnings("ignore")In [2]:
dataset_name = "CIFAR_100"
device = "cuda" if torch.cuda.is_available() else "cpu"
param_c10 = {
"output_size": 10,
"batch_size": 128,
"training": "fp32",
"dataset_name": "CIFAR_10",
"criterion": torch.nn.CrossEntropyLoss(),
"accuracy_test": [],
"accuracy_train": [],
"loss_test_history": [],
"loss_train_history": [],
"dir": "./checkpoints/CIFAR_10",
"seed": 727,
}
param_c100 = {
"output_size": 100,
"batch_size": 128,
"training": "fp32",
"dataset_name": "CIFAR_100",
"criterion": torch.nn.CrossEntropyLoss(),
"accuracy_test": [],
"accuracy_train": [],
"loss_test_history": [],
"loss_train_history": [],
"dir": "./checkpoints/CIFAR_100",
"seed": 727,
}
# In this tutorial, we present the results of CIFAR-100.
if dataset_name == "CIFAR_100":
param = param_c100
else:
# If you want to use it for CIFAR-10, set `dataset_name` to "CIFAR_100"
param = param_c10
print(f"Device Type: {device}")Device Type: cuda:0
In [3]:
# Load CIFAR-100 or CIFAR-10 data-set according to `dataset_name`.
train_loader, test_loader = get_dataloader(param=param)
# Let’s visualize `n` images from CIFAR data-set.
plot_dataset(test_loader, param)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 [4]:
torch.manual_seed(param["seed"])
random.seed(param["seed"])
# Instantiation of the custom VGG-11 network.
fp32_vgg = Fp32VGG11(param["output_size"]).to(device)
# Loading the pre-trained VGG-11 weights from torch.hub.
pretrained_weights = torch.hub.load(
"pytorch/vision:v0.10.0",
"vgg11",
pretrained=True,
).state_dict()
# Caution:
# The `fp32_vgg.state_dict()` respects the same schema for the convolutional, ReLU and pooling
# layers (order/shape/naming) as the `pretrained_weights` dict, that's why it doesn't throw an error
fp32_vgg.load_state_dict(deepcopy(pretrained_weights), strict=False)
# We got an IncompatibleKeys warning because
# we deleted the classification layers of the original VGG-11 network.Out [4]:
Using cache found in /home/stoiana/.cache/torch/hub/pytorch_vision_v0.10.0
_IncompatibleKeys(missing_keys=['final_layer.weight', 'final_layer.bias'], unexpected_keys=['classifier.0.weight', 'classifier.0.bias', 'classifier.3.weight', 'classifier.3.bias', 'classifier.6.weight', 'classifier.6.bias'])
In [5]:
# We freeze all the layers.
for p in list(fp32_vgg.parameters()):
p.requires_grad = False
# Set the `requires_grad` of the last layer at `True` to fine-tune it.
fp32_vgg.final_layer.weight.requires_grad = True
fp32_vgg.final_layer.bias.requires_grad = TrueIn [6]:
if dataset_name == "CIFAR_100":
param["lr"] = 0.06
param["epochs"] = 10
param["gamma"] = 0.01
param["milestones"] = [1]
elif dataset_name == "CIFAR_10":
param["lr"] = 0.1
param["epochs"] = 5
param["gamma"] = 0.1
param["milestones"] = [1, 3]
fp32_vgg = train(fp32_vgg, train_loader, test_loader, param, device=device)Epoch 0: Train loss = 2.5821 VS Test loss = 2.2989 - Accuracy train: 0.3639 VS Accuracy test: 0.4441 Epoch 1: Train loss = 2.0172 VS Test loss = 2.0736 - Accuracy train: 0.4741 VS Accuracy test: 0.4776 Epoch 2: Train loss = 1.9677 VS Test loss = 2.0398 - Accuracy train: 0.4868 VS Accuracy test: 0.4820 Epoch 3: Train loss = 1.9539 VS Test loss = 2.0230 - Accuracy train: 0.4887 VS Accuracy test: 0.4854 Epoch 4: Train loss = 1.9427 VS Test loss = 2.0072 - Accuracy train: 0.4941 VS Accuracy test: 0.4889 Epoch 5: Train loss = 1.9285 VS Test loss = 1.9941 - Accuracy train: 0.4978 VS Accuracy test: 0.4898 Epoch 6: Train loss = 1.9226 VS Test loss = 1.9830 - Accuracy train: 0.4960 VS Accuracy test: 0.4928 Epoch 7: Train loss = 1.9159 VS Test loss = 1.9764 - Accuracy train: 0.4965 VS Accuracy test: 0.4936 Epoch 8: Train loss = 1.9075 VS Test loss = 1.9681 - Accuracy train: 0.5017 VS Accuracy test: 0.4944 Epoch 9: Train loss = 1.9019 VS Test loss = 1.9612 - Accuracy train: 0.5023 VS Accuracy test: 0.4956 100%|██████████| 10/10 [10:37<00:00, 63.72s/it]
In [7]:
# Secondly, fine-tuning all the layers.
for p in list(fp32_vgg.parameters()):
p.requires_grad = True
if dataset_name == "CIFAR_100":
param["lr"] = 0.0006
param["epochs"] = 7
param["gamma"] = 0.1
param["milestones"] = [6]
elif dataset_name == "CIFAR_10":
param["lr"] = 0.0006
param["epochs"] = 5
param["gamma"] = 0.1
param["milestones"] = [4]
fp32_vgg = train(fp32_vgg, train_loader, test_loader, param, device=device)Epoch 0: Train loss = 2.3488 VS Test loss = 1.7114 - Accuracy train: 0.3919 VS Accuracy test: 0.5232 Epoch 1: Train loss = 1.5548 VS Test loss = 1.4423 - Accuracy train: 0.5648 VS Accuracy test: 0.5929 Epoch 2: Train loss = 1.2724 VS Test loss = 1.3197 - Accuracy train: 0.6374 VS Accuracy test: 0.6196 Epoch 3: Train loss = 1.0783 VS Test loss = 1.3551 - Accuracy train: 0.6842 VS Accuracy test: 0.6207 Epoch 4: Train loss = 0.9087 VS Test loss = 1.3401 - Accuracy train: 0.7301 VS Accuracy test: 0.6345 Epoch 5: Train loss = 0.7783 VS Test loss = 1.3401 - Accuracy train: 0.7665 VS Accuracy test: 0.6491 Epoch 6: Train loss = 0.3853 VS Test loss = 1.2485 - Accuracy train: 0.8849 VS Accuracy test: 0.6982 100%|██████████| 7/7 [09:43<00:00, 83.37s/it]
In [8]:
acc = torch_inference(fp32_vgg, data=test_loader, device=device)
print(f"With {dataset_name}: top-1 accuracy = {acc * 100:2.3f}%")With CIFAR_100: top-1 accuracy = 69.822%
In [9]:
plot_history(param)In [10]:
plot_history(param_c10, load=True)