Nada AI Linear Model Tutorial
In this tutorial, we’ll explore the capabilities of Nada AI to create a basic Linear Regression model for inference. First, we'll train our model, and then import it to Nada and the Nillion Network.
Before starting, make sure you have the Nillion SDK installed.
Installation
First things first, let’s get Nada Numpy installed on your system. It’s as easy as running:
pip install --upgrade nada-ai
Training our Linear Regression Model
If you've previously installed nada-ai
, you should already have the dependencies required for this demo. For simplicity, we'll be training on random inputs and outputs. You can find the complete training script here:
import numpy as np
from sklearn.linear_model import LinearRegression
# Create a random input dataset of 1000 samples with 10 features per sample
X = np.random.randn(1,000, 10)
# We assume trained coefficients are the data from a specific linear model
expected_weights = np.ones((10,))
expected_bias = 4.2 # Value taken randomly
y = X @ expected_weights + expected_bias
model = LinearRegression()
# The learned parameters will likely be close to the coefficients & bias we used to generate the data
fit_model = model.fit(X, y)
Now, let's break down the different parts of the program. First, we import the LinearRegression
model from sklearn
to be used in our training. Furthermore, we'll use Numpy to produce a random input dataset.
import numpy as np
from sklearn.linear_model import LinearRegression
We create a random example in a particular way. First, we produce X
, which consists of 1000 random samples with 10 features each. Then, we generate our expected_weights
and expected_bias
and use those to generate the output y
. In this way, we assume that training on X
and y
should yield the expected_weights
and expected_bias
as a result.
# Create a random input dataset of 1000 samples with 10 features per sample
X = np.random.randn(1,000, 10)
# We assume trained coefficients are the data from a specific linear model
expected_weights = np.ones((10,))
expected_bias = 4.2 # Value taken randomly
y = X @ expected_weights + expected_bias
Then we can proceed to train our Linear Regression model. The line below first initializes the LinearRegression
model and then calls the fit
function to proceed with the training.
model = LinearRegression()
fit_model = model.fit(X, y)
Based on the dataset creation, the learned weights and bias should resemble the expected_weights
and expected_bias
. These can be extracted to be imported in the next sections. Whether you save them to a .json
file, or copy-paste them is up to the user.
weights = fit_model.coef_
bias = fit_model.intercept_
Now that we've trained our model, we can proceed to migrate it to Nillion for private execution.
Writing our Nada-AI program
To get started, initialize your project structure with the following command:
nada init nada-linear-regression
This sets up your environment. We'll create a program that performs linear regression inference. Here’s the complete code to place in src/main.py
:
from nada_dsl import *
import nada_numpy as na
from nada_ai.linear_model import LinearRegression
def nada_main():
# Step 1: Define the parties involved in our computation
user = Party(name="User")
provider = Party(name="Provider")
# Step 2: Instantiate the linear regression object
my_model = LinearRegression(10)
# Step 3: Load model weights from the Nillion network using the model name as ID
# Provider provides the model and User runs inference
my_model.load_state_from_network("my_model", provider, na.SecretRational)
# Step 4: Load input data for inference provided by User
my_input = na.array((10,), user, "my_input", na.SecretRational)
# Step 5: Compute inference
result = my_model.forward(my_input)
# Step 6: Produce the output for User with the variable name "my_output"
return na.output(result, user, "my_output")
Now, let's break down each section one step at a time.
1. Import Section
Start by importing the necessary modules:
import nada_numpy as na
from nada_ai.linear_model import LinearRegression
2. Party Declaration Section
Declare the parties involved in the computation. In this case, we have a provider
in charge of training the model and uploading it to the Nillion Network. The user
will input its data and obtain the output classification. Both contribute to the computation but they learn nothing about each other's inputs.
user = Party(name="User")
provider = Party(name="Provider")
This line creates two parties: User
and Provider
.
3. Model Initialization Section
Now, let's instantiate the linear regression model. We use the Nada AI wrapper for Linear Regression and define the number of weights, matching what we initialized our model with.
my_model = LinearRegression(10)
Here, LinearRegression(10)
initializes a linear regression model with 10 features. The initialization only includes the declaration of the underlying components. Next, we need to initialize the model by loading the weights. We do that with the following line:
my_model.load_state_from_network("my_model", provider, na.SecretRational)
This line loads the model weights using the model name "my_model"
for Provider
. The weights are of type SecretRational
.
Under the hood, NadaArray creates variables for each element of the LinearRegression model. For example, for a model called my_model
, we will have variables my_model_coef_0
to my_model_coef_10
and my_model_intercept_0
.
4. Input Data Loading Section
Now, we need to load the user data for the inference. We rely on Nada Numpy for this task:
my_input = na.array((10,), user, "my_input", na.SecretRational)
This line creates an array my_input
with 10 elements, owned by User
, named "my_input"
, and of type na.SecretRational
.
5. Inference Computation Section
With our inputs ready, we can perform computations. We use the model that we just initialized with the common forward
function over the inputs.
result = my_model.forward(my_input)
This line computes the result of the linear regression inference.
6. Output Section
As a final step, we have to determine what our outputs of the computation will be. In this case, User
receives my_output
as a result of the computation.
return na.output(result, user, "my_output")
This line specifies that User
will receive the output named "my_output"
.
With this structure in place, you can build and test your program using:
nada build
Using Nada Numpy with Nillion Network
Once your program is written, you can integrate it with the Nillion Network using the Python Nada Numpy client. The process is similar to other examples. For detailed instructions and the complete code, refer to the GitHub repository.
First, import the necessary modules and the SklearnClient
from Nada AI.
from sklearn.linear_model import LinearRegression
from nada_ai.client import SklearnClient
Then, we use SklearnClient
to format our input model for upload to the Nillion Network:
# Create and store model secrets via ModelClient
model_client = SklearnClient(fit_model) # fit_model is the same model used for training
model_secrets = nillion.Secrets(
model_client.export_state_as_secrets("my_model", na.SecretRational)
)
That’s it! You’ve successfully created, built, and integrated a Nada AI Linear Regression model with the Nillion Network.
For more examples, visit our Github Repository Examples.