Saving and loading

The following applications demonstrate how to save and load trained JABBA models and their learned symbolic dictionaries for later use, deployment, or sharing. It works for all ABBA variants (fABBA, JABBA, QABBA). Now we foucs on JABBA as an example.

After fit() or fit_transform(), JABBA stores everything needed for perfect reconstruction in the lightweight dataclass:

jabba.parameters   # -> Model(centers=..., alphabets=...)

These two arrays are your learned symbolic dictionary / codebook — they completely define the compression and reconstruction behavior.

Inspecting the Learned Dictionary

from fABBA import JABBA
import numpy as np
import pandas as pd

data = np.random.randn(100, 6, 500)
jabba = JABBA(tol=0.05, verbose=0).fit(data)

df = pd.DataFrame({
    'symbol': jabba.parameters.alphabets,
    'avg_length': jabba.parameters.centers[:, 0].round(2),
    'avg_increment': jabba.parameters.centers[:, 1].round(4)
}).sort_values('avg_increment')

print(df.head(10))

# Example output # symbol avg_length avg_increment # 7 g 15.21 -0.0872 # 3 c 9.84 -0.0431 # 0 A 22.10 -0.0012 # 1 a 11.35 0.0198 # 5 e 18.67 0.0564

Loading a Trained Dictionary for Inference / Deployment

import joblib
import numpy as np
from fABBA import JABBA, Model

# Load dictionary
params = joblib.load('jabba_dictionary.joblib')           # -> Model instance
# or
# data = np.load('jabba_dictionary.npz')
# params = Model(centers=data['centers'], alphabets=data['alphabets'])

# Create a "frozen" JABBA instance that only transforms
jabba_deploy = JABBA(tol=0.05, verbose=0)   # tol must match training!
jabba_deploy.parameters = params                     # inject learned vocabulary

# Now symbolize new data without re-fitting
X_new = np.random.randn(20, 6, 500)
symbols_new, start_values = jabba_deploy.transform(X_new)
X_reconstructed = jabba_deploy.inverse_transform(symbols_new, start_values)

Saving the Entire Model (including normalization & shape info)

If you also want to preserve standardization parameters (d_norm) and original shape for zero-code reconstruction:

joblib.dump(jabba, 'jabba_full_model.joblib')

# Later
jabba_loaded = joblib.load('jabba_full_model.joblib')
# Can still call fit new data or transform
symbols = jabba_loaded.transform(new_data)

Production Deployment Example (FastAPI)

# app.py
import joblib
import numpy as np
from fastapi import FastAPI
from fABBA import JABBA

app = FastAPI()
jabba = joblib.load('jabba_full_model.joblib')  # loaded once at startup

@app.post("/symbolize")
async def symbolize(payload: dict):
    arr = np.array(payload["data"])  # (n_samples, n_channels, length)
    symbols, starts = jabba.transform(arr)
    return {"symbols": symbols}

@app.post("/reconstruct")
async def reconstruct(payload: dict):
    symbols = payload["symbols"]
    starts = payload.get("starts")
    recon = jabba.inverse_transform(symbols, starts)
    return {"data": recon.tolist()}

Visualizing the Learned Prototypes

import matplotlib.pyplot as plt
import seaborn as sns

centers = jabba.parameters.centers
symbols = jabba.parameters.alphabets

plt.figure(figsize=(10, 6))
scatter = plt.scatter(centers[:, 0], centers[:, 1],
                    c=range(len(symbols)), cmap='tab20', s=120, edgecolors='k')
for i, sym in enumerate(symbols):
    plt.text(centers[i, 0] + 0.3, centers[i, 1], sym,
             fontsize=14, weight='bold')

plt.xlabel('Average segment length', fontsize=12)
plt.ylabel('Average increment (trend)', fontsize=12)
plt.title('JABBA Learned Symbolic Dictionary', fontsize=16)
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('jabba_dictionary.pdf', dpi=300)
plt.show()

Complete Persistent Package (Most Robust)

joblib.dump({
    'tol'              : jabba.tol,
    'scl'              : jabba.scl,
    'd_norm'           : jabba.d_norm,           # (mean, std) if normalized
    'recap_shape'      : jabba.recap_shape,      # for recast_shape()
    'centers'          : jabba.parameters.centers,
    'alphabets'        : jabba.parameters.alphabets,
}, 'jabba_complete_package.joblib')

Summary – What You Really Need to Save

Only these two objects are required for 100% lossless reconstruction:

jabba.parameters.centers      -> (K, 2) float64 # for QABBA, it is of integer type
jabba.parameters.alphabets    -> (K,) strings
  • the original tol and scl values

With just these, you can reconstruct the original time series perfectly in any language or environment (Python, C++, Java, MATLAB, etc.).

You now have full control over JABBA’s symbolic dictionary — ready for industrial deployment, cross-language use, paper reproducibility, and model sharing.

Happy symbolizing!