Skip to main content

tin_man

A Rust library implementing the WiSARD family of weightless neural networks, plus thermometer-style feature encoders and full model persistence.

WiSARD (Wilkie, Stonham, and Aleksander's Recognition Device) is a pioneering Weightless Neural Network (WNN) model developed in the 1970s and 1980s by Bruce Wilkie, John Stonham, and Igor Aleksander. Unlike traditional neural networks that store knowledge in synaptic weights, WiSARD uses Random Access Memory (RAM) nodes to store learned patterns directly in lookup tables.

Igor Aleksander is an emeritus professor of Neural Systems Engineering in the Department of Electrical and Electronic Engineering at Imperial College London. He worked in artificial intelligence and neural networks and advised my advisor, Felipe Maia Galvão França, who taught me the simplicity and power of WNNs.

Felipe's PhD dissertation covers two of his research passions: Scheduling by Edge Reversal (SER) and WNNs. He has advised a prolific group of researchers on both themes (BTW, my Master's, for instance, extended SER with hibernation) and has co-authored more than fifty published manuscripts in the WNN research field, reflecting his lasting contribution to it.

This Rust library is named after the Tin Man, also known as the Tin Woodman or Nick Chopper — a fictional character created by L. Frank Baum in his 1900 novel The Wonderful Wizard of Oz. He is a sentient being made entirely of metal who seeks a heart to restore his capacity for emotion. As an engineer, I'd like to remind you: tin never, ever rusts.

Models

Model Purpose
Wisard Standard multi-class classification
ClusWisard Classification with multiple clusters per class
RegressionWisard Continuous-value regression
ClusRegressionWisard Regression with multiple clusters per group

Bloom filter variants

For large address_size values, an exact RAM node needs 2^address_size counters — most of which are never visited. The Bloom-filter-backed variants below replace each RAM's exact address table with a compact, multi-hash counting structure, trading a small, tunable false-positive rate for dramatically lower memory use.

Model Purpose Backing structure
BloomWisard Wisard-equivalent classification Counting Bloom filter per RAM (bloom_size counters, num_hashes hash functions)
BloomClusWisard ClusWisard-equivalent, multiple Bloom-backed clusters per class Same as BloomWisard, one filter set per cluster
BloomRegressionWisard RegressionWisard-equivalent continuous-value regression Count-Min-Sketch-style dual sum/count Bloom structure per RAM

Every Bloom model exposes memory_bytes() so you can directly measure the memory savings against an equivalent exact model, and accepts a parallel: bool constructor flag (where applicable) to switch classification between sequential and rayon-parallelized execution.

Encoders

Encoder Bin placement
LinearThermometer Uniform across [min, max]
GaussianThermometer Concentrated near the mean (normal CDF)
DistributiveThermometer Quantile-based, fit from data
KernelCanvas Variable-length sequences of points into a fixed-size binary canvas via random kernels

Project layout

tin_man/
├── src/ Core library (models, RAMs, encoders, persistence, Bloom variants)
├── benches/ Criterion throughput benchmarks
├── examples/ Standalone runnable usage examples
├── tests/ Integration tests (cargo test)
├── tin_man_py/ Python bindings (PyO3 + maturin)
├── tin_manR/ R bindings (extendr + rextendr)
├── scripts/ Python visualization utilities (mental images, retina mapping)
└── README.md

benches/

Benchmarks are run with Criterion and measure training and classification/prediction throughput (operations per second) for all models:

File What it measures
wisard_bench.rs Training and classification throughput for Wisard, ClusWisard, RegressionWisard, and ClusRegressionWisard, plus a classification throughput sweep across different address_size values
bloom_wisard_bench.rs Training and classification throughput for BloomWisard, BloomClusWisard, and BloomRegressionWisard, plus a comparison sweep of bloom_size/num_hashes against exact-RAM throughput and memory usage

Run all benchmarks with:

cargo bench

Criterion prints per-operation timing and throughput (e.g. Kelem/s) directly in the terminal, and generates an interactive HTML report at target/criterion/report/index.html.

examples/

Runnable, self-contained examples demonstrating end-to-end usage of each model and encoder. Run any example with:

cargo run --example <name>
Example Demonstrates
wisard_basic Training and classifying with Wisard on binary-encoded input
clus_wisard_basic Handling heterogeneous sub-patterns within a class using ClusWisard
regression_wisard_basic Continuous-value prediction with RegressionWisard
clus_regression_wisard_basic Multi-cluster regression with ClusRegressionWisard and grouped predictions
thermometer_encoding Fitting and applying LinearThermometer, GaussianThermometer, and DistributiveThermometer to continuous features
persistence Saving and loading trained models via FileFormat::Json and FileFormat::Binary
kernel_canvas_timeseries Classifying variable-length 2D strokes (diagonal vs. circular) via KernelCanvas + Wisard
bloom_iris Classifying the Iris dataset with BloomWisard and BloomClusWisard, sequentially trained so that classes are discovered incrementally (one class trained initially, two more discovered on the fly)

tests/

Integration tests exercising the public API of all models — training, classification/prediction correctness, edge cases (untrained models, input size mismatches), bleaching vs. binary mode consistency, and Bloom-filter false-positive-rate sanity checks. Run with:

cargo test

scripts/

Python utilities (using plotnine) for visualizing trained models as PNGs:

Script What it renders
tin_man_mental_image.py DRASiW-style "mental image" per class for an exact Wisard model, projecting RAM counter values back onto retina bit positions
tin_man_bloom_mental_image.py Same mental-image visualization for a BloomWisard model, reconstructing estimated per-address counts from the Bloom filter's hashed counters before projecting
tin_man_mapping.py Visualizes the retina-to-RAM mapping, labeling each pixel with its assigned RAM node id and address bit index

Installation

Add to your Cargo.toml:

[dependencies]
tin_man = { path = "path/to/tin_man" }

Quick example

use tin_man::{Wisard, encoders::LinearThermometer};

fn main() {
    let data = vec![1.2, 3.4, 2.1, 5.6, 4.3];
    let encoder = LinearThermometer::fit(&data, 8);

    let mut w = Wisard::new(8, 4, 0.1, true, false);
    w.train(&encoder.encode(1.2), "low");
    w.train(&encoder.encode(5.6), "high");

    let (label, confidence) = w.classify(&encoder.encode(1.5)).unwrap();
    println!("{label} ({confidence:.2})");
}

Persistence

All models support saving/loading via FileFormat::Json (readable) or FileFormat::Binary (compact):

use tin_man::{FileFormat, Wisard};

let w = Wisard::new(8, 4, 0.1, true, false);
w.save_to_file("model.json", FileFormat::Json).unwrap();
let w2 = Wisard::load_from_file("model.json", FileFormat::Json).unwrap();

Python bindings

See tin_man_py/README.md for installing and using this library from Python via PyO3/maturin.

Generating docs

cargo doc --open --no-deps

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tin_man_py-0.5.1.tar.gz (48.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tin_man_py-0.5.1-cp313-cp313-macosx_11_0_arm64.whl (403.9 kB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

File details

Details for the file tin_man_py-0.5.1.tar.gz.

File metadata

  • Download URL: tin_man_py-0.5.1.tar.gz
  • Upload date:
  • Size: 48.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.14.1

File hashes

Hashes for tin_man_py-0.5.1.tar.gz
Algorithm Hash digest
SHA256 bbd0f32b7bfeab29aaae1e080e613c7f5ecf38e3c043ee2e99354f1cec777b39
MD5 c2389162964e7dcc1db08f1230631b55
BLAKE2b-256 6dc1ff49c775dd8d548d3e7ee068ac62335e4607304e478e161783cd2c18571d

See more details on using hashes here.

File details

Details for the file tin_man_py-0.5.1-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for tin_man_py-0.5.1-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 5d3174a2e88133ee46d0e068e987053aacb909f7fd039b9dc8e80ddd47338756
MD5 df3830b0c0716f80747735b68ad9c49f
BLAKE2b-256 b734be2a2c35693f2c047f16f59a8a98dcca5a076a3f6ca413e48b92f119bcf6

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.5.1 This release

2 files

0.5.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page