From 94fee2d2d42cba720b6b858ba5d99239843c0133 Mon Sep 17 00:00:00 2001 From: AntreasAntoniou Date: Mon, 6 Nov 2017 17:27:08 +0000 Subject: [PATCH] Update spec and scripts --- scripts/generate_batchnorm_test.py | 43 +++++++++++++++++++++ scripts/generate_conv_test.py | 46 ++++++++++++++++++++++ spec/coursework2.pdf | Bin 94770 -> 94812 bytes spec/coursework2.tex | 60 ++++++++++++++--------------- 4 files changed, 119 insertions(+), 30 deletions(-) create mode 100644 scripts/generate_batchnorm_test.py create mode 100644 scripts/generate_conv_test.py diff --git a/scripts/generate_batchnorm_test.py b/scripts/generate_batchnorm_test.py new file mode 100644 index 0000000..b7f8690 --- /dev/null +++ b/scripts/generate_batchnorm_test.py @@ -0,0 +1,43 @@ +import numpy as np +from mlp.layers import BatchNormalizationLayer +import argparse + +parser = argparse.ArgumentParser(description='Welcome to GAN-Shot-Learning script') + +parser.add_argument('--student_id', nargs="?", type=str, help='Your student id in the format "sxxxxxxx"') + +args = parser.parse_args() + +student_id = args.student_id + +def generate_inputs(student_id): + student_number = student_id + tests = np.arange(96).reshape((2, 3, 4, 4)) + tests[:, 0, :, :] = float(student_number[1:3]) / 10 - 5 + tests[:, :, 1, :] = float(student_number[3:5]) / 10 - 5 + tests[:, 2, :, :] = float(student_number[5:7]) / 10 - 5 + tests[0, 1, :, :] = float(student_number[7]) / 10 - 5 + return tests + +test_inputs = generate_inputs(student_id) +test_inputs = np.reshape(test_inputs, newshape=(2, -1)) +test_grads_wrt_outputs = np.arange(-48, 48).reshape((2, -1)) + +#produce BatchNorm Layer fprop and bprop +activation_layer = BatchNormalizationLayer(input_dim=48) + +beta = np.array(48*[0.3]) +gamma = np.array(48*[0.8]) + +activation_layer.params = [gamma, beta] +BN_fprop = activation_layer.fprop(test_inputs) +BN_bprop = activation_layer.bprop( + test_inputs, BN_fprop, test_grads_wrt_outputs) +BN_grads_wrt_params = activation_layer.grads_wrt_params( + test_inputs, test_grads_wrt_outputs) + +test_output = "BatchNormalization:\nFprop: {}\nBprop: {}\nGrads_wrt_params: {}\n"\ + .format(BN_fprop, BN_bprop, BN_grads_wrt_params) + +with open("{}_batchnorm_test_file.txt".format(student_id), "w+") as out_file: + out_file.write(test_output) \ No newline at end of file diff --git a/scripts/generate_conv_test.py b/scripts/generate_conv_test.py new file mode 100644 index 0000000..82d6e79 --- /dev/null +++ b/scripts/generate_conv_test.py @@ -0,0 +1,46 @@ +import numpy as np +from mlp.layers import ConvolutionalLayer +import argparse + +parser = argparse.ArgumentParser(description='Welcome to GAN-Shot-Learning script') + +parser.add_argument('--student_id', nargs="?", type=str, help='Your student id in the format "sxxxxxxx"') + +args = parser.parse_args() + +student_id = args.student_id + +def generate_inputs(student_id): + student_number = student_id + tests = np.arange(96).reshape((2, 3, 4, 4)) + tests[:, 0, :, :] = float(student_number[1:3]) / 10 - 5 + tests[:, :, 1, :] = float(student_number[3:5]) / 10 - 5 + tests[:, 2, :, :] = float(student_number[5:7]) / 10 - 5 + tests[0, 1, :, :] = float(student_number[7]) / 10 - 5 + return tests + + + +test_inputs = generate_inputs(student_id) +test_grads_wrt_outputs = np.arange(-20, 16).reshape((2, 2, 3, 3)) +inputs = np.arange(96).reshape((2, 3, 4, 4)) +kernels = np.arange(-12, 12).reshape((2, 3, 2, 2)) +biases = np.arange(2) + +#produce ConvolutionalLayer fprop, bprop and grads_wrt_params +activation_layer = ConvolutionalLayer(num_input_channels=3, num_output_channels=2, input_dim_1=4, input_dim_2=4, + kernel_dim_1=2, kernel_dim_2=2) +activation_layer.params = [kernels, biases] +conv_fprop = activation_layer.fprop(test_inputs) +conv_bprop = activation_layer.bprop( + test_inputs, conv_fprop, test_grads_wrt_outputs) +conv_grads_wrt_params = activation_layer.grads_wrt_params(test_inputs, + test_grads_wrt_outputs) + +test_output = "ConvolutionalLayer:\nFprop: {}\nBprop: {}\n" \ + "Grads_wrt_params: {}\n".format(conv_fprop, + conv_bprop, + conv_grads_wrt_params) + +with open("{}_conv_test_file.txt".format(student_id), "w+") as out_file: + out_file.write(test_output) \ No newline at end of file diff --git a/spec/coursework2.pdf b/spec/coursework2.pdf index 65cccbf144f90d0b3e6561521e0e9844569fffdb..2baad36c87d1ea6541ebe5d50fdc9b94e88869c8 100644 GIT binary patch delta 19981 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 delta 19927 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 a3UhQ}a&&ldWo8OFG%+(a3MC~)PeuwPH-+W^ diff --git a/spec/coursework2.tex b/spec/coursework2.tex index 1885847..53ca6a3 100644 --- a/spec/coursework2.tex +++ b/spec/coursework2.tex @@ -138,32 +138,32 @@ code necessary for the coursework in it. This branch includes the following additions to your setup: \begin{itemize} -\itemsep1pt\parskip0pt\parsep0pt -\item - A notebook \verb+BatchNormalizationLayer_tests+ which includes - test functions to check the implementations of the BatchNorm layer - \texttt{fprop}, \texttt{bprop} and \texttt{grads\_wrt\_params} - methods. The BatchNormalizationLayer skeleton code can be found in mlp.layers. - The tests use the mlp.layers implementation so be sure to reload your notebook - when you update your mlp.layers code. -\item - A notebook \verb+Convolutional_layer_tests+ which includes - test functions to check the implementations of the Convolutional layer - \texttt{fprop}, \texttt{bprop} and \texttt{grads\_wrt\_params} - methods. The ConvolutionalLayer skeleton code can be found in mlp.layers. - The tests use the mlp.layers implementation so be sure to reload your notebook - when you update your mlp.layers code. -\item - A new \texttt{ReshapeLayer} class in the \verb+mlp.layers+ module. - When included in a a multiple layer model, this allows the output of - the previous layer to be reshaped before being forward propagated to - the next layer. -\item - A new \texttt{EMNISTDataProvider} class in the \verb+mlp.data_providers+ module. - This class is a small change to the \texttt{MNISTDataProvider} class, linking to the Balanced EMNIST data, and setting the number of classes to 47. -\item - Training, validation, and test sets for the \texttt{EMNIST Balanced} dataset that - you will use in this coursework + \itemsep1pt\parskip0pt\parsep0pt + \item + A notebook \verb+BatchNormalizationLayer_tests+ which includes + test functions to check the implementations of the BatchNorm layer + \texttt{fprop}, \texttt{bprop} and \texttt{grads\_wrt\_params} + methods. The BatchNormalizationLayer skeleton code can be found in mlp.layers. + The tests use the mlp.layers implementation so be sure to reload your notebook + when you update your mlp.layers code. + \item + A notebook \verb+Convolutional_layer_tests+ which includes + test functions to check the implementations of the Convolutional layer + \texttt{fprop}, \texttt{bprop} and \texttt{grads\_wrt\_params} + methods. The ConvolutionalLayer skeleton code can be found in mlp.layers. + The tests use the mlp.layers implementation so be sure to reload your notebook + when you update your mlp.layers code. + \item + A new \texttt{ReshapeLayer} class in the \verb+mlp.layers+ module. + When included in a a multiple layer model, this allows the output of + the previous layer to be reshaped before being forward propagated to + the next layer. + \item + A new \texttt{EMNISTDataProvider} class in the \verb+mlp.data_providers+ module. + This class is a small change to the \texttt{MNISTDataProvider} class, linking to the Balanced EMNIST data, and setting the number of classes to 47. + \item + Training, validation, and test sets for the \texttt{EMNIST Balanced} dataset that + you will use in this coursework \end{itemize} @@ -186,9 +186,9 @@ In part A of the coursework you will focus on using deep neural networks on EMNI \item Perform baseline experiments using DNNs trained on EMNIST. Obviously there are a lot things that could be explored including hidden unit activation functions, network architectures, training hyperparameters, and the use of regularisation and dropout. You cannot explore everything and is best to carefully investigate a few things in depth. \item Implement the RMSProp \citep{tieleman2012rmsprop} and Adam \citep{kingma2015adam} learning rules, by defining new classes inheriting from \texttt{GradientDescendLearningRule} in the \texttt{mlp/learning\_rules.py} module. The \texttt{MomentumLearningRule} class is an example of how to define a learning rules which uses an additional state variable to calculate the updates to the parameters. \item Perform experiments to compare stochastic gradient descent, RMSProp, and Adam for deep neural network training on EMNIST, building on your earlier baseline experiments. - \item Implement batch normalisation \citep{ioffe2015batch} as a class \verb+BatchNormLayer+. You need to implement \texttt{fprop}, \texttt{bprop} and \texttt{grads\_wrt\_params} methods for this class. - \item Verify the correctness of your implementation using the supplied unit tests in \verb+Batchnorm_tests.ipynb+. - \item Automatically create a test file \verb+sXXXXXXX_batchnorm_test.txt+, by running the provided program \verb+generate_conv_test.py+ which uses your \verb+BatchnormLayer+ class methods on a unique test vector generated using your student ID number. + \item Implement batch normalisation \citep{ioffe2015batch} as a class \verb+BatchNormalizationLayer+. You need to implement \texttt{fprop}, \texttt{bprop} and \texttt{grads\_wrt\_params} methods for this class. + \item Verify the correctness of your implementation using the supplied unit tests in\\\verb+BatchNormalizationLayer_tests.ipynb+. + \item Automatically create a test file \verb+sXXXXXXX_batchnorm_test.txt+, by running the provided program \verb+generate_batchnorm_test.py+ which uses your \verb+BatchNormalizationLayer+ class methods on a unique test vector generated using your student ID number. \item Perform experiments on EMNIST to investigate the impact of using batch normalisation in deep neural networks, building on your earlier experiments. \end{enumerate} In the above experiments you should use the validation set to assess accuracy. Use the test set at the end to assess the accuracy of the deep neural network architecture and training setup that you judge to be the best. @@ -199,7 +199,7 @@ In the above experiments you should use the validation set to assess accuracy. In part B of the coursework you should implement convolutional and max-pooling layers, and carry out experiments using a convolutional networks with one and two convolutional layers. \begin{enumerate} \item Implement a convolutional layer as a class \verb+ConvolutionalLayer+. You need to implement \texttt{fprop}, \texttt{bprop} and \texttt{grads\_wrt\_params} methods for this class. - \item Verify the correctness of your implementation using the supplied unit tests in \verb+Convolutional_layer_tests.ipynb+. + \item Verify the correctness of your implementation using the supplied unit tests in\\\verb+ConvolutionalLayer_tests.ipynb+. \item Automatically create a test file \verb+sXXXXXXX_conv_test.txt+, by running the provided program \verb+generate_conv_test.py+ which uses your \verb+ConvolutionalLayer+ class methods on a unique test vector generated using your student ID number. \item Implement a max-pooling layer. Non-overlapping pooling (which was assumed in the lecture presentation) is required. You may also implement a more generic solution with striding as well. \item Construct and train networks containing one and two convolutional layers, and max-pooling layers, using the Balanced EMNIST data, reporting your experimental results. As a default use convolutional kernels of dimension 5x5 (stride 1) and pooling regions of 2x2 (stride 2, hence non-overlapping). As a default convolutional networks with two convolutional layers, investigate a network with two convolutional+maxpooling layers with 5 feature maps in the first convolutional layer, and 10 feature maps in the second convolutional layer.