-
Notifications
You must be signed in to change notification settings - Fork 45
/
conv_layer.py
48 lines (40 loc) · 2.09 KB
/
conv_layer.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
from layer import Layer
from scipy import signal
import numpy as np
## Math behind this layer can found at :
## https://medium.com/@2017csm1006/forward-and-backpropagation-in-convolutional-neural-network-4dfa96d7b37e
# inherit from base class Layer
# This convolutional layer is always with stride 1
class ConvLayer(Layer):
# input_shape = (i,j,d)
# kernel_shape = (m,n)
# layer_depth = output_depth
def __init__(self, input_shape, kernel_shape, layer_depth):
self.input_shape = input_shape
self.input_depth = input_shape[2]
self.kernel_shape = kernel_shape
self.layer_depth = layer_depth
self.output_shape = (input_shape[0]-kernel_shape[0]+1, input_shape[1]-kernel_shape[1]+1, layer_depth)
self.weights = np.random.rand(kernel_shape[0], kernel_shape[1], self.input_depth, layer_depth) - 0.5
self.bias = np.random.rand(layer_depth) - 0.5
# returns output for a given input
def forward_propagation(self, input):
self.input = input
self.output = np.zeros(self.output_shape)
for k in range(self.layer_depth):
for d in range(self.input_depth):
self.output[:,:,k] += signal.correlate2d(self.input[:,:,d], self.weights[:,:,d,k], 'valid') + self.bias[k]
return self.output
# computes dE/dW, dE/dB for a given output_error=dE/dY. Returns input_error=dE/dX.
def backward_propagation(self, output_error, learning_rate):
in_error = np.zeros(self.input_shape)
dWeights = np.zeros((self.kernel_shape[0], self.kernel_shape[1], self.input_depth, self.layer_depth))
dBias = np.zeros(self.layer_depth)
for k in range(self.layer_depth):
for d in range(self.input_depth):
in_error[:,:,d] += signal.convolve2d(output_error[:,:,k], self.weights[:,:,d,k], 'full')
dWeights[:,:,d,k] = signal.correlate2d(self.input[:,:,d], output_error[:,:,k], 'valid')
dBias[k] = self.layer_depth * np.sum(output_error[:,:,k])
self.weights -= learning_rate*dWeights
self.bias -= learning_rate*dBias
return in_error