Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Numpy convolutional #2

Open
King-Oni opened this issue Aug 20, 2022 · 1 comment
Open

Numpy convolutional #2

King-Oni opened this issue Aug 20, 2022 · 1 comment

Comments

@King-Oni
Copy link

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

@King-Oni
Copy link
Author

I came up with a solution

correlate

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)

convolve

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)

active use

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)

then it can be used like this:

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant