{"cells":[{"cell_type":"markdown","metadata":{"_cell_guid":"ae4dbbf1-c8bc-95cf-cf5a-6ec684737322"},"source":""},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"bb0560e7-b343-7dec-4a0d-339b8ae30bd4"},"outputs":[],"source":"import numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport tensorflow as tf\nfrom tensorflow.contrib import layers\n%matplotlib inline"},{"cell_type":"markdown","metadata":{"_cell_guid":"dd13369e-7c1c-6017-98e7-7e27a71b1f04"},"source":""},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"bc22c77a-c469-4d18-5f6c-956376b1adf4"},"outputs":[],"source":"# Load train and test data\ndef load_mnist(csv_file):\n    \n    mnist_height, mnist_width = 28, 28\n    loaded = pd.read_csv(csv_file, header=None)\n    array_version = loaded.values\n    labels = array_version[:, 0]\n    \n    # Reshape 1D images back into 2D\n    images = array_version[:, 1:].reshape(-1, mnist_height, mnist_width).astype('uint8')\n    \n    return labels, images\n\ntrain_y, train_x = load_mnist('mnist_train.csv')\ntest_y, test_x = load_mnist('mnist_test.csv')"},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"e5e63f3b-3f1f-2101-4080-d7b7639d5c1c"},"outputs":[],"source":""},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"ae47c97e-627a-539a-9893-c90ded1b68ee"},"outputs":[],"source":""},{"cell_type":"markdown","metadata":{"_cell_guid":"31158baa-1c56-872b-45d6-8eca9f96fe1c"},"source":""},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"6f4ee994-1d60-8360-b847-5e5670246833"},"outputs":[],"source":"# Let's set up our model.\ntf.reset_default_graph()\n\nactivation = tf.nn.relu\n\n# Placeholders for input and labels\nwith tf.name_scope('input'):\n    x = tf.placeholder(tf.int32, shape=(None, 28, 28, 1))\n    \nwith tf.name_scope('labels'):\n    y = tf.placeholder(tf.float64, shape=(None))\n\n# The model:\nwith tf.name_scope('conv1'):\n    conv1 = layers.convolution2d(x, num_outputs=50, kernel_size=5, \n                                 activation_fn=activation, scope='conv1')\n    \n    conv1_mp = layers.max_pool2d(conv1, 2)\n    \nwith tf.name_scope('conv2'):\n    conv2 = layers.convolution2d(conv1_mp, num_outputs=16, \n                                 kernel_size=5, activation_fn=activation,\n                                 scope='conv2')\n    \n    conv2_mp = layers.max_pool2d(conv2, 2)\n    \nwith tf.name_scope('fc1'):\n    # Reshape for the fc layer\n    # We need to know the dimension of the image to reshape. After two max pools,\n    # which halve both height and with, for example, we are left with \n    # 28/4 x 28/4 = 7x7. If we have 16 output channels, that means we reshape to 7*7*16.\n    conv3_mp = tf.reshape(conv2_mp, (tf.shape(conv2_mp)[0], 7 * 7 * 16))\n    \n    fc1 = layers.fully_connected(conv3_mp, num_outputs=10, \n                                 activation_fn=None, scope='fc1')\n    \n# Loss: We use a cross entropy loss here.\nwith tf.name_scope('loss'):\n    \n    # Compute the average cross entropy loss across the batch\n    loss = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(labels=fc1, logits=y))\n    \nwith tf.name_scope('auxiliary'):\n    \n    # Just for our own benefit, compute the accuracy here\n    accuracy = tf.reduce_mean(tf.cast(tf.equal(tf.arg_max(fc1, dimension=1), y), tf.float32))"},{"cell_type":"markdown","metadata":{"_cell_guid":"b729c903-9725-3b79-8f21-cedb0ad1f23d"},"source":""},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"c9c3285a-4df5-f08f-de18-357d105f27ff"},"outputs":[],"source":""},{"cell_type":"markdown","metadata":{"_cell_guid":"bacd6bdb-d700-8881-3e8d-384f380dbc59"},"source":""},{"cell_type":"markdown","metadata":{"_cell_guid":"a29b1fda-878a-add0-700e-5dd5fe2075e2"},"source":""},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"44f42e2c-212a-e3ff-a9a6-ca4dc6d928e0"},"outputs":[],"source":"def sample_batch(x_data, y_data, batch_size):\n    chosen = np.random.choice(x_data.shape[0], size=batch_size)\n    return x_data[chosen], y_data[chosen]"},{"cell_type":"markdown","metadata":{"_cell_guid":"9a01e0fb-1746-23ab-7f63-a599707a7530"},"source":""},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"1b827175-a1f5-bfc9-992c-1f5dfcf02d96"},"outputs":[],"source":"# Mean-centre the data\nmean_image = np.mean(train_x)\ncentred_train = (train_x - mean_image)\ncentred_test = (test_x - mean_image)"},{"cell_type":"markdown","metadata":{"_cell_guid":"17bdbf02-a7c9-2736-b6af-1a937ccd6590"},"source":""},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"4d2083a9-b9a0-e7b0-f248-908670c320a6"},"outputs":[],"source":"# Create a validation and train set\n# RandomState allows us to pick a seed so that we can compare different runs\nfrom numpy.random import RandomState\nvalidation_set_size = 64\nstate = RandomState(1)\nval_choices = state.choice(centred_train.shape[0], size=validation_set_size)\n\n# Train set is inverse of validation set -- a little bit ugly in numpy\ntrain_choices = np.ones(len(centred_train), dtype=bool)\ntrain_choices[val_choices] = 0\n\n# Produce training and validation sets\n# We need the expand_dims to explicitly tell Tensorflow that it's a single-channel image\nval_x, val_y = np.expand_dims(centred_train[val_choices], axis=3), train_y[val_choices]\nmodel_train_x, model_train_y = np.expand_dims(centred_train[train_choices], axis=3), train_y[train_choices]\n\nprint('Shapes:')\nprint('Training set: {}'.format(model_train_x.shape))\nprint('Validation set: {}'.format(val_x.shape))"},{"cell_type":"markdown","metadata":{"_cell_guid":"b28b952c-1387-6e96-72c0-3602982e8bf8"},"source":""},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"64195714-aa59-58c8-6f9b-0d7de8b3f492"},"outputs":[],"source":""},{"cell_type":"markdown","metadata":{"_cell_guid":"014d3520-9e8a-e3e6-cafa-cd6f5b6d5427"},"source":""},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"8a65cae6-d483-ad43-c19a-f505a554e807"},"outputs":[],"source":""},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"46101f90-c24d-f84a-7155-860294ad9109"},"outputs":[],"source":""},{"cell_type":"markdown","metadata":{"_cell_guid":"51fcc647-0bfd-a6f6-3845-64e498d29342"},"source":""},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"416a4838-f72c-d3c2-ea7e-ead2e56d8ecd"},"outputs":[],"source":""},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"c7b04fb9-18b6-fa56-2de7-2ea24f0e0d70"},"outputs":[],"source":""}],"metadata":{"_change_revision":0,"_is_fork":false,"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.6.0"}},"nbformat":4,"nbformat_minor":0}