Saving the Whole Prediction Procedure
Weights alone do not reproduce a prediction. Botie also needs feature order, fitted preparation, and the rules connecting them.
13 sections · 4 questions · 2 coding challenges
The arrow keys move between sections too.
The Model Is One Part of the System
BOTIE
Persistence documentation also distinguishes numerical model state from its execution environment. Our small JSON example makes the state explicit; it does not promise that arbitrary model objects can be safely or portably loaded.
Why Did the Saved Model Give a Different Answer?
Botie saves a model’s weights and loads them tomorrow. The code runs, but predictions change because the new process prepares inputs differently.
Suppose we save the model weights but forget the training mean used to centre its inputs. We can reload the weights and still get different predictions. We need to save the fitted preparation alongside the model, with a description of the expected features. Then we can check whether the loaded procedure reproduces known examples.
The supplied state represents already fitted preprocessing and model parameters.
Step 1 of 4
Retain training preparation
The feature order is temperature, then humidity.
| Feature | Training mean | Training scale |
|---|---|---|
| Feature 1 | 10 | 2 |
| Feature 2 | 20 | 5 |
Feature 1
- Training mean
- 10
- Training scale
- 2
Feature 2
- Training mean
- 20
- Training scale
- 5
Step 2 of 4
Prepare one new record
Use saved values without refitting.
| Feature | New row | Prepared row |
|---|---|---|
| Feature 1 | 12 | 1 |
| Feature 2 | 25 | 1 |
Feature 1
- New row
- 12
- Prepared row
- 1
Feature 2
- New row
- 25
- Prepared row
- 1
Step 3 of 4
Apply saved model state
Weights and intercept complete the procedure.
Prepared row: [1, 1] Saved weights: [3, −1] Saved intercept: 2 Prediction = (1 × 3) + (1 × −1) + 2 = 4
Step 4 of 4
Saved coefficients also need saved feature names
A model can accept the right number of values while receiving them in the wrong order. Save the feature order with the numerical state, then assemble every later row by those names.
| Record | First model input: temperature | Second model input: humidity |
|---|---|---|
| Correctly assembled | Temperature measurement | Humidity measurement |
| Accidentally reversed | Humidity measurement | Temperature measurement |
Correctly assembled
- First model input: temperature
- Temperature measurement
- Second model input: humidity
- Humidity measurement
Accidentally reversed
- First model input: temperature
- Humidity measurement
- Second model input: humidity
- Temperature measurement
A saved model includes the transformation its inputs depend on
The same retained transformation and model state produce the same numerical procedure.
Can the saved procedure reproduce the prediction?
The training reference and model coefficients are both part of the fitted procedure. Change an incoming value and apply those retained quantities in the original order.
BOTIE
Prediction from the restored procedure
4
Follow the operations
1. Raw feature vector
- 012
- 125
2. Training means
- 010
- 120
3. Subtract
- 02
- 15
4. Positive training scales
- 02
- 15
5. Take positive reciprocals
- 00.5
- 10.2
6. Multiply
- 01
- 11
7. Saved weights
- 03
- 1-1
8. Dot product
2
9. Saved bias
2
10. Add
4
11. Result
4
Feature order and units must match the saved contract. This example is a linear predictor, not arbitrary model serialisation.
1. List Every Fitted Quantity
A standardising linear predictor needs feature names and order, training means, positive scales, weights, and intercept. A categorical pipeline may also need vocabulary, unknown-category rules, and imputation values.
Distinguish fitted values from configuration. Both matter for reproducibility, but fitted values must come only from the training partition.
Keep units and preparation order with the state rather than relying on memory.
2. Apply Preparation Without Learning Again
On a new record, subtract the saved training mean and divide by the saved scale. Do not calculate a fresh mean from each request. That would make the prediction depend on what other records arrived in the batch.
x = [12,25]
Saved mean = [10,20]; scale = [2,5]
Prepared x = [1,1]
Prediction = dot([1,1], [3,-1]) + 2 = 4Inference transforms with retained state; fitting estimates that state.
3. Serialise a Small Inspectable Artifact
For this simple model, JSON can store lists, numbers, feature names, and a schema version. Convert lists back to arrays when loading and validate their shapes and finiteness.
For larger arrays, an array format can be more suitable. Do not load untrusted pickle-based objects: deserialisation can execute code. An artifact format and runtime compatibility policy are part of the system design.
The example round-trips an in-memory JSON string so no filesystem or service setup is needed.
A coefficient expects the scale it was trained on
This one-feature rule was fitted after centring and scaling. Compare its prediction with the result of mistakenly applying the coefficient straight to the raw reading.
import numpy as np
raw = 12.0
saved_mean, saved_scale = 10.0, 2.0
weight, bias = 3.0, 1.0
prepared = (raw - saved_mean) / saved_scale
print(prepared)
print(prepared * weight + bias)
print(raw * weight + bias)1.0
4.0
37.0Saving the coefficient without its preprocessing would silently change the numerical procedure. Practice saves and restores the complete two-feature state.
4. Check Predictions Before and After Loading
Retain several representative input-output examples, including boundary cases. Compare the original and loaded procedures within a declared tolerance. Also check feature order, runtime versions, and any unsupported operations.
Exact agreement on fixtures does not prove identical behaviour for every input, but it catches common omitted-state and ordering failures before deployment.
Botie’s workshop shows the full numerical pipeline from raw record to prediction.
5. Save What Was Learned and What Was Assumed
A linear predictor may need a feature order, units, imputation values, category vocabulary, scaling statistics, weights and an intercept. Some came from fitting; others came from the input contract. Both affect the answer.
Give the artifact a schema version. A loader should know which fields that version requires and reject unsupported versions explicitly. A model name alone does not specify how an incoming record becomes the array the weights expect.
6. Reload in a Fresh Object and Compare Predictions
Serialising a model is not finished when a file is written. Load the saved representation into a new object, reconstruct its numerical arrays and run fixtures that exercise more than one input.
Keep these fixtures separate from the training objective. They test that storage and loading preserve the procedure, not that the model generalises.
Round-trip a centred linear predictor
The feature order is temperature then humidity, with a saved mean for each.
import numpy as np
import json
artifact = {'schema': 1, 'features': ['temperature','humidity'], 'mean': [10.,50.], 'weight': [2.,.1], 'bias': 3.}
restored = json.loads(json.dumps(artifact))
X = np.array([[12.,60.],[10.,50.]])
def predict(model, X):
return (X-np.array(model['mean']))@np.array(model['weight'])+model['bias']
print(predict(restored, X).tolist())
print(bool(np.allclose(predict(artifact,X), predict(restored,X))))[8.0, 3.0]
TrueThe comparison includes the fitted centring step. Saving weights alone would not reproduce these predictions.
7. An Artifact Needs a Compatible Runtime
A saved representation may depend on library conventions, numerical precision or custom preprocessing code. Record the runtime and code version needed to interpret it. Test a fresh process rather than relying on imports and variables left in a notebook.
For the small model here, an inspectable JSON schema is sufficient. More complex models may require another format. Only load trusted executable serialisations; plain numerical formats reduce that need but still require schema and size checks.
Check yourself
Questions on Parts 1 to 7
Question 1 of 4
What is the prepared row?
Use the information below.
Saved mean [10,20], scale [2,5], new row [12,25].Try it with Botie
Build with Botie
Write and run Python