I added my own max pool layer to the independent's code project neural network from scratch code(Here is the link to the his vid: https://www.youtube.com/watch?v=Lakz2MoHy6o&t=570s).I checked parts of my code and it looks like it should work, but I get an error when I try to train the model that says can't reshape array of size 1 into shape(845,1). I can't seem to find where the array of size 1 is coming from and can't find where in my code something would cause this.
Here is the code for my max pool layer(rest is from Independent code project video):
class MaxPool2d(Layer):
def __init__(self, input_shape, block_size):
input_depth, input_height, input_width = input_shape
self.block_size = block_size
self.height = input_height
self.width = input_width
self.input_shape = input_shape
self.input_depth = input_depth
self.output_shape = (input_depth, (input_height / block_size), (input_width / block_size))
def forward_prop(self, input):
self.input = input
self.output = np.zeros(self.output_shape)
self.block_input_array = np.zeros(self.input_shape)
for i in range(self.input_depth):
#gets max matrix
self.output[i] = block_reduce(self.input[i], block_size=(self.block_size, self.block_size), func=np.max)
#need this block array for the back prop
block_array = view_as_blocks(self.input[i], (self.block_size, self.block_size))
self.block_input_array[i] = block_array.reshape(self.width, self.height)
return self.output
def backward_prop(self, output_gradient, learning_rate):
self.input_gradient = np.zeros(self.input_shape)
for i in range(self.input_depth):
#find all indicies of the maxes in each block
max_indices = np.argmax(self.block_input_array[i], axis=1)
max_indices = np.expand_dims(max_indices,axis=1)
grad_arr = np.zeros_like(self.block_input_array[i])
#places a 1 on every index that had a max value
np.put_along_axis(grad_arr, max_indices, 1, axis=1)
grad_arr = grad_arr.reshape(-1, self.block_size, self.block_size)
#chain rule
self.input_gradient[i] = np.multiply(undo_blocks(grad_arr, self.width, self.height, self.block_size), output_gradient[i])
return self.input_gradient
#puts the array into same order as it was in the input
def undo_blocks(array, width, height, block_size):
ordered_blocks = array.reshape(-1,block_size,block_size)
split_blocks = np.array(np.hsplit(ordered_blocks,block_size))
split_blocks = np.array(np.hsplit(split_blocks, (width / block_size)))
reshaped_arr = split_blocks.flatten().reshape(width,height)
return reshaped_arr
Here is the code for building the network:
network = [
Convolutional((1, 28, 28), 3, 5),
Sigmoid(),
MaxPool2d((5,26,26), 2),
Reshape((5, 13, 13), (5 * 13 * 13, 1)),
Dense(5 * 13 * 13, 100),
Sigmoid(),
Dense(100, 2),
Softmax()
]
epochs = 10
learning_rate = 0.1
x_axis = []
y_axis = []
# train
for e in range(epochs):
error = 0
for x, y in zip(x_train, y_train):
# forward
output = x
for layer in network:
output = layer.forward(output)
# error
error += binary_cross_entropy(y, output)
# backward
grad = binary_cross_entropy_prime(y, output)
for layer in reversed(network):
grad = layer.backward(grad, learning_rate)
x_axis.append(e)
y_axis.append(error)
error /= len(x_train)
print(f"{e + 1}/{epochs}, error={error}")
# test
for x, y in zip(x_test, y_test):
output = x
for layer in network:
output = layer.forward(output)
print(f"pred: {np.argmax(output)}, true: {np.argmax(y)}")
The error I'm getting is happening during the forward propagation of the MaxPool layer I think and here is what it says: ValueError: cannot reshape array of size 1 into shape (845,1)
When I took out the max pool layer and changed the input shapes to match the code works fine. I don't know why but its like somewhere its changing the data to only contain one value since the error said that it can't reshape array of size 1 to (845,1).