Here you will learn how to save the configured encoder, fully trained model, or NPU state so that you can use those objects at a later date without going through the set up and training process
Users are able to save the internal Encoder, Model, and NPU state of a NIML Model in binary format. This allows you to load it at a later date to continue working with the exact same Model or NPU object by either continuing training on that NPU, or by using it in inference mode.
This method does NOT save all parameters required to recreate an encoder, model, or NPU via parameterization and training. Make sure to save a copy of the code that created your model if you think you'll want to make any adjustments to the model training in the future!
Loading a Dataset
For this example, we will need a dataset that is split into a train and test split. We will use the Iris dataset.
import pandas as pd
import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split
#Load the dataset
data_file = datasets.load_iris()
#Extract the data, outcome variable, and labels from the source dataset
X = pd.DataFrame(data_file.data)
Y = pd.DataFrame(data_file.target)
#Combine the features and label into one dataset to work with NIML
data = pd.concat([Y,X], axis=1, ignore_index=True)
#Create train and test splits of the data
train, test = train_test_split(data, test_size=0.20, random_state=451)
Saving an Encoder State
Once you have loaded your data and configured your encoder with your desired parameters, the encoder.save_encoder() function will save a binary file containing your encoder state.
from niml.encoder import encoder
num_features=len(data.columns)-1
# Enter encoder parameter
my_encoder = encoder.Encoder(set_bits=3, sparsity=0.10,
field_types = ["N"]*num_features, # 4 numeric features
cyclic_flags=[False]*num_features, # None of the fields are cyclic
spans = [0]*num_features, # Use simple/basic encoding bit-patterns
cat_overlaps = [0]*num_features, # N/A, data is numeric, not categorical. Set all features to 0
cat_values=[None]*num_features, # N/A, data is numeric, not categorical. Set all features to None
)
# Configure the encoder according to the training dataset's distribution
my_encoder.config_encoder(input_data=train)
# Save the encoder state
my_encoder.save_encoder("my_encoder_obj.bin")
Here, we're saving the file as "my_encoder_obj.bin" and we can retrieve the exact encoder configuration at any future point in time.
Loading an Encoder State
Now that we have our encoder state saved as a binary file, let's load it into an empty encoder object.
# Create an empty encoder object
loaded_encoder = encoder.Encoder()
# Populate the new encoder object with the values from the binary file
loaded_encoder.load_encoder("my_encoder_obj.bin")
The loaded encoder can now be used to encode any new incoming data.
Saving a Model State
The model.save_model() function should be used when the model.Model object is used to create an NPU and Classifier in a single step. Below we have created a model which we then save as a binary file.
from niml.model import model
new_model = model.Model(
sdr_width = 43,
enc_set_bits = 10,
feat_count = 1,
neurons = 100,
active_neurons = 20,
input_pct = 0.65,
learning = True,
synapse_inc = 15,
synapse_dec = 3,
activity_reset_cnt = 30,
seed = 123,
boost_max = 0.9,
boost_str = 2,
boost_tbl_size = 5,
boost_tbl_step = 0.01,
history_depth=150,
subclass_thresh=0.4,
min_overlap=0.0,
)
We'll save the binary model file as "my_model_obj.bin"
new_model.save_model("my_model_obj.bin")
Now we have a binary file saved that contains all the internal values for our model in its state.
Loading a Model State From a Binary File
To load the model.Model object, specify the binary file as the desired model_state within the model.Model function as shown below. We'll use the binary file that we saved above.
loaded_model = model.Model(model_state="my_model_obj.bin")
Now the model is ready to be used to perform further training, run evaluate, or run predict.
Saving an NPU State
If you are working with the NPU object directly (instead of creating a model object), you'll want use the save_pooler_binary() function on the SpatialPooler object. Here, we construct an NPU that we want to save.
from niml.model.nispooler import sp_pooler_c
# Build a NPU object
new_NPU = sp_pooler_c.SpatialPooler(
# Encoder/Data parameters
sdr_width=43,
enc_set_bits=10,
feat_count=1,
# NPU
neurons=100,
active_neurons=20,
input_pct=0.65,
learning=True,
synapse_inc=15,
synapse_dec=3,
activity_reset_cnt=30,
decay_cnt_target=50,
seed=123,
# Boosting
boost_max=0.9,
boost_str=2,
boost_tbl_size=5,
boost_tbl_step=0.01,
)
Next, we'll save the binary file as "my_NPU_obj.bin".
new_NPU.save_pooler_binary("my_NPU_obj.bin")
Now we have a file that, when loaded will populate the exact internal values of the NPU so that a trained model state can be retrieved.
Loading a NPU State From a Binary File
To load a previously saved NPU state, first construct a new NPU object and define the pooler_state file you would like to load. We'll used the NPU that we saved from the code above.
loaded_NPU = sp_pooler_c.SpatialPooler(pooler_state="my_NPU_obj.bin")
From here, the loaded NPU has the same state as before and can be used where left off.