Skip to content

Instantly share code, notes, and snippets.

@sternj
Created December 3, 2023 04:59
Show Gist options
  • Save sternj/d56c3f347ecef9206f7d91646ff1ac60 to your computer and use it in GitHub Desktop.
Save sternj/d56c3f347ecef9206f7d91646ff1ac60 to your computer and use it in GitHub Desktop.
from __future__ import annotations
import skimage.data
import sys
from typing import TYPE_CHECKING
import numpy
def extracted_conv_(filter_size, img,conv_filter,result):
for r in numpy.uint16(numpy.arange(filter_size / 2.0, img.shape[0] - filter_size / 2.0 + 1)):
for c in numpy.uint16(numpy.arange(filter_size / 2.0, img.shape[1] - filter_size / 2.0 + 1)):
'\n Getting the current region to get multiplied with the filter.\n How to loop through the image and get the region based on \n the image and filer sizes is the most tricky part of convolution.\n '
curr_region = img[r - numpy.uint16(numpy.floor(filter_size / 2.0)):r + numpy.uint16(numpy.ceil(filter_size / 2.0)), c - numpy.uint16(numpy.floor(filter_size / 2.0)):c + numpy.uint16(numpy.ceil(filter_size / 2.0))]
curr_result = curr_region * conv_filter
conv_sum = numpy.sum(curr_result)
result[r, c] = conv_sum
return result
from extracted_conv_ import extracted_conv_
import numpy
import sys
import skimage.data
'\nConvolutional neural network implementation using NumPy.\nAn article describing this project is titled "Building Convolutional Neural Network using NumPy from Scratch". It is available in these links: https://www.linkedin.com/pulse/building-convolutional-neural-network-using-numpy-from-ahmed-gad/\nhttps://www.kdnuggets.com/2018/04/building-convolutional-neural-network-numpy-scratch.html\nIt is also translated into Chinese: http://m.aliyun.com/yunqi/articles/585741\n\nThe project is tested using Python 3.5.2 installed inside Anaconda 4.2.0 (64-bit)\nNumPy version used is 1.14.0\n\nFor more info., contact me:\n Ahmed Fawzy Gad\n KDnuggets: https://www.kdnuggets.com/author/ahmed-gad\n LinkedIn: https://www.linkedin.com/in/ahmedfgad\n Facebook: https://www.facebook.com/ahmed.f.gadd\n ahmed.f.gad@gmail.com\n ahmed.fawzy@ci.menofia.edu.eg\n'
def conv_(img, conv_filter):
filter_size = conv_filter.shape[1]
result = numpy.zeros(img.shape)
result = extracted_conv_(filter_size, img, conv_filter, result)
final_result = result[numpy.uint16(filter_size / 2.0):result.shape[0] - numpy.uint16(filter_size / 2.0), numpy.uint16(filter_size / 2.0):result.shape[1] - numpy.uint16(filter_size / 2.0)]
return final_result
def conv(img, conv_filter):
if len(img.shape) != len(conv_filter.shape) - 1:
print('Error: Number of dimensions in conv filter and image do not match.')
exit()
if len(img.shape) > 2 or len(conv_filter.shape) > 3:
if img.shape[-1] != conv_filter.shape[-1]:
print('Error: Number of channels in both image and filter must match.')
sys.exit()
if conv_filter.shape[1] != conv_filter.shape[2]:
print('Error: Filter must be a square matrix. I.e. number of rows and columns must match.')
sys.exit()
if conv_filter.shape[1] % 2 == 0:
print('Error: Filter must have an odd size. I.e. number of rows and columns must be odd.')
sys.exit()
feature_maps = numpy.zeros((img.shape[0] - conv_filter.shape[1] + 1, img.shape[1] - conv_filter.shape[1] + 1, conv_filter.shape[0]))
for filter_num in range(conv_filter.shape[0]):
print('Filter ', filter_num + 1)
curr_filter = conv_filter[filter_num, :]
' \n Checking if there are mutliple channels for the single filter.\n If so, then each channel will convolve the image.\n The result of all convolutions are summed to return a single feature map.\n '
if len(curr_filter.shape) > 2:
conv_map = conv_(img[:, :, 0], curr_filter[:, :, 0])
for ch_num in range(1, curr_filter.shape[-1]):
conv_map = conv_map + conv_(img[:, :, ch_num], curr_filter[:, :, ch_num])
else:
conv_map = conv_(img, curr_filter)
feature_maps[:, :, filter_num] = conv_map
return feature_maps
def pooling(feature_map, size=2, stride=2):
pool_out = numpy.zeros((numpy.uint16((feature_map.shape[0] - size + 1) / stride + 1), numpy.uint16((feature_map.shape[1] - size + 1) / stride + 1), feature_map.shape[-1]))
for map_num in range(feature_map.shape[-1]):
r2 = 0
for r in numpy.arange(0, feature_map.shape[0] - size + 1, stride):
c2 = 0
for c in numpy.arange(0, feature_map.shape[1] - size + 1, stride):
pool_out[r2, c2, map_num] = numpy.max([feature_map[r:r + size, c:c + size, map_num]])
c2 = c2 + 1
r2 = r2 + 1
return pool_out
def relu(feature_map):
relu_out = numpy.zeros(feature_map.shape)
for map_num in range(feature_map.shape[-1]):
for r in numpy.arange(0, feature_map.shape[0]):
for c in numpy.arange(0, feature_map.shape[1]):
relu_out[r, c, map_num] = numpy.max([feature_map[r, c, map_num], 0])
return relu_out
if __name__ == '__main__':
img = skimage.data.chelsea()
img = skimage.color.rgb2gray(img)
l1_filter = numpy.zeros((2, 3, 3))
l1_filter[0, :, :] = numpy.array([[[-1, 0, 1], [-1, 0, 1], [-1, 0, 1]]])
l1_filter[1, :, :] = numpy.array([[[1, 1, 1], [0, 0, 0], [-1, -1, -1]]])
print('\n**Working with conv layer 1**')
l1_feature_map = conv(img, l1_filter)
print('\n**ReLU**')
l1_feature_map_relu = relu(l1_feature_map)
print('\n**Pooling**')
l1_feature_map_relu_pool = pooling(l1_feature_map_relu, 2, 2)
print('**End of conv layer 1**\n')
l2_filter = numpy.random.rand(3, 5, 5, l1_feature_map_relu_pool.shape[-1])
print('\n**Working with conv layer 2**')
l2_feature_map = conv(l1_feature_map_relu_pool, l2_filter)
print('\n**ReLU**')
l2_feature_map_relu = relu(l2_feature_map)
print('\n**Pooling**')
l2_feature_map_relu_pool = pooling(l2_feature_map_relu, 2, 2)
print('**End of conv layer 2**\n')
l3_filter = numpy.random.rand(1, 7, 7, l2_feature_map_relu_pool.shape[-1])
print('\n**Working with conv layer 3**')
l3_feature_map = conv(l2_feature_map_relu_pool, l3_filter)
print('\n**ReLU**')
l3_feature_map_relu = relu(l3_feature_map)
print('\n**Pooling**')
l3_feature_map_relu_pool = pooling(l3_feature_map_relu, 2, 2)
print('**End of conv layer 3**\n')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment