PyANN
Python wrapper for the libann neural network library with a Keras-like API.
Features
- Keras-style API: Familiar
Sequentialmodel withadd(),fit(),predict() - Multiple optimizers: SGD, Momentum, RMSProp, AdaGrad, Adam
- Activation functions: Sigmoid, ReLU, LeakyReLU, Tanh, Softsign, Softmax
- Loss functions: MSE, Categorical Cross-Entropy
- Learning rate schedulers: Step decay, Exponential decay, Cosine annealing
- Hyperparameter tuning: Grid search, Random search, Bayesian optimization, TPE
- NumPy optional: Works with Python lists, optimized for NumPy arrays
- Model persistence: Save/load in text or binary format, ONNX export/import
- Network visualization: Export architecture as PIKCHR diagrams (renders to SVG)
- Regularization: L1 and L2 (weight decay) regularization, dropout
- Evaluation: Accuracy scoring, confusion matrix with MCC
- Data utilities: CSV loading, normalization, one-hot encoding, train/val splitting
- Hardware acceleration: BLAS-accelerated CPU everywhere (Accelerate on macOS, OpenBLAS on Linux and Windows), plus optional GPU inference and training via Metal (macOS) or CUDA
Installation
pip install pylibann
The PyPI package is called pylibann, but you import it as pyann. (The unrelated pyann project on PyPI is a different package with the same module name, so don't install both in one environment.)
Pre-built wheels include the native library, so no compiler is needed:
| Platform | BLAS | GPU |
|---|---|---|
| macOS (Apple silicon, 12+) | Accelerate | Metal |
| Linux x86_64 and aarch64 (glibc, manylinux2014+) | OpenBLAS | - |
| Windows x86_64 | OpenBLAS | - |
On other platforms pip builds from source, which needs CMake and a C compiler (see below). NumPy is optional: pip install "pylibann[numpy]".
Building from source
git clone --recurse-submodules https://github.com/mseminatore/pyann.git
cd pyann
pip install -e ".[dev]" # builds the native library with CMake
pytest
The build picks the same acceleration as the wheels. On Linux and Windows it downloads the prebuilt OpenBLAS from the scipy-openblas32 package. Choose other options by passing CMake flags through CMAKE_ARGS:
CMAKE_ARGS="-DUSE_CUDA=ON" pip install -e . # NVIDIA CUDA (Linux/Windows)
CMAKE_ARGS="-DUSE_CBLAS=ON" pip install -e . # CBLAS from /opt/cblas
CMAKE_ARGS="-DUSE_BLAS=ON" pip install -e . # system OpenBLAS from /opt/OpenBLAS
CMAKE_ARGS="-DUSE_METAL=OFF -DUSE_ACCELERATE=OFF" pip install -e . # plain CPU build
| CMake option | Meaning |
|---|---|
USE_ACCELERATE |
Apple Accelerate (macOS; default there) |
USE_METAL |
Apple Metal GPU backend (macOS; default there) |
USE_SCIPY_OPENBLAS |
OpenBLAS from scipy-openblas32 (Linux/Windows; default there) |
USE_BLAS |
OpenBLAS installed at /opt/OpenBLAS |
USE_CBLAS |
CBLAS installed at /opt/cblas |
USE_CUDA |
NVIDIA CUDA GPU backend |
python build_lib.py [--accelerate | --scipy-openblas | --cblas | --blas] [--metal] [--cuda] [--clean] builds just the shared library into src/pyann/lib/ without installing, which is handy when working on the C side. Set PYANN_LIB_PATH to load a library from another location.
Check what a given install was built with:
import pyann
pyann.backend_info() # {'blas': 'accelerate', 'gpu': 'metal', 'gpu_active': None, ...}
Quick Start
from pyann import Sequential, Dense, Adam, Loss
# Create model
model = Sequential(optimizer=Adam(lr=0.001), loss=Loss.MSE)
model.add(Dense(128, activation='relu', input_shape=(784,)))
model.add(Dense(64, activation='relu'))
model.add(Dense(10, activation='softmax'))
# Train
model.fit(X_train, y_train, epochs=10, batch_size=32)
# Predict
predictions = model.predict(X_test)
# Evaluate
accuracy = model.evaluate(X_test, y_test)
print(f"Accuracy: {accuracy:.2%}")
Examples
XOR Problem
from pyann import Sequential, Dense
# XOR data
X = [[0, 0], [0, 1], [1, 0], [1, 1]]
y = [[0], [1], [1], [0]]
model = Sequential()
model.add(Dense(4, activation='relu', input_shape=(2,)))
model.add(Dense(1, activation='sigmoid'))
model.fit(X, y, epochs=1000, batch_size=4)
print(model.predict(X))
With NumPy
import numpy as np
from pyann import Sequential, Dense
X = np.random.randn(1000, 20).astype(np.float32)
y = (X.sum(axis=1) > 0).astype(np.float32).reshape(-1, 1)
model = Sequential()
model.add(Dense(32, activation='relu', input_shape=(20,)))
model.add(Dense(16, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
model.fit(X, y, epochs=50)
Learning Rate Scheduling
from pyann import Sequential, Dense
from pyann.callbacks import CosineAnnealing
model = Sequential()
model.add(Dense(64, activation='relu', input_shape=(10,)))
model.add(Dense(1, activation='sigmoid'))
scheduler = CosineAnnealing(T_max=100, min_lr=0.0001)
model.fit(X, y, epochs=100, lr_scheduler=scheduler)
Early Stopping
from pyann.callbacks import EarlyStopping
stopping = EarlyStopping(patience=10, min_delta=0.0001)
model.fit(X, y, epochs=500, callbacks=[stopping])
Hyperparameter Tuning
from pyann.hypertune import RandomSearch, HyperparamSpace
from pyann.utils import split_data
# Split data
X_train, y_train, X_val, y_val = split_data(X, y, train_ratio=0.8)
# Define search space
space = HyperparamSpace(
learning_rate=(0.0001, 0.01),
batch_sizes=[32, 64, 128],
hidden_layers=(1, 3),
layer_sizes=[64, 128, 256],
)
# Run search
search = RandomSearch(space, n_trials=20)
best, results = search.run(
X_train, y_train, X_val, y_val,
input_size=784, output_size=10
)
# Create best model
model = search.create_model(best, input_size=784, output_size=10)
TPE Hyperparameter Search
from pyann.hypertune import TPESearch, HyperparamSpace
space = HyperparamSpace(
learning_rate=(0.0001, 0.01),
batch_sizes=[32, 64, 128],
hidden_layers=(1, 3),
layer_sizes=[64, 128, 256],
)
# TPE uses KDE to model good vs bad configs
search = TPESearch(space, n_trials=50, n_startup=10, gamma=0.25)
best, results = search.run(
X_train, y_train, X_val, y_val,
input_size=784, output_size=10
)
Save and Load
# Save
model.save('model.nna') # Text format
model.save('model.nnb', format='binary') # Binary format
model.export_onnx('model.onnx.json') # ONNX format
# Load
loaded = Sequential.load('model.nna')
loaded = Sequential.load_onnx('model.onnx.json') # From ONNX
Network Visualization
# Export architecture as PIKCHR diagram
model.export_pikchr('network.pikchr')
# Then render to SVG with the pikchr CLI tool:
# pikchr network.pikchr > network.svg
Small networks (≤10 nodes per layer) get a detailed diagram with individual nodes and connections. Larger networks get a simplified box diagram.
Data Utilities
from pyann.utils import load_csv, split_data
from pyann.utils.data import normalize, one_hot_encode
# Load CSV data
data, rows, cols = load_csv('data.csv', has_header=True)
# Normalize features
X_norm, mean, std = normalize(X)
# One-hot encode labels
y_encoded = one_hot_encode(labels, num_classes=10)
# Split into train/validation sets
X_train, y_train, X_val, y_val = split_data(X, y, train_ratio=0.8)
API Reference
Sequential
Sequential(layers=None, optimizer=None, loss=Loss.MSE, name=None)
Methods:
add(layer)- Add a layercompile(optimizer, loss, learning_rate, weight_decay, l1_regularization)- Configure trainingfit(x, y, epochs, batch_size, ...)- Train the modelpredict(x)- Generate predictionsevaluate(x, y)- Compute accuracyconfusion_matrix(x, y)- Compute TP/FP/TN/FN and MCC (binary classification)save(filepath, format)- Save modelload(filepath, format)- Load model (classmethod)export_onnx(filepath)- Export to ONNX JSON formatload_onnx(filepath)- Load from ONNX JSON (classmethod)export_pikchr(filepath)- Export architecture as PIKCHR diagramexport_learning_curve(filepath)- Export training history as CSVclear_history()- Clear training history to free memoryset_weight_decay(lambda_)- Set L2 regularization coefficientset_l1_regularization(lambda_)- Set L1 regularization coefficientsummary()- Get model summary
Backend
pyann.backend_info() # dict: blas, gpu (compiled in), gpu_active, plus CBLAS details when present
pyann.enable_gpu() # initialize the GPU backend; returns True if one is active
pyann.gpu_enabled() # whether a GPU backend is active
Layers
Dense(units, activation=None, input_shape=None, dropout=0.0)
Input(shape)
Optimizers
SGD(lr=0.05)
Momentum(lr=0.01)
RMSProp(lr=0.001)
AdaGrad(lr=0.01)
Adam(lr=0.001) # Recommended
Loss Functions
Loss.MSE # Mean Squared Error
Loss.CATEGORICAL_CROSS_ENTROPY # For classification
CATEGORICAL_CROSS_ENTROPY needs a softmax output layer (one class per sample) or a sigmoid output layer (binary cross-entropy per output). Training with any other output activation fails.
Activations
Activation.NONE # Linear
Activation.SIGMOID
Activation.RELU
Activation.LEAKY_RELU
Activation.TANH
Activation.SOFTSIGN
Activation.SOFTMAX
Callbacks
StepDecay(step_size, gamma=0.5) # Multiply LR by gamma every step_size epochs
ExponentialDecay(gamma=0.95) # Multiply LR by gamma each epoch
CosineAnnealing(T_max, min_lr=0.0001) # Smooth decay to min_lr over T_max epochs
EarlyStopping(patience=10, min_delta=0.0001) # Stop when loss stops improving
Hyperparameter Tuning
GridSearch(space, lr_steps=3) # Exhaustive grid search
RandomSearch(space, n_trials=50) # Random sampling
BayesianSearch(space, n_trials=50, n_initial=10) # Bayesian optimization
TPESearch(space, n_trials=50, n_startup=10, gamma=0.25) # Tree-structured Parzen Estimator
All accept a HyperparamSpace and return (best_result, all_results) from run().
Hardware Acceleration
The CPU path uses the BLAS the library was built with (see backend_info()["blas"]). GPU use is opt-in:
import pyann
if pyann.enable_gpu(): # True when a GPU backend is compiled in and a device is available
print("Using", pyann.backend_info()["gpu_active"]) # 'metal' or 'cuda'
model.fit(X, y, epochs=10) # trains on the GPU when enabled
model.predict(X) # batch inference on the GPU when enabled
If no GPU backend is built in, or no device is found, enable_gpu() returns False and everything keeps running on the CPU with BLAS, so the same code works everywhere.
Notes:
enable_gpu()applies to the whole process and cannot be undone.- GPU speedups depend on problem size. In an informal test on Apple silicon (batch size 128) Metal sped up batch inference but was several times slower than the CPU for training, which is why it is not enabled automatically. Measure your own workload.
- The macOS wheels include Metal. CUDA is only available when building from source with
USE_CUDA=ON, and has had little testing. predict()runs the whole input as one batch call.
License
MIT License - see LICENSE for details.
The Linux and Windows wheels also bundle OpenBLAS, LAPACK and the GCC runtime libraries (libgfortran, libquadmath) under their own licenses, included in the wheel as pyann/lib/LICENSE-scipy-openblas32.txt.
Metadata
Release files for pylibann 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| pylibann-0.1.0.tar.gz | 167.0 kB | With provenance | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| pylibann-0.1.0-py3-none-win_amd64.whl | Python 3 | none | Windows x86-64 | Details |
| pylibann-0.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | Python 3 | none | Linux glibc 2.17+ x86-64 | Details |
| pylibann-0.1.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | Python 3 | none | Linux glibc 2.17+ ARM64 | Details |
| pylibann-0.1.0-py3-none-macosx_12_0_arm64.whl | Python 3 | none | macOS 12.0+ ARM64 | Details |
Total release size: 25.4 MB
Release files / pylibann-0.1.0.tar.gz
| Download URL | pylibann-0.1.0.tar.gz |
|---|---|
| Size | 167.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a0bdb90578228cc23b7c8b90e8d5efaa32c99afea533e04917f006adfd1d03a2
|
|
BLAKE2b-256 checksum How to use checksums |
c9b2c2628a4e93e38b19739db8af17cc26fbf1c57f9dce458194035aa0b23709
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.
Transparency logRelease files / pylibann-0.1.0-py3-none-win_amd64.whl
| Download URL | pylibann-0.1.0-py3-none-win_amd64.whl |
|---|---|
| Size | 6.8 MB |
| Tags | Python 3 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
b849bb3d9801c801a7412835045108175ea0125a3431ef645091236d9b18f8e6
|
|
BLAKE2b-256 checksum How to use checksums |
16a3d6fd543f9afe8379fbc6cc878490afa4d0492ae0dfd94d55201133c0bf88
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.
Transparency logRelease files / pylibann-0.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | pylibann-0.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 8.8 MB |
| Tags | Linux glibc 2.17+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
cff3bf9726804af6dcd77e6be5cf663933910815f4ab3d060ce6ad777740cedc
|
|
BLAKE2b-256 checksum How to use checksums |
610c543c5cafd5d40687b7d28d7a82a8166cea7ea977be190db0a17f642c4d9e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.
Transparency logRelease files / pylibann-0.1.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | pylibann-0.1.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 9.5 MB |
| Tags | Linux glibc 2.17+ ARM64 Python 3 |
|
SHA-256 checksum How to use checksums |
1651425fbefa4dbfaaaa85cbf85fb494b6d262ad073f4c2e634edc74e3fce8e0
|
|
BLAKE2b-256 checksum How to use checksums |
ad2d8d2779f7361971d2d20ec5857cc2086ed8e22c070f37d0c631ca45f6d27c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.
Transparency logRelease files / pylibann-0.1.0-py3-none-macosx_12_0_arm64.whl
| Download URL | pylibann-0.1.0-py3-none-macosx_12_0_arm64.whl |
|---|---|
| Size | 106.0 kB |
| Tags | Python 3 macOS 12.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
c04783a35e4d890980075ff4f9bea202895c09095c40b84cf44579cec4d2118a
|
|
BLAKE2b-256 checksum How to use checksums |
1a45869ae08d29b3865a0e8805c2334537a5c2a9ecb69be459fa53dababfed44
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.
Transparency logSecurity for pylibann 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 5 files in this release have been uploaded with provenance metadata.
Attestation for pylibann-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.