Реализация простого блока Re sNet с PyTorch - PullRequest
0 голосов
/ 23 марта 2020

Я пытаюсь реализовать следующий блок Re sNet, который Re sNet состоит из блоков с двумя сверточными слоями и пропущенным соединением. По какой-то причине он не добавляет вывод пропускаемого соединения, если он применяется, или ввод к выводу слоев свертки.

Блок Re sNet имеет:

  • Два сверточных слоя с:

    • 3x3 ядро ​​
    • без смещений
    • заполнение одним пикселем с обеих сторон
    • 2d нормализация партии после каждый сверточный слой
  • Пропускное соединение:

    • просто копирует вход, если разрешение и количество каналов не изменяются.
    • в случае изменения разрешения или количества каналов пропускаемое соединение должно иметь один сверточный слой с:
      • 1x1 сверткой без смещения
      • изменение разрешения с шагом (необязательно)
      • различное количество входных и выходных каналов (опционально)
      • за сверточным слоем 1x1 следует 2-мерная нормализация партии.
  • Нелинейность ReLU является Применяется после первого сверточного слоя и в конце блока.

Мой код:

class Block(nn.Module):
    def __init__(self, in_channels, out_channels, stride=1):
        """
        Args:
          in_channels (int):  Number of input channels.
          out_channels (int): Number of output channels.
          stride (int):       Controls the stride.
        """
        super(Block, self).__init__()

        self.skip = nn.Sequential()

        if stride != 1 or in_channels != out_channels:
          self.skip = nn.Sequential(
            nn.Conv2d(in_channels=in_channels, out_channels=out_channels, kernel_size=1, stride=stride, bias=False),
            nn.BatchNorm2d(out_channels))
        else:
          self.skip = None

        self.block = nn.Sequential(
            nn.Conv2d(in_channels=in_channels, out_channels=out_channels, kernel_size=3, padding=1, stride=1, bias=False),
            nn.BatchNorm2d(out_channels),
            nn.ReLU(),
            nn.Conv2d(in_channels=in_channels, out_channels=out_channels, kernel_size=3, padding=1, stride=1, bias=False),
            nn.BatchNorm2d(out_channels))

    def forward(self, x):
        out = self.block(x)

        if self.skip is not None:
          out = self.skip(x)
        else:
          out = x

        out += x

        out = F.relu(out)
        return out

1 Ответ

2 голосов
/ 23 марта 2020

Проблема заключается в повторном использовании переменной out. Обычно вы реализуете как this :

def forward(self, x):
    identity = x
    out = self.block(x)

    if self.skip is not None:
        identity = self.skip(x)

    out += identity
    out = F.relu(out)

    return out

Если вам нравятся "однострочники":

def forward(self, x):
    out = self.block(x)
    out += (x if self.skip is None else self.skip(x))
    out = F.relu(out)
    return out

Если вы действительно как одна строка (пожалуйста, это слишком много, не выбирайте эту опцию:))

def forward(self, x):
    return F.relu(self.block(x) + (x if self.skip is None else self.skip(x)))
...