From 615a778dacae3ed99033e0a4a2b86f52d670213c Mon Sep 17 00:00:00 2001 From: Giovanni Volpe Date: Sun, 7 Jul 2024 16:34:19 +0800 Subject: [PATCH] Delete Building a block.ipynb --- tutorials/developers/Building a block.ipynb | 508 -------------------- 1 file changed, 508 deletions(-) delete mode 100644 tutorials/developers/Building a block.ipynb diff --git a/tutorials/developers/Building a block.ipynb b/tutorials/developers/Building a block.ipynb deleted file mode 100644 index 72121dd..0000000 --- a/tutorials/developers/Building a block.ipynb +++ /dev/null @@ -1,508 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Implementing a block\n", - "\n", - "Here we will show the steps you should follow to implement a block in deeplay.\n", - "\n", - "## 1. Should I implement a block?\n", - "\n", - "The first step is to ensure that what you want to implement is actually a block. \n", - "The main utility of a block is that the order of operations can be changed.\n", - "If this is useful for your module, then you should implement a block.\n", - "\n", - "Another reason to implement a block is if you want users to be able to add or\n", - "remove steps from the block. For example, adding an activation function, or\n", - "removing a dropout layer. \n", - "\n", - "Also, remember that blocks shouls be small and modular. If you are implementing\n", - "a block that is too big, you should consider breaking it down into smaller blocks.\n", - "\n", - "Finally, blocks should be pretty strict in terms of input and output. This is \n", - "important to ensure that the user has the flexibility to change the order of\n", - "operations without breaking the model." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 2. Implementing the block\n", - "\n", - "The first step is to create a new file in the `deeplay/blocks` directory. It\n", - "can be in a deeper subdirectory if it makes sense.\n", - "\n", - "# 2.1 The BaseBlock class\n", - "\n", - "The file should contain a class that inherits from `BaseBlock`. The first \n", - "arguments should specify the input and output shapes of the block. This is\n", - "important to ensure that the block is used correctly.\n", - "\n", - "The next arguments should specify the arguments for the default layer class.\n", - "In this case, we are using `torch.nn.Conv1d`, so we should specify the kernel\n", - "size, stride, padding, etc.\n", - "\n", - "Finally, the class should accept kwargs that will be passed to the super class." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "from deeplay.blocks.base import BaseBlock\n", - "from deeplay.external.layer import Layer\n", - "\n", - "import torch\n", - "import torch.nn as nn\n", - "\n", - "class MyConv1dBlock(BaseBlock):\n", - " def __init__(self, \n", - " in_channels, \n", - " out_channels, \n", - " kernel_size=3, \n", - " stride=1, \n", - " padding=0, \n", - " dilation=1, \n", - " groups=1, \n", - " bias=True,\n", - " order=None, # We take order here for typing purposes\n", - " **kwargs):\n", - " \n", - " # We save the input parameters\n", - " self.in_channels = in_channels\n", - " self.out_channels = out_channels\n", - " self.kernel_size = kernel_size\n", - " self.stride = stride\n", - " self.padding = padding\n", - " self.dilation = dilation\n", - " self.groups = groups\n", - " self.bias = bias\n", - "\n", - " # Create the layer\n", - " layer = Layer(nn.Conv1d, \n", - " in_channels=in_channels, \n", - " out_channels=out_channels, \n", - " kernel_size=kernel_size, \n", - " stride=stride, \n", - " padding=padding, \n", - " dilation=dilation, \n", - " groups=groups, \n", - " bias=bias)\n", - " \n", - " # Send the layers and modules to the parent class\n", - " super(MyConv1dBlock, self).__init__(order=order, layer=layer, **kwargs)\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# 2.2 Annotations\n", - "\n", - "It is important to add annotations to the class and methods to ensure that the\n", - "user knows what to expect. This is also useful for the IDE to provide \n", - "autocomplete." - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "from typing import List, Optional\n", - "from torch.nn.common_types import _size_1_t\n", - "\n", - "from deeplay.module import DeeplayModule\n", - "\n", - "class MyConv1dBlock(BaseBlock):\n", - "\n", - " # We annotate the attributes\n", - " in_channels: int\n", - " out_channels: int\n", - " kernel_size: _size_1_t\n", - " stride: _size_1_t\n", - " padding: _size_1_t\n", - " dilation: _size_1_t\n", - " groups: int\n", - " bias: bool\n", - "\n", - " # We also annotate layer\n", - " layer: Layer \n", - "\n", - " def __init__(self, \n", - " in_channels: int,\n", - " out_channels: int,\n", - " kernel_size: _size_1_t = 3,\n", - " stride: _size_1_t = 1,\n", - " padding: _size_1_t = 0,\n", - " dilation: _size_1_t = 1, \n", - " groups: int = 1,\n", - " bias: bool = True,\n", - " order: Optional[List[str]] = None,\n", - " **kwargs: DeeplayModule) -> None:\n", - " \n", - " # We save the input parameters\n", - " self.in_channels = in_channels\n", - " self.out_channels = out_channels\n", - " self.kernel_size = kernel_size\n", - " self.stride = stride\n", - " self.padding = padding\n", - " self.dilation = dilation\n", - " self.groups = groups\n", - " self.bias = bias\n", - "\n", - " # Create the layer\n", - " layer = Layer(nn.Conv1d, \n", - " in_channels=in_channels, \n", - " out_channels=out_channels, \n", - " kernel_size=kernel_size, \n", - " stride=stride, \n", - " padding=padding, \n", - " dilation=dilation, \n", - " groups=groups, \n", - " bias=bias)\n", - " \n", - " # Send the layers and modules to the parent class\n", - " super().__init__(order=order, layer=layer, **kwargs)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 2.3 Documenting the block\n", - "\n", - "The next step is to document the block. This should include a description of \n", - "the block, the input and output shapes, and the arguments that can be passed to\n", - "the block." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "class MyConv1dBlock(BaseBlock):\n", - " \"\"\"A block for 1D convolutional operations.\n", - "\n", - " This block performs a 1D convolutional operation on the input tensor.\n", - "\n", - " Parameters\n", - " ----------\n", - " in_channels : int\n", - " The number of input channels.\n", - " out_channels : int\n", - " The number of output channels.\n", - " kernel_size : int\n", - " The size of the convolutional kernel.\n", - " stride : int\n", - " The stride of the convolutional operation.\n", - " padding : int\n", - " The padding of the convolutional operation.\n", - " dilation : int\n", - " The dilation of the convolutional operation.\n", - " groups : int \n", - " The number of groups for the convolutional operation.\n", - " bias : bool\n", - " Whether to include a bias term in the convolutional operation.\n", - " order : List[str]\n", - " The order of the layers in the block. If None, the order is\n", - " inferred from the order of keyword arguments, with `layer`\n", - " always being the first layer.\n", - " **kwargs\n", - " Additional modules to include in the block. The keys should be\n", - " the names of the modules and the values should be the modules.\n", - " \n", - " Attributes\n", - " ----------\n", - " in_channels : int\n", - " The number of input channels.\n", - " out_channels : int\n", - " The number of output channels.\n", - " kernel_size : int\n", - " The size of the convolutional kernel.\n", - " stride : int\n", - " The stride of the convolutional operation.\n", - " padding : int\n", - " The padding of the convolutional operation.\n", - " dilation : int\n", - " The dilation of the convolutional operation.\n", - " groups : int \n", - " The number of groups for the convolutional operation.\n", - " bias : bool\n", - " Whether to include a bias term in the convolutional operation.\n", - " order : List[str]\n", - " The order of the layers in the block.\n", - " layer : Layer\n", - " The layer that performs the convolutional operation.\n", - " \n", - " Input\n", - " -----\n", - " x : torch.Tensor (batch_size, in_channels, Any)\n", - " The input tensor to the block.\n", - " \n", - " Output\n", - " ------\n", - " y : torch.Tensor (batch_size, out_channels, Any)\n", - " The output tensor from the block.\n", - "\n", - " Evaluation\n", - " ----------\n", - " See :func:`~SequentialBlock.forward` for details.\n", - "\n", - " Examples\n", - " --------\n", - " >>> block = MyConv1dBlock(in_channels=3, out_channels=6, kernel_size=3)\n", - " >>> block.build()\n", - " MyConv1dBlock(\n", - " (layer): Conv1d(3, 6, kernel_size=(3,), stride=(1,))\n", - " )\n", - "\n", - " \"\"\"\n", - " # [rest of the code]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 2.4 Methods\n", - "\n", - "There are anumber of special methods that improve the usability of the block.\n", - "These do not need to be documented extensibly since they are not meant to be\n", - "used directly by the user.\n", - "These include:\n", - "\n", - "### 2.4.1 call_with_dummy_data\n", - "\n", - "This method creates some dummy data and calls the forward method. This is used to \n", - "create any lazy layers, and run all callbacks that are defined to run on forward.\n", - "\n", - "This method will be called immediately before the build phase, and only if the user\n", - "do not provide a dummy input.\n", - "\n", - "It is recommended to use a batch size of 2, to ensure that the batch normalization\n", - "works correctly. If there are any spatial or temporal dimensions, they should be\n", - "set to at least 12. This is to reduce the risk of stride or padding errors for\n", - "small inputs.\n", - "\n", - "### 2.4.2 get_default_activation (optional)\n", - "\n", - "This method should return the default activation function for the block. This will be\n", - "used if the user calls `.activated()` without specifying an activation function. Default\n", - "is nn.ReLU.\n", - "\n", - "### 2.4.3 get_default_normalization\n", - "\n", - "This method should return the default normalization function for the block. This will be\n", - "used if the user calls `.normalized()` without specifying a normalization function. \n", - "\n", - "### 2.4.4 get_default_merge (optional)\n", - "\n", - "This method should return the default merge function for the block. This will be used if\n", - "the user calls `.shortcut()` without specifying a merge function. Default is `ops.Add`.\n", - "\n", - "### 2.4.5 get_default_shortcut (optional)\n", - "\n", - "This method should return the default shortcut function for the block. This will be used \n", - "if the user calls `.shortcut()` without specifying a shortcut function. Default is \n", - "nn.Identity. \n", - "\n", - "This is used if there is a need for a projection in the shortcut connection. For example,\n", - "if the input and output shapes are different such that the merge function cannot be used.\n", - "\n" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "\n", - "from re import L\n", - "from deeplay.module import DeeplayModule\n", - "from deeplay.ops.merge import MergeOp\n", - "\n", - "\n", - "class MyConv1dBlock(BaseBlock):\n", - " \"\"\"A block for 1D convolutional operations.\n", - "\n", - " This block performs a 1D convolutional operation on the input tensor.\n", - "\n", - " Parameters\n", - " ----------\n", - " in_channels : int\n", - " The number of input channels.\n", - " out_channels : int\n", - " The number of output channels.\n", - " kernel_size : int\n", - " The size of the convolutional kernel.\n", - " stride : int\n", - " The stride of the convolutional operation.\n", - " padding : int\n", - " The padding of the convolutional operation.\n", - " dilation : int\n", - " The dilation of the convolutional operation.\n", - " groups : int \n", - " The number of groups for the convolutional operation.\n", - " bias : bool\n", - " Whether to include a bias term in the convolutional operation.\n", - " order : List[str]\n", - " The order of the layers in the block. If None, the order is\n", - " inferred from the order of keyword arguments, with `layer`\n", - " always being the first layer.\n", - " **kwargs\n", - " Additional modules to include in the block. The keys should be\n", - " the names of the modules and the values should be the modules.\n", - " \n", - " Attributes\n", - " ----------\n", - " in_channels : int\n", - " The number of input channels.\n", - " out_channels : int\n", - " The number of output channels.\n", - " kernel_size : int\n", - " The size of the convolutional kernel.\n", - " stride : int\n", - " The stride of the convolutional operation.\n", - " padding : int\n", - " The padding of the convolutional operation.\n", - " dilation : int\n", - " The dilation of the convolutional operation.\n", - " groups : int \n", - " The number of groups for the convolutional operation.\n", - " bias : bool\n", - " Whether to include a bias term in the convolutional operation.\n", - " order : List[str]\n", - " The order of the layers in the block.\n", - " layer : Layer\n", - " The layer that performs the convolutional operation.\n", - " \n", - " Input\n", - " -----\n", - " x : torch.Tensor (batch_size, in_channels, Any)\n", - " The input tensor to the block.\n", - " \n", - " Output\n", - " ------\n", - " y : torch.Tensor (batch_size, out_channels, Any)\n", - " The output tensor from the block.\n", - "\n", - " Evaluation\n", - " ----------\n", - " See :func:`~SequentialBlock.forward` for details.\n", - "\n", - " Examples\n", - " --------\n", - " >>> block = MyConv1dBlock(in_channels=3, out_channels=6, kernel_size=3)\n", - " >>> block.build()\n", - " MyConv1dBlock(\n", - " (layer): Conv1d(3, 6, kernel_size=(3,), stride=(1,))\n", - " )\n", - "\n", - " \"\"\"\n", - " # [rest of the code]\n", - "\n", - " # We annotate the attributes\n", - " in_channels: int\n", - " out_channels: int\n", - " kernel_size: _size_1_t\n", - " stride: _size_1_t\n", - " padding: _size_1_t\n", - " dilation: _size_1_t\n", - " groups: int\n", - " bias: bool\n", - "\n", - " # We also annotate layer\n", - " layer: Layer \n", - "\n", - " def __init__(self, \n", - " in_channels: int,\n", - " out_channels: int,\n", - " kernel_size: _size_1_t = 3,\n", - " stride: _size_1_t = 1,\n", - " padding: _size_1_t = 0,\n", - " dilation: _size_1_t = 1, \n", - " groups: int = 1,\n", - " bias: bool = True,\n", - " order: Optional[List[str]] = None,\n", - " **kwargs: DeeplayModule) -> None:\n", - " \n", - " # We save the input parameters\n", - " self.in_channels = in_channels\n", - " self.out_channels = out_channels\n", - " self.kernel_size = kernel_size\n", - " self.stride = stride\n", - " self.padding = padding\n", - " self.dilation = dilation\n", - " self.groups = groups\n", - " self.bias = bias\n", - "\n", - " # Create the layer\n", - " layer = Layer(nn.Conv1d, \n", - " in_channels=in_channels, \n", - " out_channels=out_channels, \n", - " kernel_size=kernel_size, \n", - " stride=stride, \n", - " padding=padding, \n", - " dilation=dilation, \n", - " groups=groups, \n", - " bias=bias)\n", - " \n", - " # Send the layers and modules to the parent class\n", - " super().__init__(order=order, layer=layer, **kwargs)\n", - "\n", - " def call_with_dummy_data(self) -> None:\n", - " x = torch.randn(2, self.in_channels, 16)\n", - " self(x)\n", - "\n", - " def get_default_activation(self) -> DeeplayModule:\n", - " return Layer(nn.ReLU)\n", - "\n", - " def get_default_normalization(self) -> DeeplayModule:\n", - " # We assume that the normalization is applied after Layer.\n", - " # If it is before, num_features should be in_channels.\n", - " # This will be automatically handled during the build process.\n", - " return Layer(nn.BatchNorm1d, num_features=self.out_channels)\n", - " \n", - " def get_default_merge(self) -> MergeOp:\n", - " from deeplay.ops.merge import Add\n", - " return Add()\n", - " \n", - " def get_default_shortcut(self) -> DeeplayModule:\n", - " return MyConv1dBlock(self.in_channels, self.out_channels, kernel_size=1, stride=self.stride, padding=0)\n" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.10" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -}