https://github.com/szymonmaszke/torchlayers

Shape and dimension inference (Keras-like) for PyTorch layers and neural networks

https://github.com/szymonmaszke/torchlayers

Science Score: 10.0%

This score indicates how likely this project is to be science-related based on various indicators:

  • CITATION.cff file
  • codemeta.json file
  • .zenodo.json file
  • DOI references
  • Academic publication links
    Links to: arxiv.org
  • Committers with academic emails
  • Institutional organization owner
  • JOSS paper metadata
  • Scientific vocabulary similarity
    Low similarity (12.3%) to scientific vocabulary

Keywords

deep-learning framework inference keras layers library machine-learning pytorch shape sota
Last synced: 5 months ago · JSON representation

Repository

Shape and dimension inference (Keras-like) for PyTorch layers and neural networks

Basic Info
Statistics
  • Stars: 572
  • Watchers: 12
  • Forks: 44
  • Open Issues: 5
  • Releases: 0
Topics
deep-learning framework inference keras layers library machine-learning pytorch shape sota
Created over 6 years ago · Last pushed over 3 years ago
Metadata Files
Readme License

README.md

torchlayers Logo


| Version | Docs | Tests | Coverage | Style | PyPI | Python | PyTorch | Docker | |---------|------|-------|----------|-------|------|--------|---------|--------| | Version | Documentation | Tests | codecov | codebeat badge | PyPI | Python | PyTorch | Docker |

torchlayers is a library based on PyTorch providing automatic shape and dimensionality inference of torch.nn layers + additional building blocks featured in current SOTA architectures (e.g. Efficient-Net).

Above requires no user intervention (except single call to torchlayers.build) similarly to the one seen in Keras.

Main functionalities:

  • Shape inference for most of torch.nn module (convolutional, recurrent, transformer, attention and linear layers)
  • Dimensionality inference (e.g. torchlayers.Conv working as torch.nn.Conv1d/2d/3d based on input shape)
  • Shape inference of custom modules (see examples section)
  • Additional Keras-like layers (e.g. torchlayers.Reshape or torchlayers.StandardNormalNoise)
  • Additional SOTA layers mostly from ImageNet competitions (e.g. PolyNet, Squeeze-And-Excitation, StochasticDepth)
  • Useful defaults ("same" padding and default kernel_size=3 for Conv, dropout rates etc.)
  • Zero overhead and torchscript support

Keep in mind this library works almost exactly like PyTorch originally. What that means is you can use Sequential, define your own networks of any complexity using torch.nn.Module, create new layers with shape inference etc.

See below to get some intuition about library.

Examples

For full functionality please check torchlayers documentation. Below examples should introduce all necessary concepts you should know.

Basic classifier

All torch.nn modules can be used through torchlayers and each module with input shape will be appropriately modified with it's input inferable counterpart.

```python import torchlayers as tl

class Classifier(tl.Module): def init(self): super().init() self.conv1 = tl.Conv2d(64, kernelsize=6) self.conv2 = tl.Conv2d(128, kernelsize=3) self.conv3 = tl.Conv2d(256, kernel_size=3, padding=1) # New layer, more on that in the next example self.pooling = tl.GlobalMaxPool() self.dense = tl.Linear(10)

def forward(self, x):
    x = torch.relu(self.conv1(x))
    x = torch.relu(self.conv2(x))
    x = torch.relu(self.conv3(x))
    return self.dense(self.pooling(x))

Pass model and any example inputs afterwards

clf = tl.build(Classifier(), torch.randn(1, 3, 32, 32)) ```

Above torchlayers.Linear(out_features=10) is used. It is "equivalent" to original PyTorch's torch.nn.Linear(in_features=?, out_features=10) where in_features will be inferred from example input input during torchlayers.build call.

Same thing happens with torch.nn.Conv2d(in_channels, out_channels, kernel_size, ...) which can be replaced directly by tl.Conv2d(out_channels, kernel_size, ...).

Just remember to pass example input through the network!

Simple image and text classifier in one!

  • We will use single "model" for both tasks. Firstly let's define it using torch.nn and torchlayers:

```python import torch import torchlayers as tl

torch.nn and torchlayers can be mixed easily

model = torch.nn.Sequential( tl.Conv(64), # specify ONLY outchannels torch.nn.ReLU(), # use torch.nn wherever you wish tl.BatchNorm(), # BatchNormNd inferred from input tl.Conv(128), # Default kernelsize equal to 3 tl.ReLU(), tl.Conv(256, kernel_size=11), # "same" padding as default tl.GlobalMaxPool(), # Known from Keras tl.Linear(10), # Output for 10 classes )

print(model) ```

Above would give you model's summary like this (notice question marks for not yet inferred values):

python Sequential( (0): Conv(in_channels=?, out_channels=64, kernel_size=3, stride=1, padding=same, dilation=1, groups=1, bias=True, padding_mode=zeros) (1): ReLU() (2): BatchNorm(num_features=?, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True) (3): Conv(in_channels=?, out_channels=128, kernel_size=3, stride=1, padding=same, dilation=1, groups=1, bias=True, padding_mode=zeros) (4): ReLU() (5): Conv(in_channels=?, out_channels=256, kernel_size=11, stride=1, padding=same, dilation=1, groups=1, bias=True, padding_mode=zeros) (6): GlobalMaxPool() (7): Linear(in_features=?, out_features=10, bias=True) )

  • Now you can build/instantiate your model with example input (in this case MNIST-like):

python mnist_model = tl.build(model, torch.randn(1, 3, 28, 28))

  • Or if it's text classification you are after, same model could be built with different input shape (e.g. for text classification using 300 dimensional pretrained embedding):

```python

[batch, embedding, timesteps], first dimension > 1 for BatchNorm1d to work

text_model = tl.build(model, torch.randn(2, 300, 1)) ```

  • Finally, you can print both models after instantiation, provided below side by-side for readability (notice different dimenstionality, e.g. Conv2d vs Conv1d after torchlayers.build):

```python # TEXT CLASSIFIER MNIST CLASSIFIER

            Sequential(                       Sequential(
              (0): Conv1d(300, 64)              (0): Conv2d(3, 64)
              (1): ReLU()                       (1): ReLU()
              (2): BatchNorm1d(64)              (2): BatchNorm2d(64)
              (3): Conv1d(64, 128)              (3): Conv2d(64, 128)
              (4): ReLU()                       (4): ReLU()
              (5): Conv1d(128, 256)             (5): Conv2d(128, 256)
              (6): GlobalMaxPool()              (6): GlobalMaxPool()
              (7): Linear(256, 10)              (7): Linear(256, 10)
            )                                 )

```

As you can see both modules "compiled" into original pytorch layers.

Custom modules with shape inference capabilities

User can define any module and make it shape inferable with torchlayers.infer function:

```python # Class defined with infeatures # It might be a good practice to use _ prefix and Impl as postfix # to differentiate from shape inferable version class _MyLinearImpl(torch.nn.Module): def _init(self, infeatures: int, outfeatures: int): super().init_() self.weight = torch.nn.Parameter(torch.randn(outfeatures, infeatures)) self.bias = torch.nn.Parameter(torch.randn(outfeatures))

def forward(self, inputs):
    return torch.nn.functional.linear(inputs, self.weight, self.bias)

MyLinear = tl.infer(_MyLinearImpl)

Build and use just like any other layer in this library

layer =tl.build(MyLinear(out_features=32), torch.randn(1, 64)) layer(torch.randn(1, 64)) ```

By default inputs.shape[1] will be used as in_features value during initial forward pass. If you wish to use different index (e.g. to infer using inputs.shape[3]) use MyLayer = tl.infer(_MyLayerImpl, index=3) as a decorator.

Autoencoder with inverted residual bottleneck and pixel shuffle

Please check code comments and documentation if needed. If you are unsure what autoencoder is you could see this example blog post.

Below is a convolutional denoising autoencoder example for ImageNet-like images. Think of it like a demonstration of capabilities of different layers and building blocks provided by torchlayers.

```python

Input - 3 x 256 x 256 for ImageNet reconstruction

class AutoEncoder(torch.nn.Module): def init(self): super().init() self.encoder = tl.Sequential( tl.StandardNormalNoise(), # Apply noise to input images tl.Conv(64, kernelsize=7), tl.activations.Swish(), # Direct access to module .activations tl.InvertedResidualBottleneck(squeezeexcitation=False), tl.AvgPool(), # shape 64 x 128 x 128, kernelsize=2 by default tl.HardSwish(), # Access simply through tl tl.SeparableConv(128), # Up number of channels to 128 tl.InvertedResidualBottleneck(), # Default with squeeze excitation torch.nn.ReLU(), tl.AvgPool(), # shape 128 x 64 x 64, kernelsize=2 by default tl.DepthwiseConv(256), # DepthwiseConv easier to use # Pass input thrice through the same weights like in PolyNet tl.Poly(tl.InvertedResidualBottleneck(), order=3), tl.ReLU(), # all torch.nn can be accessed via tl tl.MaxPool(), # shape 256 x 32 x 32 tl.Fire(outchannels=512), # shape 512 x 32 x 32 tl.SqueezeExcitation(hidden=64), tl.InvertedResidualBottleneck(), tl.MaxPool(), # shape 512 x 16 x 16 tl.InvertedResidualBottleneck(squeezeexcitation=False), # Randomly switch off the last two layers with 0.5 probability tl.StochasticDepth( torch.nn.Sequential( tl.InvertedResidualBottleneck(squeezeexcitation=False), tl.InvertedResidualBottleneck(squeezeexcitation=False), ), p=0.5, ), tl.AvgPool(), # shape 512 x 8 x 8 )

    # This one is more "standard"
    self.decoder = tl.Sequential(
        tl.Poly(tl.InvertedResidualBottleneck(), order=2),
        # Has ICNR initialization by default after calling `build`
        tl.ConvPixelShuffle(out_channels=512, upscale_factor=2),
        # Shape 512 x 16 x 16 after PixelShuffle
        tl.Poly(tl.InvertedResidualBottleneck(), order=3),
        tl.ConvPixelShuffle(out_channels=256, upscale_factor=2),
        # Shape 256 x 32 x 32
        tl.Poly(tl.InvertedResidualBottleneck(), order=3),
        tl.ConvPixelShuffle(out_channels=128, upscale_factor=2),
        # Shape 128 x 64 x 64
        tl.Poly(tl.InvertedResidualBottleneck(), order=4),
        tl.ConvPixelShuffle(out_channels=64, upscale_factor=2),
        # Shape 64 x 128 x 128
        tl.InvertedResidualBottleneck(),
        tl.Conv(256),
        tl.Dropout(),  # Defaults to 0.5 and Dropout2d for images
        tl.Swish(),
        tl.InstanceNorm(),
        tl.ConvPixelShuffle(out_channels=32, upscale_factor=2),
        # Shape 32 x 256 x 256
        tl.Conv(16),
        tl.Swish(),
        tl.Conv(3),
        # Shape 3 x 256 x 256
    )

def forward(self, inputs):
    return self.decoder(self.encoder(inputs))

```

Now one can instantiate the module and use it with torch.nn.MSELoss as per usual.

python autoencoder = tl.build(AutoEncoder(), torch.randn(1, 3, 256, 256))

Installation

pip

Latest release:

shell pip install --user torchlayers

Nightly:

shell pip install --user torchlayers-nightly

Docker

CPU standalone and various versions of GPU enabled images are available at dockerhub.

For CPU quickstart, issue:

shell docker pull szymonmaszke/torchlayers:18.04

Nightly builds are also available, just prefix tag with nightly_. If you are going for GPU image make sure you have nvidia/docker installed and it's runtime set.

Contributing

If you find issue or would like to see some functionality (or implement one), please open new Issue or create Pull Request.

Owner

  • Name: Szymon Maszke
  • Login: szymonmaszke
  • Kind: user
  • Location: Poland, Kraków
  • Company: InovIntell

CTO @ InovIntell | ML | DL | Ops

GitHub Events

Total
  • Issues event: 1
  • Watch event: 4
Last Year
  • Issues event: 1
  • Watch event: 4

Committers

Last synced: 9 months ago

All Time
  • Total Commits: 96
  • Total Committers: 4
  • Avg Commits per committer: 24.0
  • Development Distribution Score (DDS): 0.104
Past Year
  • Commits: 0
  • Committers: 0
  • Avg Commits per committer: 0.0
  • Development Distribution Score (DDS): 0.0
Top Committers
Name Email Commits
vyzyv v****z@p****m 86
Szymon Maszke s****e@p****m 8
Szymon Maszke g****b@m****o 1
Devanshu Desai 3****i 1
Committer Domains (Top 20 + Academic)

Issues and Pull Requests

Last synced: 6 months ago

All Time
  • Total issues: 16
  • Total pull requests: 2
  • Average time to close issues: 2 days
  • Average time to close pull requests: 6 months
  • Total issue authors: 15
  • Total pull request authors: 2
  • Average comments per issue: 1.25
  • Average comments per pull request: 0.5
  • Merged pull requests: 2
  • Bot issues: 0
  • Bot pull requests: 0
Past Year
  • Issues: 1
  • Pull requests: 0
  • Average time to close issues: N/A
  • Average time to close pull requests: N/A
  • Issue authors: 1
  • Pull request authors: 0
  • Average comments per issue: 0.0
  • Average comments per pull request: 0
  • Merged pull requests: 0
  • Bot issues: 0
  • Bot pull requests: 0
Top Authors
Issue Authors
  • soulhi-vz (2)
  • j-adamczyk (1)
  • ImYoungUn (1)
  • m-rph (1)
  • goingtosleep (1)
  • pengzhangzhi (1)
  • kogolobo (1)
  • mycpuorg (1)
  • chrislemke (1)
  • MatthieuBizien (1)
  • pranjalchaubey (1)
  • veritas9872 (1)
  • va1shn9v (1)
  • triwahyuu (1)
  • arita37 (1)
Pull Request Authors
  • devanshuDesai (1)
  • szymonmaszke (1)
Top Labels
Issue Labels
bug (1) enhancement (1)
Pull Request Labels

Dependencies

docs/code/requirements.txt pypi
  • javasphinx *
  • matplotlib *
  • sphinx *
setup.py pypi
  • torch >=1.3.0