Open King-Oni opened 2 years ago
I came up with a solution
import numpy as np
from numpy.fft import fft2, ifft2
def _correlate2D(array, kernel):
a = array
f = kernel
s = f.shape + tuple(np.subtract(a.shape, f.shape) + 1)
strd = np.lib.stride_tricks.as_strided
subM = strd(a, shape=s, strides=a.strides * 2)
return np.einsum("ij,ijkl->kl", f, subM)
def _convolve2D(array, kernel):
a = array
f = np.flip(kernel)
s = f.shape + tuple(np.subtract(a.shape, f.shape) + 1)
strd = np.lib.stride_tricks.as_strided
subM = strd(a, shape=s, strides=a.strides * 2)
return np.einsum("ij,ijkl->kl", f, subM)
def correlate2d(array: np.array, kernel: np.array, mode="full"):
modes = ["full", "valid"]
keyFlag = mode in modes
if not keyFlag:
raise KeyError("mode is either full or valid!.\n other than that can't do.")
if mode == "valid":
return _correlate2D(array, kernel)
return _correlate2D(np.pad(array, 1), kernel)
def convolve2d(array: np.array, kernel: np.array, mode="full"):
modes = ["full", "valid"]
keyFlag = mode in modes
if not keyFlag:
raise KeyError("mode is either full or valid!.\n other than that can't do.")
if mode == "valid":
return _convolve2D(array, kernel)
return _convolve2D(np.pad(array, 1), kernel)
class Convolutional(Layer):
def __init__(self, input_shape, kernel_size, depth):
input_depth, input_height, input_width = input_shape
self.depth = depth
self.input_shape = input_shape
self.input_depth = input_depth
self.output_shape = (depth, input_height - kernel_size + 1, input_width - kernel_size + 1)
self.kernels_shape = (depth, input_depth, kernel_size, kernel_size)
self.kernels = np.random.randn(*self.kernels_shape)
self.biases = np.random.randn(*self.output_shape)
def forward(self, input):
self.input = input
self.output = np.copy(self.biases)
for i in range(self.depth):
for j in range(self.input_depth):
self.output[i] += correlate2d(self.input[j], self.kernels[i, j], "valid")
return self.output
def backward(self, output_gradient, learning_rate):
kernels_gradient = np.zeros(self.kernels_shape)
input_gradient = np.zeros(self.input_shape)
for i in range(self.depth):
for j in range(self.input_depth):
kernels_gradient[i, j] = correlate2d(self.input[j], output_gradient[i], "valid")
input_gradient[j] += convolve2d(output_gradient[i], self.kernels[i, j], "full")
self.kernels -= learning_rate * kernels_gradient
self.biases -= learning_rate * output_gradient
return input_gradient
I'm not sure if it really works well I only tested it on one matrix which is the one Used in the video to explain how it works
First I have to say thanks for your tutorials on neural networks, now I understand the topic better
But there was a thing that I couldn't let pass through
In the conv layer you used a functionality from scipy, But scipy doesn't work in my device for some reasons And I need a way to implement these functions using numpy, but I don't understand the math behind that Nor do I find some mathematical formula that tells me how to 2d convolve or correlate and I can't come up with working solution that's why I'm here I need a way to implement conv layer in numpy only