Skip to main content

A compact define-by-run deep learning framework written in Python

Project description

Pinenut

PyPI Python Tests License

English | 简体中文

Pinenut is a compact, define-by-run deep learning framework written in Python. It provides automatic differentiation, neural-network modules, optimization algorithms, and a shared NumPy/CuPy API for CPU and NVIDIA GPU execution. Its small codebase is designed to be easy to read, experiment with, and extend.

Highlights

  • Dynamic computational graphs with first- and higher-order gradients
  • A consistent Module, Parameter, and Optimizer interface
  • Common layers, activations, losses, datasets, and optimizers
  • NumPy execution on CPU and optional CuPy acceleration on NVIDIA GPUs
  • Model state dictionaries and synchronous multi-GPU training
  • Pure Python implementation suitable for learning and small experiments

Requirements

  • Python 3.8 or later
  • NumPy 1.20 or later
  • Optional GPU support: a compatible NVIDIA driver and exactly one supported CuPy package

Installation

Install the latest release from PyPI:

python -m pip install --upgrade pinenut

Or install the current source tree in editable mode:

git clone https://github.com/pinenuthome/pinenut.git
cd pinenut
python -m pip install -e .

For NVIDIA GPUs, install the extra matching your CUDA major version:

# CUDA 12.x
python -m pip install "pinenut[gpu-cu12]"

# CUDA 13.x
python -m pip install "pinenut[gpu-cu13]"

Install only one CuPy distribution in an environment. For virtual-environment setup, distribution-specific prerequisites, CUDA troubleshooting, and a real two-GPU check, see the Linux installation guide.

Automatic differentiation

Build a dynamic graph and differentiate a scalar result:

import numpy as np

import pinenut as pn

x = pn.tensor(np.array([1.0, 2.0, 3.0]))
loss = pn.sum(x ** 2)
loss.backward()

print(loss.data)    # 14.0
print(x.grad.data)  # [2. 4. 6.]

Set create_graph=True when a later computation needs to differentiate the resulting gradient:

x = pn.tensor(3.0)
y = x ** 2
y.backward(create_graph=True)

first_derivative = x.grad
x.zero_grad()
first_derivative.backward()
print(x.grad.data)  # 2.0

Neural-network training

Modules expose parameters to optimizers and use explicit training and evaluation modes:

import numpy as np

import pinenut as pn
from pinenut import nn, optim
from pinenut.nn import functional as F

model = nn.Sequential(
    nn.Linear(2, 32),
    nn.ReLU(),
    nn.Dropout(0.1),
    nn.Linear(32, 3),
)
optimizer = optim.Adam(model.parameters(), lr=0.001)

inputs = pn.tensor(np.random.randn(8, 2))
targets = pn.tensor(np.random.randint(0, 3, size=8))

model.train()
optimizer.zero_grad()
logits = model(inputs)
loss = F.cross_entropy(logits, targets)
loss.backward()
optimizer.step()

model.eval()
with pn.no_grad():
    predictions = model(inputs)

Available components include Linear, LazyLinear, Sequential, MLP, Embedding, Dropout, SGD, Adagrad, and Adam. SGD accepts an optional momentum value. Classification losses accept unnormalized logits, so the final layer should not apply softmax when used with F.cross_entropy.

Devices

Use the same model and tensor API on CPU and GPU:

device = 'cuda' if pn.cuda.is_available() else 'cpu'
model.to(device)
inputs.to(device)
targets.to(device)

Specific GPUs can be selected with names such as cuda:1. Calling cpu(), cuda(), or to(device) moves a tensor or module in place and returns it.

Saving model state

pn.save(model.state_dict(), 'model_weights.npz')

restored = nn.Sequential(
    nn.Linear(2, 32),
    nn.ReLU(),
    nn.Dropout(0.1),
    nn.Linear(32, 3),
)
restored.load_state_dict(pn.load('model_weights.npz'))
restored.eval()

Examples

Run the Spiral visualization to train an MLP and save its decision boundary, metrics, and state dictionary:

python examples/nn/test_spiral.py
python examples/nn/test_spiral.py --animate

Outputs are written to demo_outputs/spiral/. Use --help to configure the dataset, model, training schedule, output directory, and CPU/GPU selection.

Tests

Install the development dependencies and run the CPU-compatible test suite:

python -m pip install -r requirements-dev.txt
python -m pip install -e . --no-deps
python -m unittest discover -s test -v

On a machine with two physical NVIDIA GPUs, run the synthetic multi-GPU smoke test:

CUDA_VISIBLE_DEVICES=0,1 python tools/test_multigpu.py --devices 0,1

To test physical GPUs 2 and 3, remap them to logical devices 0 and 1:

CUDA_VISIBLE_DEVICES=2,3 python tools/test_multigpu.py --devices 0,1

The command prints MULTI-GPU SMOKE TEST PASSED when device placement, training, parameter synchronization, and finite-value checks all succeed.

Project structure

core/       Automatic differentiation and internal implementations
nn/         Neural-network modules and stateless functions
optim/      Optimization algorithms
datasets/   Built-in datasets
utils/      Data loading and utility interfaces
examples/   Runnable training and visualization examples
test/       Unit and regression tests
tools/      Standalone verification utilities
docs/       Installation and usage guides

Contributing

Issues and pull requests are welcome. Please add or update tests for behavioral changes and run the test suite before submitting a pull request.

License

Pinenut is released under the MIT License.

Project details


Download files

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

Source Distribution

pinenut-1.2.0.tar.gz (41.6 kB view details)

Uploaded Source

Built Distribution

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

pinenut-1.2.0-py3-none-any.whl (27.9 kB view details)

Uploaded Python 3

File details

Details for the file pinenut-1.2.0.tar.gz.

File metadata

  • Download URL: pinenut-1.2.0.tar.gz
  • Upload date:
  • Size: 41.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.9

File hashes

Hashes for pinenut-1.2.0.tar.gz
Algorithm Hash digest
SHA256 f6a40eb79e951937c48aadce437a4a02f87c22a2c5dde1a4e58b2ae97fe2d5a0
MD5 5524c0740afef2b24ea508bdb5123958
BLAKE2b-256 dbf12d6a0d85e4481d0a62c59efb4cb6f1d32ed9771f25e8bed1a6d92dac826c

See more details on using hashes here.

File details

Details for the file pinenut-1.2.0-py3-none-any.whl.

File metadata

  • Download URL: pinenut-1.2.0-py3-none-any.whl
  • Upload date:
  • Size: 27.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.9

File hashes

Hashes for pinenut-1.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4d36ca268d7865ea66f78ca0e6fd66554a76702ca169c24e855d51771cc1c042
MD5 0dce66185fcc81415044b00196737184
BLAKE2b-256 b77df78899790dc307c1070b1f58f065112e779861bf142692b5c36178de83cb

See more details on using hashes here.

Supported by

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