Skip to main content

Make PyTorch models using generator functions.

Project description

Torch Yield

Last release Python version Documentation Test status Test coverage Last commit

Torch Yield is a library that makes it easier to create custom models in PyTorch. The key idea is to write models as generator functions, where each module is yielded in the order it should be invoked. This approach leads to very modular, flexible, and succinct code. In turn, this makes it much easier and faster to experiment with different model architectures. Here's an example of what this might look like:

import torch
import torch.nn as nn
import torchyield as ty

def conv_relu(
        in_channels,
        out_channels,
        kernel_size=3,
        stride=1,
        padding=0,
):
    yield nn.Conv2d(
            in_channels=in_channels,
            out_channels=out_channels,
            kernel_size=kernel_size,
            stride=stride,
            padding=padding,
    )
    yield nn.ReLU()

def conv_relu_pool(
        pool_size=3,
        pool_stride=2,
        **hparams,
):
    yield from conv_relu(**hparams)
    yield nn.MaxPool2d(
            kernel_size=pool_size,
            stride=pool_stride,
    )

def linear_relu_dropout(
        in_features,
        out_features,
        drop_rate=0.5,
):
    yield nn.Linear(
            in_features=in_features,
            out_features=out_features,
    )
    yield nn.ReLU()
    yield nn.Dropout(p=drop_rate)

def alexnet():
    yield from conv_relu_pool(
            in_channels=3,
            out_channels=96,
            kernel_size=11,
            stride=4,
    )
    yield from conv_relu_pool(
            in_channels=96,
            out_channels=256,
            kernel_size=5,
            padding=2,
    )
    yield from conv_relu(
            in_channels=256,
            out_channels=384,
            padding=1,
    )
    yield from conv_relu(
            in_channels=384,
            out_channels=384,
            padding=1,
    )
    yield from conv_relu_pool(
            in_channels=384,
            out_channels=256,
            padding=1,
    )

    yield nn.Flatten()

    yield from linear_relu_dropout(
            in_features=36 * 256,
            out_features=4096,
    )
    yield from linear_relu_dropout(
            in_features=4096,
            out_features=4096,
    )
    yield nn.Linear(
            in_features=4096,
            out_features=1000,
    )

# Convert the generator into an instance of `torch.nn.Sequential`:
f = ty.module_from_layers(alexnet())

# Demonstrate that the model works, i.e. it can make a prediction 
# given random input:
x = torch.randn(1, 3, 227, 227)
y = f(x)
print(torch.argmax(y))  # tensor(388)

Model visualization

Note how using generators makes it easy to compose complex models from simple building blocks. In particular, this example starts by defining a simple convolution-ReLU layer. It then uses that layer to define a slightly more complex convolution-ReLU-pool layer. Those two layers are ultimately used, along with another simple linear-ReLU-dropout layer, to define the full AlexNet model.

It would've been possible to define all the same building blocks as normal PyTorch modules (i.e. without using generators). However, that approach would've been much more verbose. We would've had to create a class for each layer, and then we would've had to worry about getting the hyperparameters from __init__() to forward().

That said, the above example is still pretty verbose. The reason why is that we didn't actually use torchyield much at all! There are two big improvements we can make:

  • All of the "simple" layers we need for this model are provided by torchyield, so we can just import them rather than writing our own functions.
  • The bulk of the code consists of calling the same functions multiple times with different arguments. One of the most important helper functions provided by torchyield is make_layers(), which automates this process.
import torch.nn as nn
import torchyield as ty

def alexnet():
    # `make_layers()` zips together all the keyword arguments 
    # (including any scalar ones), then calls the same factory 
    # function on each set of arguments.  The `channels()` helper 
    # is useful: it breaks a list of channels into separate lists 
    # of input and output channels.  Also note that this factory 
    # function is smart enough to skip the pooling module when the 
    # `pool_size` parameter is 1 (or less).
    yield from ty.make_layers(
            ty.conv2_relu_maxpool_layer,
            **ty.channels([3, 96, 256, 384, 384, 256]),
            kernel_size=[11, 5, 3, 3, 3],
            stride=[4, 1, 1, 1, 1],
            padding=[0, 2, 1, 1, 1],
            pool_size=[3, 3, 1, 1, 3],
            pool_stride=2,
    )

    yield nn.Flatten()

    # `mlp_layer()` is very similar to `make_layers()`.  The only 
    # difference is that instead of using the given factory to 
    # make the last layer, it just makes a plain linear layer. 
    # This is because you typically don't want any nonlinear/ 
    # regularization layers after the last linear layer.
    yield from ty.mlp_layer(
            ty.linear_relu_dropout_layer,
            **ty.channels([36 * 256, 4096, 4096, 1000])
    )

Model visualization

Hopefully you can see how powerful this code is:

  • It only took a few lines to define the whole model.
  • Every hyperparameter is easy to see and modify. This includes more "structural" hyperparameters like the number of layers, and the specific modules used in each layer.
  • The alexnet() function is itself a generator, so it can be used to build more complex models in the same way that we built it.

Installation

Install Torch Yield from PyPI:

$ pip install torchyield

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

torchyield-0.4.0.tar.gz (9.6 kB view details)

Uploaded Source

Built Distribution

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

torchyield-0.4.0-py3-none-any.whl (8.6 kB view details)

Uploaded Python 3

File details

Details for the file torchyield-0.4.0.tar.gz.

File metadata

  • Download URL: torchyield-0.4.0.tar.gz
  • Upload date:
  • Size: 9.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.0.1 CPython/3.12.8

File hashes

Hashes for torchyield-0.4.0.tar.gz
Algorithm Hash digest
SHA256 f8420ea64a7a2ea34d0d55d585ef01912a61da02ee1758c15e80682fb2be1601
MD5 8e63267d683e980f679dc9cdd714240a
BLAKE2b-256 7f9e3ea263215cc00f3dc3832e74162da273c421306aba4f5fc9521ea5c8676f

See more details on using hashes here.

Provenance

The following attestation bundles were made for torchyield-0.4.0.tar.gz:

Publisher: release.yml on kalekundert/torchyield

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file torchyield-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: torchyield-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 8.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.0.1 CPython/3.12.8

File hashes

Hashes for torchyield-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 63c1c7ecdd39e146daedec0dcb428408f39fc6d3c057bd141484192a15d7dcc5
MD5 210a8f7eeb5d20b708425c6aeee08632
BLAKE2b-256 0848ea38a720398f2addc428a44eab5e093034737e17582ca0e9c6932ace5065

See more details on using hashes here.

Provenance

The following attestation bundles were made for torchyield-0.4.0-py3-none-any.whl:

Publisher: release.yml on kalekundert/torchyield

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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