title: Translating tensorflows conv2d to numpy/scipy operations?
body: <p>This is the documentation for tf.nn.conv2d: Given an input tensor of shape [batch, in_height, in_width, in_channels] and a filter / kernel tensor of shape [filter_height, filter_width, in_channels, out_channels], this op performs the following</p>
  
  <ol>
  <li>Flattens the filter to a 2-D matrix with shape [filter_height *
  filter_width * in_channels, </li>
  <li>Extracts image patches from the input tensor to form a virtual tensor of shape [batch, out_height, out_width, filter_height *
  filter_width * in_channels].</li>
  <li>For each patch, right-multiplies the filter matrix and the image patch vector.</li>
  </ol>
  
  <p>In other words, it takes in a tensor of n images and does convolution with out_channel filters. </p>
  
  <p>I am trying to translate to code that uses only numpy operations and the code is the following:</p>
  
  <pre><code>def my_conv2d(x, kernel):
     nf = kernel.shape[-1]  # number of filters
     rf = kernel.shape[0]  # filter size
     w = kernel
     s = 1 # stride
  
     h_range = int((x.shape[2] - rf) / s) + 1  # (W - F + 2P) / S
     w_range = int((x.shape[1] - rf) / s) + 1  # (W - F + 2P) / S
     np_o = np.zeros((1, h_range, w_range, nf))
     for i in range(x.shape[0]):
       for z in range(nf):
         for _h in range(h_range):
           for _w in range(w_range):
             np_o[0, _h, _w, z] = np.sum(x[i, _h * s:_h * s + rf, _w * s:_w * s 
                                  + rf, * w[:, :, :, z])                     
      return np_o
  </code></pre>
  
  <p>The problem is that code is extremely slow. Are there any numpy or scipy functions that can replicate what tensorflows' conv2d is doing that is of similar efficiency? I have looked at <a href="https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.convolve2d.html" rel="nofollow noreferrer">https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.convolve2d.html</a> and it does convolution ONCE, meaning I have to pass a 2d tensor alongside a 2d kernel (it does not do multiple filters).
  None of the previous stackoverflow questions helped much with this.</p>
  
  <p>Thanks</p>
  
  <p>Edit: did some testing and my code is about 44000% slower than doing tf.nn.conv2d!</p>