我尝试为卷积网络实现反卷积层。我所说的反卷积是指假设我有 3x227x227 输入图像到一个层,过滤器的大小为 3x11x11 ,步幅为 4。因此生成的特征图的大小为 55x55 。我尝试做的是应用反向操作,将 55x55 特征图再次投影到 3x227x227 图像。基本上 55x55 特征图上的每个值都由 3x11x11 过滤器加权并投影到图像空间,并且由于步幅而导致重叠区域被平均。

我试图在 numpy 中实现它,但没有成功。我找到了一个强力嵌套 for 循环的解决方案,但速度太慢了。如何在 numpy 中有效地实现它?欢迎任何帮助。

最佳答案

正如在 this question 中所讨论的,反卷积只是一个卷积层,但具有特定的填充、步长和过滤器大小选择。

例如,如果您当前的图像大小是 55x55 ,则可以使用 padding=20stride=1filter=[21x21] 应用卷积以获得 75x75 图像,然后是 95x95 等等。 (我不是说这个数字选择给出了输出图像的期望质量,只是大小。实际上,我认为从 227x227 下采样到 55x55 然后上采样回 227x227 太激进了,但是您可以自由尝试任何架构)。

这是任何步幅和填充的前向传递的实现。它确实 im2col transformation ,但使用来自 numpy 的 stride_tricks 。它不像现代 GPU 实现那样优化,但绝对比 4 inner loops 快:

import numpy as np

def conv_forward(x, w, b, stride, pad):
  N, C, H, W = x.shape
  F, _, HH, WW = w.shape

  # Check dimensions
  assert (W + 2 * pad - WW) % stride == 0, 'width does not work'
  assert (H + 2 * pad - HH) % stride == 0, 'height does not work'

  # Pad the input
  p = pad
  x_padded = np.pad(x, ((0, 0), (0, 0), (p, p), (p, p)), mode='constant')

  # Figure out output dimensions
  H += 2 * pad
  W += 2 * pad
  out_h = (H - HH) / stride + 1
  out_w = (W - WW) / stride + 1

  # Perform an im2col operation by picking clever strides
  shape = (C, HH, WW, N, out_h, out_w)
  strides = (H * W, W, 1, C * H * W, stride * W, stride)
  strides = x.itemsize * np.array(strides)
  x_stride = np.lib.stride_tricks.as_strided(x_padded,
                                             shape=shape, strides=strides)
  x_cols = np.ascontiguousarray(x_stride)
  x_cols.shape = (C * HH * WW, N * out_h * out_w)

  # Now all our convolutions are a big matrix multiply
  res = w.reshape(F, -1).dot(x_cols) + b.reshape(-1, 1)

  # Reshape the output
  res.shape = (F, N, out_h, out_w)
  out = res.transpose(1, 0, 2, 3)
  out = np.ascontiguousarray(out)
  return out

关于python - 如何在 numpy 中为 CNN 实现反卷积层?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34254679/

10-16 08:08