I implemented a simplified version using scipy for learning purposes:
```python
import numpy as np
from scipy import signal
def conv2d_simplified(input, weight, bias=None, padding=0):
# This is an implemention of torch's conv2d using scipy correlate2d. Only
# limited options are supported for simplicity.
# Inspired by https://github.com/99991/NumPyConv2D/
c_out, c_in_by_groups, kh, kw = weight.shape
if not isinstance(padding, int):
raise NotImplementedError()
if padding:
input = np.pad(input, ((0, 0), (0, 0), (padding, padding), (padding, padding)), "constant")
outArr = np.empty((input.shape[0], c_out, input.shape[2]+1-kh, input.shape[3]+1-kw))
al = np.empty((outArr.shape[2], outArr.shape[3]))
for k in range(input.shape[0]):
for i in range(weight.shape[0]):
al[:, :] = 0.0
for j in range(weight.shape[1]):
al += signal.correlate2d(input[k, j, :, :], weight[i, j, :, :], 'valid')
outArr[k, i, :, :] = al
if bias is not None:
outArr = outArr + bias.reshape(1, c_out, 1, 1)
return outArr
```
I implemented a simplified version using scipy for learning purposes:
```python
import numpy as np
from scipy import signal
def conv2d_simplified(input, weight, bias=None, padding=0):
# This is an implemention of torch's conv2d using scipy correlate2d. Only
# limited options are supported for simplicity.
# Inspired by https://github.com/99991/NumPyConv2D/
c_out, c_in_by_groups, kh, kw = weight.shape
if not isinstance(padding, int):
raise NotImplementedError()
if padding:
input = np.pad(input, ((0, 0), (0, 0), (padding, padding), (padding, padding)), "constant")
outArr = np.empty((input.shape[0], c_out, input.shape[2]+1-kh, input.shape[3]+1-kw))
al = np.empty((outArr.shape[2], outArr.shape[3]))
for k in range(input.shape[0]):
for i in range(weight.shape[0]):
al[:, :] = 0.0
for j in range(weight.shape[1]):
al += signal.correlate2d(input[k, j, :, :], weight[i, j, :, :], 'valid')
outArr[k, i, :, :] = al
if bias is not None:
outArr = outArr + bias.reshape(1, c_out, 1, 1)
return outArr
```
If you want to do a convolution, you have to flip the kernel because the conv2d function actually uses the cross-correlation operator.