class ConvolutionLayer: def __init__(self, kernel_num, kernel_size): self.kernel_num = kernel_num self.kernel_size = kernel_size self.kernels = np.random.randn(kernel_num, kernel_size, kernel_size) / (kernel_size**2) def patches_generator(self, image): image_h, image_w = image.shape self.image = image for h in range(image_h-self.kernel_size+1): for w in range(image_w-self.kernel_size+1): patch = image[h:(h+self.kernel_size), w:(w+self.kernel_size)] yield patch, h, w def forward_prop(self, image): image_h, image_w = image.shape convolution_output = np.zeros((image_h-self.kernel_size+1, image_w-self.kernel_size+1, self.kernel_num)) for patch, h, w in self.patches_generator(image): convolution_output[h,w] = np.sum(patch*self.kernels, axis=(1,2)) return convolution_output def back_prop(self, dE_dY, alpha): dE_dk = np.zeros(self.kernels.shape) for patch, h, w in self.patches_generator(self.image): for f in range(self.kernel_num): dE_dk[f] += patch * dE_dY[h, w, f] self.kernels -= alpha*dE_dk return dE_dk