def test_output_size_is_correct(self): input_size = (1, 28, 28) layer = Conv2DLayer(64, (3, 3), activation=Relu(), input_size=input_size) layer.init_weights() assert layer.output_size == (64, 26, 26)
def test_output_size_is_correct_with_same_padding(self): input_size = (1, 28, 28) layer = Conv2DLayer(64, (3, 3), activation=Relu(), padding=Padding.SAME, input_size=input_size) layer.init_weights() assert layer.output_size == (64, 28, 28)
def test_can_stack_layers(self, padding): input_size = (1, 28, 28) layer1 = Conv2DLayer(64, (3, 3), activation=Linear(), padding=padding, input_size=input_size) layer1.init_weights() layer2 = Conv2DLayer(32, (3, 3), activation=Linear(), input_size=layer1.output_size) layer2.init_weights() input_ = np.random.random_sample(input_size) * 10 layer1_output = layer1.forwards(input_, context={}) layer2_output = layer2.forwards(layer1_output, context={}) assert layer1.weights.shape == (64, 1, 3, 3) assert layer2.weights.shape == (32, 64, 3, 3) assert layer2_output.shape == layer2.output_size
def test_forwards_returns_convolution(self): input_size = (1, 28, 28) layer = Conv2DLayer(64, (3, 3), activation=Linear(), input_size=input_size) layer.init_weights() input_ = np.random.random_sample(input_size) output = layer.forwards(input_, context={}) for channel in range(64): expected_output = conv2d(input_, layer.weights) assert_almost_equal(output, expected_output)
def test_forwards_returns_correct_output_shape(self, padding, expected_output_shape): input_size = (1, 28, 28) layer = Conv2DLayer(64, (3, 3), activation=Relu(), padding=padding, input_size=input_size) layer.init_weights() input_ = np.random.random_sample(input_size) output = layer.forwards(input_, context={}) assert output.shape == expected_output_shape
def test_backwards_returns_weight_grad(self): input_size = (1, 28, 28) layer = Conv2DLayer(64, (3, 3), activation=Linear(), input_size=input_size) layer.init_weights() # FIXME: If the initial loss happens to be small, the learning rate may # be too high and the test can fail. input_ = np.random.random_sample(input_size) losses = _minimize_output(layer, input_, steps=10, learning_rate=0.001, train_weights=True) assert losses[-1] < losses[0]
def train_and_test(dataset_path, model="basic"): # Debugging. np.seterr(divide="raise") if model == "conv2d": # Load train and test datasets. print("reading data...") train_images, train_labels, test_images, test_labels = load_mnist_dataset( dataset_path, (1, 28, 28) ) model = Model( layers=[ Conv2DLayer(32, (3, 3), activation=Relu()), MaxPoolingLayer((2, 2)), Conv2DLayer(32, (3, 3), activation=Relu()), MaxPoolingLayer((2, 2)), FlattenLayer(), Layer(64, name="relu", activation=Relu()), Layer(10, name="softmax", activation=Softmax()), ], input_size=(1, 28, 28), ) print("training model...") model.fit( train_images, train_labels, batch_size=32, epochs=10, learning_rate=0.15, learning_rate_decay=0.1, loss_op=CategoricalCrossentropy(), ) elif model == "basic": input_size = (28 * 28,) train_images, train_labels, test_images, test_labels = load_mnist_dataset( dataset_path, input_size ) model = Model( layers=[ Layer(32, name="relu", activation=Relu()), Layer(10, name="softmax", activation=Softmax()), ], input_size=input_size, ) print("training model...") model.fit( train_images, train_labels, batch_size=32, epochs=10, learning_rate=0.18, learning_rate_decay=0.1, loss_op=CategoricalCrossentropy(), ) else: raise Exception(f"Unknown model {model}") print("evaluating model...") accuracy = model.evaluate(test_images, test_labels) print("accuracy {:3f}".format(accuracy))