Zigmoid
The zigmoid function is defined as follows:
\[\begin{split}zigmoid(x) = \left\{
\begin{array}\\
0 & if\ x<-0.5 \\
x+0.5 & if\ -0.5\leq x \leq 0.5 \\
1 & if x>0.5
\end{array}
\right.\end{split}\]
It is an approximation to the sigmoid function, but easier to compute in the MPC context. It is further analagous to the “cut” function defined in the literature and similar to approximations used elsewhere such as in SecureML.
In this example, we secret share a vector of values selected to demonstrate the different piecewise separated areas of interest for the zigmoid function, and compute the zigmoid.
As always, Cicada’s zigmoid function operates element-wise on arrays of any shape.
[1]:
import logging
import numpy
from cicada.additive import AdditiveProtocolSuite
from cicada.communicator import SocketCommunicator
from cicada.logging import Logger
logging.basicConfig(level=logging.INFO)
def main(communicator):
log = Logger(logging.getLogger(), communicator)
protocol = AdditiveProtocolSuite(communicator)
values = numpy.array([-5, -0.25, 0, 0.25, 5]) if communicator.rank == 0 else None
log.info(f"Player {communicator.rank} values: {values}")
values_share = protocol.share(secret=values, src=0, shape=(5,))
zigmoid_share = protocol.zigmoid(values_share)
zigmoid = protocol.reveal(zigmoid_share)
log.info(f"Player {communicator.rank} zigmoid: {zigmoid}")
SocketCommunicator.run(world_size=2, fn=main);
INFO:root:Player 0 values: [-5. -0.25 0. 0.25 5. ]
INFO:root:Player 1 values: None
INFO:root:Player 0 zigmoid: [0. 0.25 0.5 0.75 1. ]
INFO:root:Player 1 zigmoid: [0. 0.25 0.5 0.75 1. ]