Step-by-step guide
Last updated
Was this helpful?
Last updated
Was this helpful?
This guide demonstrates how to convert a PyTorch neural network into a Fully Homomorphic Encryption (FHE)-friendly, quantized version. It focuses on Quantization Aware Training (QAT) using a simple network on a synthetic data-set. This guide is based on a , from which some code blocks are documented.
In general, quantization can be carried out in two different ways:
During the training phase with
After the training phase with .
For FHE-friendly neural networks, QAT is the best method to achieve optimal accuracy under . This technique reduces weights and activations to very low bit-widths (for example, 2-3 bits). When combined with pruning, QAT helps keep low accumulator bit-widths.
Concrete ML uses the third-party library to perform QAT for PyTorch neural networks, but options exist for other frameworks such as Keras/Tensorflow. Concrete ML provides several that use Brevitas , including the . For a more formal description of the usage of Brevitas to build FHE-compatible neural networks, please see the .
In PyTorch, using standard layers, a Fully Connected Neural Network (FCNN) would look like this:
The network was trained using different numbers of neurons in the hidden layers, and quantized using 3-bits weights and activations. The mean accumulator size, shown below, is measured as the mean over 10 runs of the experiment. An accumulator size of 6.6 means that 4 times out of 10, the accumulator was 6 bits, while 6 times it was 7 bits.
fp32 accuracy
68.70%
83.32%
88.06%
3-bit accuracy
56.44%
55.54%
56.50%
mean accumulator size
6.6
6.9
7.4
This shows that the fp32 accuracy and accumulator size increases with the number of hidden neurons, while the 3-bits accuracy remains low regardless of the number of neurons. Although all configurations tested were FHE-compatible (accumulator < 16 bits), it is often preferable to have a lower accumulator size to speed up inference time.
Brevitas provides quantized versions of almost all PyTorch layers. For example, Linear
layer becomes QuantLinear
, and ReLU
layer becomes QuantReLU
. Brevitas also offers additional quantization parameters, such as:
bit_width
: precision quantization bits for activations
act_quant
: quantization protocol for the activations
weight_bit_width
: precision quantization bits for weights
weight_quant
: quantization protocol for the weights
To use FHE, the network must be quantized from end to end. With the Brevitas QuantIdentity
layer, you can quantize the input by placing it at the network's entry point. Moreover, you can combine PyTorch and Brevitas layers, as long as a QuantIdentity
layer follows the PyTorch layer. The following table lists the replacements needed to convert a PyTorch neural network for Concrete ML compatibility.
torch.nn.Linear
brevitas.quant.QuantLinear
torch.nn.Conv2d
brevitas.quant.Conv2d
torch.nn.AvgPool2d
torch.nn.AvgPool2d
+ brevitas.quant.QuantIdentity
torch.nn.ReLU
brevitas.quant.QuantReLU
Some PyTorch operators (from the PyTorch functional API), require a brevitas.quant.QuantIdentity
to be applied on their inputs.
torch.transpose
torch.add
(between two activation tensors)
torch.reshape
torch.flatten
With Brevitas, the network above becomes:
3-bit accuracy brevitas
95.4%
3-bit accuracy in Concrete ML
95.4%
Accumulator size
7
Considering that FHE only works with limited integer precision, there is a risk of overflowing in the accumulator, which will make Concrete ML raise an error.
The following code shows how to use pruning in the previous example:
Results with PrunedQuantNet
, a pruned version of the QuantSimpleNet
with 100 neurons on the hidden layers, are given below, showing a mean accumulator size measured over 10 runs of the experiment:
3-bit accuracy
82.50%
88.06%
Mean accumulator size
6.6
6.8
This shows that the fp32 accuracy has been improved while maintaining constant mean accumulator size.
When pruning a larger neural network during training, it is easier to obtain a low bit-width accumulator while maintaining better final accuracy. Thus, pruning is more robust than training a similar, smaller network.
Similarly to the one above, the shows how to train a FCNN on a synthetic 2D data-set with a checkerboard grid pattern of 100 x 100 points. The data is split into 9500 training and 500 test samples.
Once trained, you can import this PyTorch network using the function, which uses simple PTQ.
Accumulator size is determined by as the maximum bit-width encountered anywhere in the encrypted circuit.
Using with is the best way to guarantee a good accuracy for Concrete ML compatible neural networks.
Training this network with pruning (see ) using 30 out of 100 total non-zero neurons gives good accuracy while keeping the accumulator size low.
To understand how to overcome this limitation, consider a scenario where 2 bits are used for weights and layer inputs/outputs. The Linear
layer computes a dot product between weights and inputs . With 2 bits, no overflow can occur during the computation of the Linear
layer as long the number of neurons does not exceed 14, as in the sum of 14 products of 2-bits numbers does not exceed 7 bits.
By default, Concrete ML uses symmetric quantization for model weights, with values in the interval . For example, for the possible values are ; for , the values can be .
In a typical setting, the weights will not all have the maximum or minimum values (such as ). Weights typically have a normal distribution around 0, which is one of the motivating factors for their symmetric quantization. A symmetric distribution and many zero-valued weights are desirable because opposite sign weights can cancel each other out and zero weights do not increase the accumulator size.
This fact can be leveraged to train a network with more neurons, while not overflowing the accumulator, using a technique called where the developer can impose a number of zero-valued weights. Torch out of the box.