Skip to content

wideresnet

BasicBlock

Bases: Module

A Wide Residual Network Basic block.

This class creates a basic block.

Parameters:

Name Type Description Default
in_planes int

How many channels enter the block.

required
out_planes int

How many channels leave the block.

required
stride int

stride for convolution layer.

required
dropout float

Adds dropout if value is greater than 0.0.

0.0
Source code in fastestimator/fastestimator/architecture/pytorch/wideresnet.py
class BasicBlock(nn.Module):
    """A Wide Residual Network Basic block.

    This class creates a basic block.

    Args:
        in_planes: How many channels enter the block.
        out_planes: How many channels leave the block.
        stride: stride for convolution layer.
        dropout: Adds dropout if value is greater than 0.0.
    """
    def __init__(self, in_planes: int, out_planes: int, stride: int, dropout: float = 0.0) -> None:
        super(BasicBlock, self).__init__()
        self.bn1 = nn.BatchNorm2d(in_planes)
        self.relu1 = nn.ReLU(inplace=True)
        self.conv1 = nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride, padding=1, bias=False)
        self.bn2 = nn.BatchNorm2d(out_planes)
        self.relu2 = nn.ReLU(inplace=True)
        self.conv2 = nn.Conv2d(out_planes, out_planes, kernel_size=3, stride=1, padding=1, bias=False)
        self.dropout = dropout
        self.equalInOut = (in_planes == out_planes)
        self.convShortcut = (not self.equalInOut) and nn.Conv2d(
            in_planes, out_planes, kernel_size=1, stride=stride, padding=0, bias=False) or None

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        if not self.equalInOut:
            x = self.relu1(self.bn1(x))
        else:
            out = self.relu1(self.bn1(x))
        out = self.relu2(self.bn2(self.conv1(out if self.equalInOut else x)))
        if self.dropout > 0:
            out = F.dropout(out, p=self.droprate, training=self.training)
        out = self.conv2(out)
        return torch.add(x if self.equalInOut else self.convShortcut(x), out)

NetworkBlock

Bases: Module

A Wide Residual Network block.

This class utilizes the basic block to create a network block.

Parameters:

Name Type Description Default
nb_layers int

How many layers to create.

required
in_planes int

How many channels enter the block.

required
out_planes int

How many channels leave the block.

required
block BasicBlock

Class for creating a network block.

required
stride int

stride for convolution layer.

required
dropout float

Adds dropout if value is greater than 0.0.

0.0
Source code in fastestimator/fastestimator/architecture/pytorch/wideresnet.py
class NetworkBlock(nn.Module):
    """A Wide Residual Network block.

    This class utilizes the basic block to create a network block.

    Args:
        nb_layers: How many layers to create.
        in_planes: How many channels enter the block.
        out_planes: How many channels leave the block.
        block: Class for creating a network block.
        stride: stride for convolution layer.
        dropout: Adds dropout if value is greater than 0.0.
    """
    def __init__(self,
                 nb_layers: int,
                 in_planes: int,
                 out_planes: int,
                 block: BasicBlock,
                 stride: int,
                 dropout: float = 0.0) -> None:
        super(NetworkBlock, self).__init__()
        self.layer = self._make_layer(block, in_planes, out_planes, nb_layers, stride, dropout)

    def _make_layer(self,
                    block: BasicBlock,
                    in_planes: int,
                    out_planes: int,
                    nb_layers: int,
                    stride: int,
                    dropout: float) -> torch.nn.Sequential:
        layers = []
        for i in range(int(nb_layers)):
            layers.append(block(i == 0 and in_planes or out_planes, out_planes, i == 0 and stride or 1, dropout))
        return nn.Sequential(*layers)

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        return self.layer(x)

WideResidualNetwork

Bases: Module

Wide Residual Network.

This class creates the Wide Residual Network with specified parameters.

Parameters:

Name Type Description Default
depth int

Depth of the network. Compute N = (n - 4) / 6. For a depth of 16, n = 16, N = (16 - 4) / 6 = 2 For a depth of 28, n = 28, N = (28 - 4) / 6 = 4 For a depth of 40, n = 40, N = (40 - 4) / 6 = 6

28
classes int

The number of outputs the model should generate.

10
widen_factor int

Width of the network.

10
dropout float

Adds dropout if value is greater than 0.0.

0.0

Raises:

Type Description
AssertionError

If (depth - 4) is not divisible by 6.

Source code in fastestimator/fastestimator/architecture/pytorch/wideresnet.py
class WideResidualNetwork(nn.Module):
    """Wide Residual Network.

    This class creates the Wide Residual Network with specified parameters.

    Args:
        depth: Depth of the network. Compute N = (n - 4) / 6.
               For a depth of 16, n = 16, N = (16 - 4) / 6 = 2
               For a depth of 28, n = 28, N = (28 - 4) / 6 = 4
               For a depth of 40, n = 40, N = (40 - 4) / 6 = 6
        classes: The number of outputs the model should generate.
        widen_factor: Width of the network.
        dropout: Adds dropout if value is greater than 0.0.

    Raises:
        AssertionError: If (depth - 4) is not divisible by 6.
    """
    def __init__(self, depth: int = 28, classes: int = 10, widen_factor: int = 10, dropout: float = 0.0) -> None:
        super(WideResidualNetwork, self).__init__()
        nChannels = [16, 16 * widen_factor, 32 * widen_factor, 64 * widen_factor]
        assert (depth - 4) % 6 == 0
        n = (depth - 4) / 6
        block = BasicBlock
        # 1st conv before any network block
        self.conv1 = nn.Conv2d(3, nChannels[0], kernel_size=3, stride=1, padding=1, bias=False)
        # 1st block
        self.block1 = NetworkBlock(n, nChannels[0], nChannels[1], block, 1, dropout)
        # 2nd block
        self.block2 = NetworkBlock(n, nChannels[1], nChannels[2], block, 2, dropout)
        # 3rd block
        self.block3 = NetworkBlock(n, nChannels[2], nChannels[3], block, 2, dropout)
        # global average pooling and classifier
        self.bn1 = nn.BatchNorm2d(nChannels[3])
        self.relu = nn.ReLU(inplace=True)
        self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
        self.fc = nn.Linear(nChannels[3], classes)
        self.nChannels = nChannels[3]

        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
            elif isinstance(m, nn.BatchNorm2d):
                m.weight.data.fill_(1)
                m.bias.data.zero_()
            elif isinstance(m, nn.Linear):
                m.bias.data.zero_()

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        out = self.conv1(x)
        out = self.block1(out)
        out = self.block2(out)
        out = self.block3(out)
        out = self.relu(self.bn1(out))
        out = self.avgpool(out)
        out = out.view(-1, self.nChannels)
        return self.fc(out)