├── README.md ├── example.ipynb ├── setup.py └── torch_bandpass ├── __init__.py ├── dct.py └── layer.py /README.md: -------------------------------------------------------------------------------- 1 | # torch-bandpass 2 | 3 | This is an implementation of the [Prism layer](https://arxiv.org/abs/2011.04823), a DCT-based bandpass filter suitable for transformer sequence models. 4 | 5 | # Usage 6 | 7 | See [example.ipynb](example.ipynb) for full usage. The basic usage is as follows: 8 | 9 | ```python 10 | seq_len = 512 # number of timesteps per sequence 11 | d_model = 768 # number of feature channels in the transformer 12 | 13 | # Create a Prism layer, which only needs to know about the 14 | # total sequence length and how you want to split up features. 15 | layer = Prism(seq_len, mid_periods=(2, 8, 32, 256)) 16 | 17 | # random [N x T x C] tensor. 18 | input_sequence = torch.randn(BATCH_SIZE, seq_len, d_model) 19 | 20 | # output is the same shape as input_sequence 21 | output_sequence = layer(input_sequence) 22 | ``` 23 | -------------------------------------------------------------------------------- /example.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "language_info": { 4 | "codemirror_mode": { 5 | "name": "ipython", 6 | "version": 3 7 | }, 8 | "file_extension": ".py", 9 | "mimetype": "text/x-python", 10 | "name": "python", 11 | "nbconvert_exporter": "python", 12 | "pygments_lexer": "ipython3", 13 | "version": "3.7.3-final" 14 | }, 15 | "orig_nbformat": 2, 16 | "kernelspec": { 17 | "name": "python37364bit2d832ff4253d4ad2949ee022c04a1bde", 18 | "display_name": "Python 3.7.3 64-bit" 19 | } 20 | }, 21 | "nbformat": 4, 22 | "nbformat_minor": 2, 23 | "cells": [ 24 | { 25 | "cell_type": "code", 26 | "execution_count": 1, 27 | "metadata": {}, 28 | "outputs": [], 29 | "source": [ 30 | "import matplotlib.pyplot as plt\n", 31 | "import numpy as np\n", 32 | "import torch as th\n", 33 | "\n", 34 | "from torch_bandpass import Prism" 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": 2, 40 | "metadata": {}, 41 | "outputs": [], 42 | "source": [ 43 | "layer = Prism(64, mid_periods=(2, 8))\n", 44 | "data = th.randn(1, 64) + th.arange(64) / 8" 45 | ] 46 | }, 47 | { 48 | "cell_type": "code", 49 | "execution_count": 3, 50 | "metadata": {}, 51 | "outputs": [ 52 | { 53 | "output_type": "display_data", 54 | "data": { 55 | "text/plain": "
", 56 | "image/svg+xml": "\n\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", 57 | "image/png": "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\n" 58 | }, 59 | "metadata": { 60 | "needs_background": "light" 61 | } 62 | } 63 | ], 64 | "source": [ 65 | "repeated = data[..., None].repeat(1, 1, 3)\n", 66 | "filtered = layer(repeated)\n", 67 | "\n", 68 | "plt.plot(data[0].numpy())\n", 69 | "plt.plot(filtered[0, :, 0].numpy(), '--')\n", 70 | "plt.plot(filtered[0, :, 1].numpy(), '--')\n", 71 | "plt.plot(filtered[0, :, 2].numpy(), '--')\n", 72 | "plt.legend(['signal', 'low-pass', 'mid-pass', 'high-pass'])\n", 73 | "plt.show()" 74 | ] 75 | } 76 | ] 77 | } -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | setup( 4 | name="torch-bandpass", 5 | version="1.0.0", 6 | description="A PyTorch implementation of the Prism filter for Transformers", 7 | url="https://github.com/unixpickle/torch-bandpass", 8 | author="Alex Nichol", 9 | author_email="unixpickle@gmail.com", 10 | license="BSD", 11 | packages=["torch_bandpass"], 12 | install_requires=["numpy", "torch"], 13 | ) 14 | -------------------------------------------------------------------------------- /torch_bandpass/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | An implementation of the Prism algorithm from https://arxiv.org/abs/2011.04823. 3 | """ 4 | 5 | from .layer import Prism 6 | 7 | __all__ = ["Prism"] 8 | -------------------------------------------------------------------------------- /torch_bandpass/dct.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | def create_dct_matrix(num_samples): 5 | """ 6 | Create a matrix that can be left-multiplied to perform the discrete cosine 7 | transform. 8 | """ 9 | result = np.zeros([num_samples, num_samples], dtype=np.float32) 10 | result += np.pi / num_samples 11 | result *= np.arange(num_samples, dtype=np.float32) + 0.5 12 | result *= np.arange(num_samples, dtype=np.float32)[:, None] 13 | result = np.cos(result) 14 | return result 15 | 16 | 17 | def create_dct_inverse(num_samples): 18 | """ 19 | Create the inverse of create_dct_matrix(). 20 | """ 21 | return np.linalg.inv(create_dct_matrix(num_samples)) 22 | 23 | 24 | def dct_period_to_bin(num_samples, period): 25 | """ 26 | Get the DCT bin index closest to the given period. 27 | """ 28 | return round(num_samples / (2 * period)) 29 | -------------------------------------------------------------------------------- /torch_bandpass/layer.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | 4 | from .dct import create_dct_matrix, create_dct_inverse, dct_period_to_bin 5 | 6 | 7 | class Prism(nn.Module): 8 | """ 9 | A Prism module performs different bandpass filters on different subsets of 10 | the features in a batch of activations. 11 | 12 | :param num_samples: the number of timesteps to expect in the inputs. 13 | :param mid_periods: the periods separating the bands. Periods of 1 and 14 | infinity are implied at the two extremes. 15 | """ 16 | 17 | def __init__(self, num_samples, mid_periods=(2, 8, 32, 256)): 18 | super().__init__() 19 | self.num_samples = num_samples 20 | self.mid_periods = mid_periods 21 | bins = ( 22 | [0] 23 | + [dct_period_to_bin(num_samples, p) for p in mid_periods[::-1]] 24 | + [num_samples] 25 | ) 26 | self.bands = nn.ModuleList([]) 27 | for min_index, max_index in zip(bins, bins[1:]): 28 | self.bands.append(Bandpass(num_samples, min_index, max_index)) 29 | 30 | def forward(self, x): 31 | """ 32 | Apply the Prism layer to a batch of sequences. 33 | 34 | :param x: an [N x T x C] Tensor, where C is the number of features, 35 | T is the number of timesteps, and N is the batch size. 36 | """ 37 | n, t, _c = x.shape 38 | assert t == self.num_samples 39 | 40 | x = x.permute(2, 0, 1).contiguous() # put C on the outer dimension 41 | 42 | chunks_in = _split_up_chunks(x, len(self.bands)) 43 | chunks_out = [] 44 | for bandpass, chunk in zip(self.bands, chunks_in): 45 | chunk = chunk.reshape(-1, t) 46 | chunk = bandpass(chunk) 47 | chunk = chunk.reshape(-1, n, t) 48 | chunks_out.append(chunk) 49 | joined_out = torch.cat(chunks_out, dim=0) 50 | joined_out = joined_out.permute( 51 | 1, 2, 0 52 | ).contiguous() # put C back as the inner dimension 53 | return joined_out 54 | 55 | 56 | class Bandpass(nn.Module): 57 | def __init__(self, num_samples, min_index, max_index): 58 | super().__init__() 59 | dct = create_dct_matrix(num_samples)[min_index:max_index] 60 | inv = create_dct_inverse(num_samples)[:, min_index:max_index] 61 | self.register_buffer("forward_dct", torch.from_numpy(dct.T)) 62 | self.register_buffer("backward_dct", torch.from_numpy(inv.T)) 63 | 64 | def forward(self, x): 65 | return (x @ self.forward_dct) @ self.backward_dct 66 | 67 | 68 | def _split_up_chunks(batch, num_chunks): 69 | chunk_size = batch.shape[0] // num_chunks 70 | num_larger_chunks = batch.shape[0] % num_chunks 71 | start_idx = 0 72 | result = [] 73 | for i in range(num_chunks): 74 | this_chunk_size = chunk_size 75 | if i < num_larger_chunks: 76 | this_chunk_size += 1 77 | result.append(batch[start_idx : start_idx + this_chunk_size]) 78 | start_idx += this_chunk_size 79 | return result 80 | --------------------------------------------------------------------------------