From 2deb8473ec7b88a0effcd1ab1ff8ec921069d3ec Mon Sep 17 00:00:00 2001 From: scbrubaker02 Date: Tue, 25 Jul 2017 11:59:30 -0400 Subject: [PATCH 1/3] Enabled image_classification for the project assistant --- image-classification/.udacity-pa/projects.py | 16 ++ .../dlnd_image_classification.ipynb | 269 +++++++----------- image-classification/my_answers.py | 148 ++++++++++ image-classification/problem_unittests.py | 208 -------------- image-classification/test_my_answers.py | 174 +++++++++++ 5 files changed, 437 insertions(+), 378 deletions(-) create mode 100644 image-classification/.udacity-pa/projects.py create mode 100644 image-classification/my_answers.py delete mode 100644 image-classification/problem_unittests.py create mode 100644 image-classification/test_my_answers.py diff --git a/image-classification/.udacity-pa/projects.py b/image-classification/.udacity-pa/projects.py new file mode 100644 index 0000000000..47a6473373 --- /dev/null +++ b/image-classification/.udacity-pa/projects.py @@ -0,0 +1,16 @@ +import argparse +import subprocess as sp +from udacity_pa import udacity + +nanodegree = 'nd101' +projects = ['image_classification'] +filenames = ['my_answers.py', 'dlnd_image_classification.ipynb'] + +def submit(args): + + # Do we prefer ipynb, html or both? + # sp.call(['jupyter', 'nbconvert', '--to', 'html', 'dlnd_image_classification.ipynb']) + + udacity.submit(nanodegree, projects[0], filenames, + environment = args.environment, + jwt_path = args.jwt_path) diff --git a/image-classification/dlnd_image_classification.ipynb b/image-classification/dlnd_image_classification.ipynb index a0698b809c..62bdd30208 100644 --- a/image-classification/dlnd_image_classification.ipynb +++ b/image-classification/dlnd_image_classification.ipynb @@ -14,11 +14,19 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": { "collapsed": false }, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "CIFAR-10 Dataset: 171MB [01:21, 2.08MB/s] 8.19K/170M [00:00<4:10:05, 11.4KB/s]\n" + ] + } + ], "source": [ "\"\"\"\n", "DON'T MODIFY ANYTHING IN THIS CELL THAT IS BELOW THIS LINE\n", @@ -26,9 +34,14 @@ "from urllib.request import urlretrieve\n", "from os.path import isfile, isdir\n", "from tqdm import tqdm\n", - "import problem_unittests as tests\n", + "import test_answers as tests\n", "import tarfile\n", "\n", + "%load_ext autoreload\n", + "%autoreload 2\n", + "\n", + "from my_answers import *\n", + "\n", "cifar10_dataset_folder_path = 'cifar-10-batches-py'\n", "\n", "# Use Floyd's cifar-10 dataset if present\n", @@ -56,10 +69,7 @@ "if not isdir(cifar10_dataset_folder_path):\n", " with tarfile.open(tar_gz_path) as tar:\n", " tar.extractall()\n", - " tar.close()\n", - "\n", - "\n", - "tests.test_folder_path(cifar10_dataset_folder_path)" + " tar.close()\n" ] }, { @@ -86,11 +96,43 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": { "collapsed": false }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Stats of batch 1:\n", + "Samples: 10000\n", + "Label Counts: {0: 1005, 1: 974, 2: 1032, 3: 1016, 4: 999, 5: 937, 6: 1030, 7: 1001, 8: 1025, 9: 981}\n", + "First 20 Labels: [6, 9, 9, 4, 1, 1, 2, 7, 8, 3, 4, 7, 7, 2, 9, 9, 9, 3, 2, 6]\n", + "\n", + "Example of Image 5:\n", + "Image - Min Value: 0 Max Value: 252\n", + "Image - Shape: (32, 32, 3)\n", + "Label - Label Id: 1 Name: automobile\n" + ] + }, + { + "data": { + "image/png": "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\nrkJggg==\n", + "text/plain": [ + "" + ] + }, + "metadata": { + "image/png": { + "height": 250, + "width": 253 + } + }, + "output_type": "display_data" + } + ], "source": [ "%matplotlib inline\n", "%config InlineBackend.figure_format = 'retina'\n", @@ -115,26 +157,42 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": { "collapsed": false }, - "outputs": [], - "source": [ - "def normalize(x):\n", - " \"\"\"\n", - " Normalize a list of sample image data in the range of 0 to 1\n", - " : x: List of image data. The image shape is (32, 32, 3)\n", - " : return: Numpy array of normalize data\n", - " \"\"\"\n", - " # TODO: Implement Function\n", - " return None\n", - "\n", + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "F\n", + "======================================================================\n", + "FAIL: test_normalize (test_answers.ImageClassificationTest)\n", + "normalize is correctly implemented\n", + "----------------------------------------------------------------------\n", + "Traceback (most recent call last):\n", + " File \"/Users/charlesbrubaker/Documents/udacity/DL/deep-learning/image-classification/test_answers.py\", line 26, in test_normalize\n", + " 'Not Numpy Object')\n", + "AssertionError: 'builtins' != 'numpy'\n", + "- builtins\n", + "+ numpy\n", + " : Not Numpy Object\n", + "\n", + "----------------------------------------------------------------------\n", + "Ran 1 test in 0.037s\n", + "\n", + "FAILED (failures=1)\n" + ] + } + ], + "source": [ + "from my_answers import normalize\n", "\n", "\"\"\"\n", "DON'T MODIFY ANYTHING IN THIS CELL THAT IS BELOW THIS LINE\n", "\"\"\"\n", - "tests.test_normalize(normalize)" + "tests.run('test_normalize')" ] }, { @@ -155,20 +213,12 @@ }, "outputs": [], "source": [ - "def one_hot_encode(x):\n", - " \"\"\"\n", - " One hot encode a list of sample labels. Return a one-hot encoded vector for each label.\n", - " : x: List of sample Labels\n", - " : return: Numpy array of one-hot encoded labels\n", - " \"\"\"\n", - " # TODO: Implement Function\n", - " return None\n", - "\n", + "from my_answers import one_hot_encode\n", "\n", "\"\"\"\n", "DON'T MODIFY ANYTHING IN THIS CELL THAT IS BELOW THIS LINE\n", "\"\"\"\n", - "tests.test_one_hot_encode(one_hot_encode)" + "tests.run('one_hot_encode')" ] }, { @@ -269,44 +319,15 @@ }, "outputs": [], "source": [ - "import tensorflow as tf\n", - "\n", - "def neural_net_image_input(image_shape):\n", - " \"\"\"\n", - " Return a Tensor for a batch of image input\n", - " : image_shape: Shape of the images\n", - " : return: Tensor for image input.\n", - " \"\"\"\n", - " # TODO: Implement Function\n", - " return None\n", - "\n", - "\n", - "def neural_net_label_input(n_classes):\n", - " \"\"\"\n", - " Return a Tensor for a batch of label input\n", - " : n_classes: Number of classes\n", - " : return: Tensor for label input.\n", - " \"\"\"\n", - " # TODO: Implement Function\n", - " return None\n", - "\n", - "\n", - "def neural_net_keep_prob_input():\n", - " \"\"\"\n", - " Return a Tensor for keep probability\n", - " : return: Tensor for keep probability.\n", - " \"\"\"\n", - " # TODO: Implement Function\n", - " return None\n", - "\n", + "from my_answers import neural_net_image_input, neural_net_label_input, neural_net_keep_prob_input\n", "\n", "\"\"\"\n", "DON'T MODIFY ANYTHING IN THIS CELL THAT IS BELOW THIS LINE\n", "\"\"\"\n", "tf.reset_default_graph()\n", - "tests.test_nn_image_inputs(neural_net_image_input)\n", - "tests.test_nn_label_inputs(neural_net_label_input)\n", - "tests.test_nn_keep_prob_inputs(neural_net_keep_prob_input)" + "tests.run('test_nn_image_inputs')\n", + "tests.run('test_nn_label_inputs')\n", + "tests.run('test_nn_keep_prob_inputs')" ] }, { @@ -334,25 +355,12 @@ }, "outputs": [], "source": [ - "def conv2d_maxpool(x_tensor, conv_num_outputs, conv_ksize, conv_strides, pool_ksize, pool_strides):\n", - " \"\"\"\n", - " Apply convolution then max pooling to x_tensor\n", - " :param x_tensor: TensorFlow Tensor\n", - " :param conv_num_outputs: Number of outputs for the convolutional layer\n", - " :param conv_ksize: kernal size 2-D Tuple for the convolutional layer\n", - " :param conv_strides: Stride 2-D Tuple for convolution\n", - " :param pool_ksize: kernal size 2-D Tuple for pool\n", - " :param pool_strides: Stride 2-D Tuple for pool\n", - " : return: A tensor that represents convolution and max pooling of x_tensor\n", - " \"\"\"\n", - " # TODO: Implement Function\n", - " return None \n", - "\n", + "from my_answers import conv2d_maxpool\n", "\n", "\"\"\"\n", "DON'T MODIFY ANYTHING IN THIS CELL THAT IS BELOW THIS LINE\n", "\"\"\"\n", - "tests.test_con_pool(conv2d_maxpool)" + "tests.run('test_con_pool')" ] }, { @@ -371,20 +379,12 @@ }, "outputs": [], "source": [ - "def flatten(x_tensor):\n", - " \"\"\"\n", - " Flatten x_tensor to (Batch Size, Flattened Image Size)\n", - " : x_tensor: A tensor of size (Batch Size, ...), where ... are the image dimensions.\n", - " : return: A tensor of size (Batch Size, Flattened Image Size).\n", - " \"\"\"\n", - " # TODO: Implement Function\n", - " return None\n", - "\n", + "from my_answers import flatten\n", "\n", "\"\"\"\n", "DON'T MODIFY ANYTHING IN THIS CELL THAT IS BELOW THIS LINE\n", "\"\"\"\n", - "tests.test_flatten(flatten)" + "tests.run('test_flatten')" ] }, { @@ -403,21 +403,12 @@ }, "outputs": [], "source": [ - "def fully_conn(x_tensor, num_outputs):\n", - " \"\"\"\n", - " Apply a fully connected layer to x_tensor using weight and bias\n", - " : x_tensor: A 2-D tensor where the first dimension is batch size.\n", - " : num_outputs: The number of output that the new tensor should be.\n", - " : return: A 2-D tensor where the second dimension is num_outputs.\n", - " \"\"\"\n", - " # TODO: Implement Function\n", - " return None\n", - "\n", + "from my_answers import fully_conn\n", "\n", "\"\"\"\n", "DON'T MODIFY ANYTHING IN THIS CELL THAT IS BELOW THIS LINE\n", "\"\"\"\n", - "tests.test_fully_conn(fully_conn)" + "tests.run('test_fully_conn')" ] }, { @@ -438,21 +429,12 @@ }, "outputs": [], "source": [ - "def output(x_tensor, num_outputs):\n", - " \"\"\"\n", - " Apply a output layer to x_tensor using weight and bias\n", - " : x_tensor: A 2-D tensor where the first dimension is batch size.\n", - " : num_outputs: The number of output that the new tensor should be.\n", - " : return: A 2-D tensor where the second dimension is num_outputs.\n", - " \"\"\"\n", - " # TODO: Implement Function\n", - " return None\n", - "\n", + "from my_answers import output\n", "\n", "\"\"\"\n", "DON'T MODIFY ANYTHING IN THIS CELL THAT IS BELOW THIS LINE\n", "\"\"\"\n", - "tests.test_output(output)" + "tests.run('test_output')" ] }, { @@ -478,39 +460,7 @@ }, "outputs": [], "source": [ - "def conv_net(x, keep_prob):\n", - " \"\"\"\n", - " Create a convolutional neural network model\n", - " : x: Placeholder tensor that holds image data.\n", - " : keep_prob: Placeholder tensor that hold dropout keep probability.\n", - " : return: Tensor that represents logits\n", - " \"\"\"\n", - " # TODO: Apply 1, 2, or 3 Convolution and Max Pool layers\n", - " # Play around with different number of outputs, kernel size and stride\n", - " # Function Definition from Above:\n", - " # conv2d_maxpool(x_tensor, conv_num_outputs, conv_ksize, conv_strides, pool_ksize, pool_strides)\n", - " \n", - "\n", - " # TODO: Apply a Flatten Layer\n", - " # Function Definition from Above:\n", - " # flatten(x_tensor)\n", - " \n", - "\n", - " # TODO: Apply 1, 2, or 3 Fully Connected Layers\n", - " # Play around with different number of outputs\n", - " # Function Definition from Above:\n", - " # fully_conn(x_tensor, num_outputs)\n", - " \n", - " \n", - " # TODO: Apply an Output Layer\n", - " # Set this to the number of classes\n", - " # Function Definition from Above:\n", - " # output(x_tensor, num_outputs)\n", - " \n", - " \n", - " # TODO: return output\n", - " return None\n", - "\n", + "from my_answers import conv_net\n", "\n", "\"\"\"\n", "DON'T MODIFY ANYTHING IN THIS CELL THAT IS BELOW THIS LINE\n", @@ -542,7 +492,7 @@ "correct_pred = tf.equal(tf.argmax(logits, 1), tf.argmax(y, 1))\n", "accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32), name='accuracy')\n", "\n", - "tests.test_conv_net(conv_net)" + "tests.run('test_conv_net')" ] }, { @@ -569,23 +519,12 @@ }, "outputs": [], "source": [ - "def train_neural_network(session, optimizer, keep_probability, feature_batch, label_batch):\n", - " \"\"\"\n", - " Optimize the session on a batch of images and labels\n", - " : session: Current TensorFlow session\n", - " : optimizer: TensorFlow optimizer function\n", - " : keep_probability: keep probability\n", - " : feature_batch: Batch of Numpy image data\n", - " : label_batch: Batch of Numpy label data\n", - " \"\"\"\n", - " # TODO: Implement Function\n", - " pass\n", - "\n", + "from my_answers import train_neural_network\n", "\n", "\"\"\"\n", "DON'T MODIFY ANYTHING IN THIS CELL THAT IS BELOW THIS LINE\n", "\"\"\"\n", - "tests.test_train_nn(train_neural_network)" + "tests.run('test_train_nn')" ] }, { @@ -604,17 +543,7 @@ }, "outputs": [], "source": [ - "def print_stats(session, feature_batch, label_batch, cost, accuracy):\n", - " \"\"\"\n", - " Print information about loss and validation accuracy\n", - " : session: Current TensorFlow session\n", - " : feature_batch: Batch of Numpy image data\n", - " : label_batch: Batch of Numpy label data\n", - " : cost: TensorFlow cost function\n", - " : accuracy: TensorFlow accuracy function\n", - " \"\"\"\n", - " # TODO: Implement Function\n", - " pass" + "from my_answers import print_stats" ] }, { diff --git a/image-classification/my_answers.py b/image-classification/my_answers.py new file mode 100644 index 0000000000..fddfd92968 --- /dev/null +++ b/image-classification/my_answers.py @@ -0,0 +1,148 @@ +import numpy as np +import tensorflow as tf + +def normalize(x): + """ + Normalize a list of sample image data in the range of 0 to 1 + : x: List of image data. The image shape is (32, 32, 3) + : return: Numpy array of normalize data + """ + # TODO: Implement Function + return None + +def one_hot_encode(x): + """ + One hot encode a list of sample labels. Return a one-hot encoded vector for each label. + : x: List of sample Labels + : return: Numpy array of one-hot encoded labels + """ + # TODO: Implement Function + return None + +def neural_net_image_input(image_shape): + """ + Return a Tensor for a batch of image input + : image_shape: Shape of the images + : return: Tensor for image input. + """ + # TODO: Implement Function + return None + + +def neural_net_label_input(n_classes): + """ + Return a Tensor for a batch of label input + : n_classes: Number of classes + : return: Tensor for label input. + """ + # TODO: Implement Function + return None + + +def neural_net_keep_prob_input(): + """ + Return a Tensor for keep probability + : return: Tensor for keep probability. + """ + # TODO: Implement Function + return None + +def conv2d_maxpool(x_tensor, conv_num_outputs, conv_ksize, conv_strides, pool_ksize, pool_strides): + """ + Apply convolution then max pooling to x_tensor + :param x_tensor: TensorFlow Tensor + :param conv_num_outputs: Number of outputs for the convolutional layer + :param conv_ksize: kernal size 2-D Tuple for the convolutional layer + :param conv_strides: Stride 2-D Tuple for convolution + :param pool_ksize: kernal size 2-D Tuple for pool + :param pool_strides: Stride 2-D Tuple for pool + : return: A tensor that represents convolution and max pooling of x_tensor + """ + # TODO: Implement Function + return None + +def flatten(x_tensor): + """ + Flatten x_tensor to (Batch Size, Flattened Image Size) + : x_tensor: A tensor of size (Batch Size, ...), where ... are the image dimensions. + : return: A tensor of size (Batch Size, Flattened Image Size). + """ + # TODO: Implement Function + return None + +def fully_conn(x_tensor, num_outputs): + """ + Apply a fully connected layer to x_tensor using weight and bias + : x_tensor: A 2-D tensor where the first dimension is batch size. + : num_outputs: The number of output that the new tensor should be. + : return: A 2-D tensor where the second dimension is num_outputs. + """ + # TODO: Implement Function + return None + +def output(x_tensor, num_outputs): + """ + Apply a output layer to x_tensor using weight and bias + : x_tensor: A 2-D tensor where the first dimension is batch size. + : num_outputs: The number of output that the new tensor should be. + : return: A 2-D tensor where the second dimension is num_outputs. + """ + # TODO: Implement Function + return None + +def conv_net(x, keep_prob): + """ + Create a convolutional neural network model + : x: Placeholder tensor that holds image data. + : keep_prob: Placeholder tensor that hold dropout keep probability. + : return: Tensor that represents logits + """ + # TODO: Apply 1, 2, or 3 Convolution and Max Pool layers + # Play around with different number of outputs, kernel size and stride + # Function Definition from Above: + # conv2d_maxpool(x_tensor, conv_num_outputs, conv_ksize, conv_strides, pool_ksize, pool_strides) + + + # TODO: Apply a Flatten Layer + # Function Definition from Above: + # flatten(x_tensor) + + + # TODO: Apply 1, 2, or 3 Fully Connected Layers + # Play around with different number of outputs + # Function Definition from Above: + # fully_conn(x_tensor, num_outputs) + + + # TODO: Apply an Output Layer + # Set this to the number of classes + # Function Definition from Above: + # output(x_tensor, num_outputs) + + + # TODO: return output + return None + +def train_neural_network(session, optimizer, keep_probability, feature_batch, label_batch): + """ + Optimize the session on a batch of images and labels + : session: Current TensorFlow session + : optimizer: TensorFlow optimizer function + : keep_probability: keep probability + : feature_batch: Batch of Numpy image data + : label_batch: Batch of Numpy label data + """ + # TODO: Implement Function + pass + +def print_stats(session, feature_batch, label_batch, cost, accuracy): + """ + Print information about loss and validation accuracy + : session: Current TensorFlow session + : feature_batch: Batch of Numpy image data + : label_batch: Batch of Numpy label data + : cost: TensorFlow cost function + : accuracy: TensorFlow accuracy function + """ + # TODO: Implement Function + pass diff --git a/image-classification/problem_unittests.py b/image-classification/problem_unittests.py deleted file mode 100644 index 35af490c1f..0000000000 --- a/image-classification/problem_unittests.py +++ /dev/null @@ -1,208 +0,0 @@ -import os -import numpy as np -import tensorflow as tf -import random -from unittest.mock import MagicMock - - -def _print_success_message(): - print('Tests Passed') - - -def test_folder_path(cifar10_dataset_folder_path): - assert cifar10_dataset_folder_path is not None,\ - 'Cifar-10 data folder not set.' - assert cifar10_dataset_folder_path[-1] != '/',\ - 'The "/" shouldn\'t be added to the end of the path.' - assert os.path.exists(cifar10_dataset_folder_path),\ - 'Path not found.' - assert os.path.isdir(cifar10_dataset_folder_path),\ - '{} is not a folder.'.format(os.path.basename(cifar10_dataset_folder_path)) - - train_files = [cifar10_dataset_folder_path + '/data_batch_' + str(batch_id) for batch_id in range(1, 6)] - other_files = [cifar10_dataset_folder_path + '/batches.meta', cifar10_dataset_folder_path + '/test_batch'] - missing_files = [path for path in train_files + other_files if not os.path.exists(path)] - - assert not missing_files,\ - 'Missing files in directory: {}'.format(missing_files) - - print('All files found!') - - -def test_normalize(normalize): - test_shape = (np.random.choice(range(1000)), 32, 32, 3) - test_numbers = np.random.choice(range(256), test_shape) - normalize_out = normalize(test_numbers) - - assert type(normalize_out).__module__ == np.__name__,\ - 'Not Numpy Object' - - assert normalize_out.shape == test_shape,\ - 'Incorrect Shape. {} shape found'.format(normalize_out.shape) - - assert normalize_out.max() <= 1 and normalize_out.min() >= 0,\ - 'Incorect Range. {} to {} found'.format(normalize_out.min(), normalize_out.max()) - - _print_success_message() - - -def test_one_hot_encode(one_hot_encode): - test_shape = np.random.choice(range(1000)) - test_numbers = np.random.choice(range(10), test_shape) - one_hot_out = one_hot_encode(test_numbers) - - assert type(one_hot_out).__module__ == np.__name__,\ - 'Not Numpy Object' - - assert one_hot_out.shape == (test_shape, 10),\ - 'Incorrect Shape. {} shape found'.format(one_hot_out.shape) - - n_encode_tests = 5 - test_pairs = list(zip(test_numbers, one_hot_out)) - test_indices = np.random.choice(len(test_numbers), n_encode_tests) - labels = [test_pairs[test_i][0] for test_i in test_indices] - enc_labels = np.array([test_pairs[test_i][1] for test_i in test_indices]) - new_enc_labels = one_hot_encode(labels) - - assert np.array_equal(enc_labels, new_enc_labels),\ - 'Encodings returned different results for the same numbers.\n' \ - 'For the first call it returned:\n' \ - '{}\n' \ - 'For the second call it returned\n' \ - '{}\n' \ - 'Make sure you save the map of labels to encodings outside of the function.'.format(enc_labels, new_enc_labels) - - for one_hot in new_enc_labels: - assert (one_hot==1).sum() == 1,\ - 'Each one-hot-encoded value should include the number 1 exactly once.\n' \ - 'Found {}\n'.format(one_hot) - assert (one_hot==0).sum() == len(one_hot)-1,\ - 'Each one-hot-encoded value should include zeros in all but one position.\n' \ - 'Found {}\n'.format(one_hot) - - - _print_success_message() - - -def test_nn_image_inputs(neural_net_image_input): - image_shape = (32, 32, 3) - nn_inputs_out_x = neural_net_image_input(image_shape) - - assert nn_inputs_out_x.get_shape().as_list() == [None, image_shape[0], image_shape[1], image_shape[2]],\ - 'Incorrect Image Shape. Found {} shape'.format(nn_inputs_out_x.get_shape().as_list()) - - assert nn_inputs_out_x.op.type == 'Placeholder',\ - 'Incorrect Image Type. Found {} type'.format(nn_inputs_out_x.op.type) - - assert nn_inputs_out_x.name == 'x:0', \ - 'Incorrect Name. Found {}'.format(nn_inputs_out_x.name) - - print('Image Input Tests Passed.') - - -def test_nn_label_inputs(neural_net_label_input): - n_classes = 10 - nn_inputs_out_y = neural_net_label_input(n_classes) - - assert nn_inputs_out_y.get_shape().as_list() == [None, n_classes],\ - 'Incorrect Label Shape. Found {} shape'.format(nn_inputs_out_y.get_shape().as_list()) - - assert nn_inputs_out_y.op.type == 'Placeholder',\ - 'Incorrect Label Type. Found {} type'.format(nn_inputs_out_y.op.type) - - assert nn_inputs_out_y.name == 'y:0', \ - 'Incorrect Name. Found {}'.format(nn_inputs_out_y.name) - - print('Label Input Tests Passed.') - - -def test_nn_keep_prob_inputs(neural_net_keep_prob_input): - nn_inputs_out_k = neural_net_keep_prob_input() - - assert nn_inputs_out_k.get_shape().ndims is None,\ - 'Too many dimensions found for keep prob. Found {} dimensions. It should be a scalar (0-Dimension Tensor).'.format(nn_inputs_out_k.get_shape().ndims) - - assert nn_inputs_out_k.op.type == 'Placeholder',\ - 'Incorrect keep prob Type. Found {} type'.format(nn_inputs_out_k.op.type) - - assert nn_inputs_out_k.name == 'keep_prob:0', \ - 'Incorrect Name. Found {}'.format(nn_inputs_out_k.name) - - print('Keep Prob Tests Passed.') - - -def test_con_pool(conv2d_maxpool): - test_x = tf.placeholder(tf.float32, [None, 32, 32, 5]) - test_num_outputs = 10 - test_con_k = (2, 2) - test_con_s = (4, 4) - test_pool_k = (2, 2) - test_pool_s = (2, 2) - - conv2d_maxpool_out = conv2d_maxpool(test_x, test_num_outputs, test_con_k, test_con_s, test_pool_k, test_pool_s) - - assert conv2d_maxpool_out.get_shape().as_list() == [None, 4, 4, 10],\ - 'Incorrect Shape. Found {} shape'.format(conv2d_maxpool_out.get_shape().as_list()) - - _print_success_message() - - -def test_flatten(flatten): - test_x = tf.placeholder(tf.float32, [None, 10, 30, 6]) - flat_out = flatten(test_x) - - assert flat_out.get_shape().as_list() == [None, 10*30*6],\ - 'Incorrect Shape. Found {} shape'.format(flat_out.get_shape().as_list()) - - _print_success_message() - - -def test_fully_conn(fully_conn): - test_x = tf.placeholder(tf.float32, [None, 128]) - test_num_outputs = 40 - - fc_out = fully_conn(test_x, test_num_outputs) - - assert fc_out.get_shape().as_list() == [None, 40],\ - 'Incorrect Shape. Found {} shape'.format(fc_out.get_shape().as_list()) - - _print_success_message() - - -def test_output(output): - test_x = tf.placeholder(tf.float32, [None, 128]) - test_num_outputs = 40 - - output_out = output(test_x, test_num_outputs) - - assert output_out.get_shape().as_list() == [None, 40],\ - 'Incorrect Shape. Found {} shape'.format(output_out.get_shape().as_list()) - - _print_success_message() - - -def test_conv_net(conv_net): - test_x = tf.placeholder(tf.float32, [None, 32, 32, 3]) - test_k = tf.placeholder(tf.float32) - - logits_out = conv_net(test_x, test_k) - - assert logits_out.get_shape().as_list() == [None, 10],\ - 'Incorrect Model Output. Found {}'.format(logits_out.get_shape().as_list()) - - print('Neural Network Built!') - - -def test_train_nn(train_neural_network): - mock_session = tf.Session() - test_x = np.random.rand(128, 32, 32, 3) - test_y = np.random.rand(128, 10) - test_k = np.random.rand(1) - test_optimizer = tf.train.AdamOptimizer() - - mock_session.run = MagicMock() - train_neural_network(mock_session, test_optimizer, test_k, test_x, test_y) - - assert mock_session.run.called, 'Session not used' - - _print_success_message() diff --git a/image-classification/test_my_answers.py b/image-classification/test_my_answers.py new file mode 100644 index 0000000000..8d9d0b5999 --- /dev/null +++ b/image-classification/test_my_answers.py @@ -0,0 +1,174 @@ +import os +import sys +import numpy as np +import tensorflow as tf +import random +import unittest +from unittest.mock import MagicMock + +import my_answers + +class ImageClassificationTest(unittest.TestCase): + + def test_normalize(self): + """normalize is correctly implemented""" + test_shape = (np.random.choice(range(1000)), 32, 32, 3) + test_numbers = np.random.choice(range(256), test_shape) + normalize_out = my_answers.normalize(test_numbers) + + self.assertEqual(type(normalize_out).__module__, np.__name__,\ + 'Not Numpy Object') + + self.assertEqual(normalize_out.shape, test_shape,\ + 'Incorrect Shape. {} shape found'.format(normalize_out.shape)) + + self.assertTrue(normalize_out.max() <= 1 and normalize_out.min() >= 0,\ + 'Incorrect Range. {} to {} found'.format(normalize_out.min(), normalize_out.max())) + + def test_one_hot_encode(self): + """one_hot_encode is correctly implemented""" + test_shape = np.random.choice(range(1000)) + test_numbers = np.random.choice(range(10), test_shape) + one_hot_out = my_answers.one_hot_encode(test_numbers) + + self.assertEqual(type(one_hot_out).__module__, np.__name__,\ + 'Not Numpy Object') + + self.assertEqual(one_hot_out.shape, (test_shape, 10),\ + 'Incorrect Shape. {} shape found'.format(one_hot_out.shape)) + + n_encode_tests = 5 + test_pairs = list(zip(test_numbers, one_hot_out)) + test_indices = np.random.choice(len(test_numbers), n_encode_tests) + labels = [test_pairs[test_i][0] for test_i in test_indices] + enc_labels = np.array([test_pairs[test_i][1] for test_i in test_indices]) + new_enc_labels = my_answers.one_hot_encode(labels) + + self.assertTrue(np.array_equal(enc_labels, new_enc_labels),\ + 'Encodings returned different results for the same numbers.\n' \ + 'For the first call it returned:\n' \ + '{}\n' \ + 'For the second call it returned\n' \ + '{}\n' \ + 'Make sure you save the map of labels to encodings outside of the function.'.format(enc_labels, new_enc_labels)) + + for one_hot in new_enc_labels: + self.assertEqual((one_hot==1).sum(), 1,\ + 'Each one-hot-encoded value should include the number 1 exactly once.\n' \ + 'Found {}\n'.format(one_hot)) + self.assertEqual((one_hot==0).sum(), len(one_hot)-1,\ + 'Each one-hot-encoded value should include zeros in all but one position.\n' \ + 'Found {}\n'.format(one_hot)) + + def test_nn_image_inputs(self): + """nn_image_inputs is correctly implemented""" + image_shape = (32, 32, 3) + nn_inputs_out_x = my_answers.neural_net_image_input(image_shape) + + self.assertEqual(nn_inputs_out_x.get_shape().as_list(), [None, image_shape[0], image_shape[1], image_shape[2]],\ + 'Incorrect Image Shape. Found {} shape'.format(nn_inputs_out_x.get_shape().as_list())) + + self.assertEquals(nn_inputs_out_x.op.type,'Placeholder',\ + 'Incorrect Image Type. Found {} type'.format(nn_inputs_out_x.op.type)) + + self.assertEqual(nn_inputs_out_x.name, 'x:0', \ + 'Incorrect Name. Found {}'.format(nn_inputs_out_x.name)) + + def test_nn_label_inputs(self): + """test_nn_label_inputs is correctly implemented""" + n_classes = 10 + nn_inputs_out_y = my_answers.neural_net_label_input(n_classes) + + self.assertEqual(nn_inputs_out_y.get_shape().as_list(), [None, n_classes],\ + 'Incorrect Label Shape. Found {} shape'.format(nn_inputs_out_y.get_shape().as_list())) + + self.assertEqual(nn_inputs_out_y.op.type, 'Placeholder',\ + 'Incorrect Label Type. Found {} type'.format(nn_inputs_out_y.op.type)) + + self.assertEqual(nn_inputs_out_y.name, 'y:0', \ + 'Incorrect Name. Found {}'.format(nn_inputs_out_y.name)) + + def test_nn_keep_prob_inputs(self): + """test_nn_keep_prob_inputs is correctly implemented""" + nn_inputs_out_k = my_answers.neural_net_keep_prob_input() + + self.assertTrue(nn_inputs_out_k.get_shape().ndims is None,\ + 'Too many dimensions found for keep prob. Found {} dimensions. It should be a scalar (0-Dimension Tensor).'.format(nn_inputs_out_k.get_shape().ndims)) + + self.assertEqual(nn_inputs_out_k.op.type, 'Placeholder',\ + 'Incorrect keep prob Type. Found {} type'.format(nn_inputs_out_k.op.type)) + + self.assertEqual(nn_inputs_out_k.name, 'keep_prob:0', \ + 'Incorrect Name. Found {}'.format(nn_inputs_out_k.name)) + + + def test_con_pool(self): + """con_pool is correctly implemented""" + test_x = tf.placeholder(tf.float32, [None, 32, 32, 5]) + test_num_outputs = 10 + test_con_k = (2, 2) + test_con_s = (4, 4) + test_pool_k = (2, 2) + test_pool_s = (2, 2) + + conv2d_maxpool_out = my_answers.conv2d_maxpool(test_x, test_num_outputs, test_con_k, test_con_s, test_pool_k, test_pool_s) + + self.assertEqual(conv2d_maxpool_out.get_shape().as_list(), [None, 4, 4, 10],\ + 'Incorrect Shape. Found {} shape'.format(conv2d_maxpool_out.get_shape().as_list())) + + def test_flatten(self): + """flatten is correctly implemented""" + test_x = tf.placeholder(tf.float32, [None, 10, 30, 6]) + flat_out = my_answers.flatten(test_x) + + self.assertEqual(flat_out.get_shape().as_list(), [None, 10*30*6],\ + 'Incorrect Shape. Found {} shape'.format(flat_out.get_shape().as_list())) + + def test_fully_conn(self): + """fully_conn is correctly implemented""" + test_x = tf.placeholder(tf.float32, [None, 128]) + test_num_outputs = 40 + + fc_out = my_answers.fully_conn(test_x, test_num_outputs) + + self.assertEqual(fc_out.get_shape().as_list(), [None, 40],\ + 'Incorrect Shape. Found {} shape'.format(fc_out.get_shape().as_list())) + + def test_output(self): + """output is correctly implemented""" + test_x = tf.placeholder(tf.float32, [None, 128]) + test_num_outputs = 40 + + output_out = my_answers.output(test_x, test_num_outputs) + + self.assertEqual(output_out.get_shape().as_list(), [None, 40],\ + 'Incorrect Shape. Found {} shape'.format(output_out.get_shape().as_list())) + + def test_conv_net(self): + """conv_net is correctly implemented""" + test_x = tf.placeholder(tf.float32, [None, 32, 32, 3]) + test_k = tf.placeholder(tf.float32) + + logits_out = my_answers.conv_net(test_x, test_k) + + self.assertEqual(logits_out.get_shape().as_list(), [None, 10],\ + 'Incorrect Model Output. Found {}'.format(logits_out.get_shape().as_list())) + + def test_train_nn(self): + """train_nn invokes a tf session""" + mock_session = tf.Session() + test_x = np.random.rand(128, 32, 32, 3) + test_y = np.random.rand(128, 10) + test_k = np.random.rand(1) + test_optimizer = tf.train.AdamOptimizer() + + mock_session.run = MagicMock() + my_answers.train_neural_network(mock_session, test_optimizer, test_k, test_x, test_y) + + self.assertTrue(mock_session.run.called, 'Session not used') + +def run(test_name): + unittest.TextTestRunner().run(ImageClassificationTest(test_name)) + +if __name__ == '__main__': + run('test_normalize') From 9c13b88e04a620d0789eb19291eda561cf5387bd Mon Sep 17 00:00:00 2001 From: scbrubaker02 Date: Thu, 24 Aug 2017 12:52:41 -0400 Subject: [PATCH 2/3] Added .udacity-pa directory for first neural network project --- first-neural-network/.udacity-pa/projects.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 first-neural-network/.udacity-pa/projects.py diff --git a/first-neural-network/.udacity-pa/projects.py b/first-neural-network/.udacity-pa/projects.py new file mode 100644 index 0000000000..2fb653b295 --- /dev/null +++ b/first-neural-network/.udacity-pa/projects.py @@ -0,0 +1,16 @@ +import argparse +import subprocess as sp +from udacity_pa import udacity + +nanodegree = 'nd101' +projects = ['first_neural_network'] +filenames = ['my_answers.py', 'Your_first_neural_network.ipynb'] + +def submit(args): + + # Do we prefer ipynb, html or both? + # sp.call(['jupyter', 'nbconvert', '--to', 'html', 'dlnd_image_classification.ipynb']) + + udacity.submit(nanodegree, projects[0], filenames, + environment = args.environment, + jwt_path = args.jwt_path) From 067179a6b910ce3fe1fc45fa93952299a6027ef2 Mon Sep 17 00:00:00 2001 From: Luke Rucks Date: Thu, 21 Sep 2017 08:41:05 -0700 Subject: [PATCH 3/3] Refactor out student code and write tests Refactored all student written code from Jupiter notebook to my_answers.py file; wrote tests for complete auto grading --- .../Your_first_neural_network.ipynb | 113 ++------------ .../assets/neural_network.png | Bin first-neural-network/my_answers.py | 108 ++++++++++++++ first-neural-network/requirements.txt | 0 first-neural-network/test_my_answers.py | 139 ++++++++++++++++++ 5 files changed, 259 insertions(+), 101 deletions(-) mode change 100644 => 100755 first-neural-network/assets/neural_network.png create mode 100644 first-neural-network/my_answers.py mode change 100644 => 100755 first-neural-network/requirements.txt create mode 100755 first-neural-network/test_my_answers.py diff --git a/first-neural-network/Your_first_neural_network.ipynb b/first-neural-network/Your_first_neural_network.ipynb index 1e6492063b..97eccfae7b 100644 --- a/first-neural-network/Your_first_neural_network.ipynb +++ b/first-neural-network/Your_first_neural_network.ipynb @@ -216,102 +216,11 @@ }, "outputs": [], "source": [ - "class NeuralNetwork(object):\n", - " def __init__(self, input_nodes, hidden_nodes, output_nodes, learning_rate):\n", - " # Set number of nodes in input, hidden and output layers.\n", - " self.input_nodes = input_nodes\n", - " self.hidden_nodes = hidden_nodes\n", - " self.output_nodes = output_nodes\n", - "\n", - " # Initialize weights\n", - " self.weights_input_to_hidden = np.random.normal(0.0, self.input_nodes**-0.5, \n", - " (self.input_nodes, self.hidden_nodes))\n", - "\n", - " self.weights_hidden_to_output = np.random.normal(0.0, self.hidden_nodes**-0.5, \n", - " (self.hidden_nodes, self.output_nodes))\n", - " self.lr = learning_rate\n", - " \n", - " #### TODO: Set self.activation_function to your implemented sigmoid function ####\n", - " #\n", - " # Note: in Python, you can define a function with a lambda expression,\n", - " # as shown below.\n", - " self.activation_function = lambda x : 0 # Replace 0 with your sigmoid calculation.\n", - " \n", - " ### If the lambda code above is not something you're familiar with,\n", - " # You can uncomment out the following three lines and put your \n", - " # implementation there instead.\n", - " #\n", - " #def sigmoid(x):\n", - " # return 0 # Replace 0 with your sigmoid calculation here\n", - " #self.activation_function = sigmoid\n", - " \n", - " \n", - " def train(self, features, targets):\n", - " ''' Train the network on batch of features and targets. \n", - " \n", - " Arguments\n", - " ---------\n", - " \n", - " features: 2D array, each row is one data record, each column is a feature\n", - " targets: 1D array of target values\n", - " \n", - " '''\n", - " n_records = features.shape[0]\n", - " delta_weights_i_h = np.zeros(self.weights_input_to_hidden.shape)\n", - " delta_weights_h_o = np.zeros(self.weights_hidden_to_output.shape)\n", - " for X, y in zip(features, targets):\n", - " #### Implement the forward pass here ####\n", - " ### Forward pass ###\n", - " # TODO: Hidden layer - Replace these values with your calculations.\n", - " hidden_inputs = None # signals into hidden layer\n", - " hidden_outputs = None # signals from hidden layer\n", - "\n", - " # TODO: Output layer - Replace these values with your calculations.\n", - " final_inputs = None # signals into final output layer\n", - " final_outputs = None # signals from final output layer\n", - " \n", - " #### Implement the backward pass here ####\n", - " ### Backward pass ###\n", - "\n", - " # TODO: Output error - Replace this value with your calculations.\n", - " error = None # Output layer error is the difference between desired target and actual output.\n", - " \n", - " # TODO: Calculate the backpropagated error term (delta) for the output \n", - " output_error_term = None\n", - " \n", - " # TODO: Calculate the hidden layer's contribution to the error\n", - " hidden_error = None\n", - " \n", - " # TODO: Calculate the backpropagated error term (delta) for the hidden layer\n", - " hidden_error_term = None\n", - "\n", - " # Weight step (input to hidden)\n", - " delta_weights_i_h += None\n", - " # Weight step (hidden to output)\n", - " delta_weights_h_o += None\n", - "\n", - " # TODO: Update the weights - Replace these values with your calculations.\n", - " self.weights_hidden_to_output += None # update hidden-to-output weights with gradient descent step\n", - " self.weights_input_to_hidden += None # update input-to-hidden weights with gradient descent step\n", - " \n", - " def run(self, features):\n", - " ''' Run a forward pass through the network with input features \n", - " \n", - " Arguments\n", - " ---------\n", - " features: 1D array of feature values\n", - " '''\n", - " \n", - " #### Implement the forward pass here ####\n", - " # TODO: Hidden layer - replace these values with the appropriate calculations.\n", - " hidden_inputs = None # signals into hidden layer\n", - " hidden_outputs = None # signals from hidden layer\n", - " \n", - " # TODO: Output layer - Replace these values with the appropriate calculations.\n", - " final_inputs = None # signals into final output layer\n", - " final_outputs = None # signals from final output layer \n", - " \n", - " return final_outputs" + "#############\n", + "# In the my_answers.py file, fill out the TODO sections as specified\n", + "#############\n", + "\n", + "from my_answers import NeuralNetwork" ] }, { @@ -435,11 +344,13 @@ "source": [ "import sys\n", "\n", - "### Set the hyperparameters here ###\n", - "iterations = 100\n", - "learning_rate = 0.1\n", - "hidden_nodes = 2\n", - "output_nodes = 1\n", + "####################\n", + "### Set the hyperparameters in you myanswers.py file ###\n", + "####################\n", + "\n", + "from myanswers import iterations, learning_rate, \n", + " hidden_nodes, output_nodes\n", + "\n", "\n", "N_i = train_features.shape[1]\n", "network = NeuralNetwork(N_i, hidden_nodes, output_nodes, learning_rate)\n", diff --git a/first-neural-network/assets/neural_network.png b/first-neural-network/assets/neural_network.png old mode 100644 new mode 100755 diff --git a/first-neural-network/my_answers.py b/first-neural-network/my_answers.py new file mode 100644 index 0000000000..614553be49 --- /dev/null +++ b/first-neural-network/my_answers.py @@ -0,0 +1,108 @@ +import numpy as np + + +class NeuralNetwork(object): + def __init__(self, input_nodes, hidden_nodes, output_nodes, learning_rate): + # Set number of nodes in input, hidden and output layers. + self.input_nodes = input_nodes + self.hidden_nodes = hidden_nodes + self.output_nodes = output_nodes + + # Initialize weights + self.weights_input_to_hidden = np.random.normal(0.0, self.input_nodes**-0.5, + (self.input_nodes, self.hidden_nodes)) + + self.weights_hidden_to_output = np.random.normal(0.0, self.hidden_nodes**-0.5, + (self.hidden_nodes, self.output_nodes)) + self.lr = learning_rate + + #### TODO: Set self.activation_function to your implemented sigmoid function #### + # + # Note: in Python, you can define a function with a lambda expression, + # as shown below. + self.activation_function = lambda x : 0 # Replace 0 with your sigmoid calculation. + + ### If the lambda code above is not something you're familiar with, + # You can uncomment out the following three lines and put your + # implementation there instead. + # + #def sigmoid(x): + # return 0 # Replace 0 with your sigmoid calculation here + #self.activation_function = sigmoid + + + def train(self, features, targets): + ''' Train the network on batch of features and targets. + + Arguments + --------- + + features: 2D array, each row is one data record, each column is a feature + targets: 1D array of target values + + ''' + n_records = features.shape[0] + delta_weights_i_h = np.zeros(self.weights_input_to_hidden.shape) + delta_weights_h_o = np.zeros(self.weights_hidden_to_output.shape) + for X, y in zip(features, targets): + #### Implement the forward pass here #### + ### Forward pass ### + # TODO: Hidden layer - Replace these values with your calculations. + hidden_inputs = None # signals into hidden layer + hidden_outputs = None # signals from hidden layer + + # TODO: Output layer - Replace these values with your calculations. + final_inputs = None # signals into final output layer + final_outputs = None # signals from final output layer + + #### Implement the backward pass here #### + ### Backward pass ### + + # TODO: Output error - Replace this value with your calculations. + error = None # Output layer error is the difference between desired target and actual output. + + # TODO: Calculate the backpropagated error term (delta) for the output + output_error_term = None + + # TODO: Calculate the hidden layer's contribution to the error + hidden_error = None + + # TODO: Calculate the backpropagated error term (delta) for the hidden layer + hidden_error_term = None + + # Weight step (input to hidden) + delta_weights_i_h += None + # Weight step (hidden to output) + delta_weights_h_o += None + + # TODO: Update the weights - Replace these values with your calculations. + self.weights_hidden_to_output += None # update hidden-to-output weights with gradient descent step + self.weights_input_to_hidden += None # update input-to-hidden weights with gradient descent step + + def run(self, features): + ''' Run a forward pass through the network with input features + + Arguments + --------- + features: 1D array of feature values + ''' + + #### Implement the forward pass here #### + # TODO: Hidden layer - replace these values with the appropriate calculations. + hidden_inputs = None # signals into hidden layer + hidden_outputs = None # signals from hidden layer + + # TODO: Output layer - Replace these values with the appropriate calculations. + final_inputs = None # signals into final output layer + final_outputs = None # signals from final output layer + + return final_outputs + + +######################################################### +# Set your hyperparameters here +########################################################## +iterations = 100 +learning_rate = 0.1 +hidden_nodes = 2 +output_nodes = 1 diff --git a/first-neural-network/requirements.txt b/first-neural-network/requirements.txt old mode 100644 new mode 100755 diff --git a/first-neural-network/test_my_answers.py b/first-neural-network/test_my_answers.py new file mode 100755 index 0000000000..6f1049fd10 --- /dev/null +++ b/first-neural-network/test_my_answers.py @@ -0,0 +1,139 @@ +import os +import sys +import numpy as np +import pandas as pd +from my_answers import NeuralNetwork +from my_answers import iterations, learning_rate, hidden_nodes, output_nodes +import unittest + + +def MSE(y, Y): + return np.mean((y - Y) ** 2) + + +class FirstNNTestMethods(unittest.TestCase): + + ########## + # Unit tests for data loading + ########## + + def test_data_path(self): + # Test that file path to dataset has been unaltered + self.assertTrue(data_path.lower() == 'bike-sharing-dataset/hour.csv') + + def test_data_loaded(self): + # Test that data frame loaded + self.assertTrue(isinstance(rides, pd.DataFrame)) + + ########## + # Unit tests for network functionality + ########## + + def test_activation(self): + network = NeuralNetwork(3, 2, 1, 0.5) + # Test that the activation function is a sigmoid + self.assertTrue(np.all(network.activation_function(0.5) == 1/(1+np.exp(-0.5)))) + + def test_train(self): + # Test that weights are updated correctly on training + network = NeuralNetwork(3, 2, 1, 0.5) + network.weights_input_to_hidden = test_w_i_h.copy() + network.weights_hidden_to_output = test_w_h_o.copy() + + network.train(inputs, targets) + self.assertTrue(np.allclose(network.weights_hidden_to_output, + np.array([[0.37275328], + [-0.03172939]]))) + self.assertTrue(np.allclose(network.weights_input_to_hidden, + np.array([[0.10562014, -0.20185996], + [0.39775194, 0.50074398], + [-0.29887597, 0.19962801]]))) + + def test_run(self): + # Test correctness of run method + network = NeuralNetwork(3, 2, 1, 0.5) + network.weights_input_to_hidden = test_w_i_h.copy() + network.weights_hidden_to_output = test_w_h_o.copy() + + self.assertTrue(np.allclose(network.run(inputs), 0.09998924)) + + def test_hyperparameters(self): + bounds = [[50, 15000], [0.05, 5], [5, 100], [1, 1]] + actual = [iterations, learning_rate, hidden_nodes, output_nodes] + for ii in range(4): + self.assertTrue(bounds[ii][0] <= actual[ii] <= bounds[ii][1]) + + def test_results(self): + # Test results of running network on full data + self.assertTrue(sum(losses['train'][-20:]) / 20.0 < 0.09) + self.assertTrue(sum(losses['validation'][-20:]) / 20.0 < 0.18) + + +if __name__ == '__main__': + data_path = 'Bike-Sharing-Dataset/hour.csv' + + rides = pd.read_csv(data_path) + + dummy_fields = ['season', 'weathersit', 'mnth', 'hr', 'weekday'] + for each in dummy_fields: + dummies = pd.get_dummies(rides[each], prefix=each, drop_first=False) + rides = pd.concat([rides, dummies], axis=1) + + fields_to_drop = ['instant', 'dteday', 'season', 'weathersit', + 'weekday', 'atemp', 'mnth', 'workingday', 'hr'] + data = rides.drop(fields_to_drop, axis=1) + + quant_features = ['casual', 'registered', 'cnt', + 'temp', 'hum', 'windspeed'] + # Store scalings in a dictionary so we can convert back later + scaled_features = {} + for each in quant_features: + mean, std = data[each].mean(), data[each].std() + scaled_features[each] = [mean, std] + data.loc[:, each] = (data[each] - mean) / std + + # Save data for approximately the last 21 days + test_data = data[-21 * 24:] + + # Now remove the test data from the data set + data = data[:-21 * 24] + + # Separate the data into features and targets + target_fields = ['cnt', 'casual', 'registered'] + features, targets = data.drop(target_fields, axis=1), data[target_fields] + test_features, test_targets = test_data.drop(target_fields, axis=1), test_data[target_fields] + + # Hold out the last 60 days or so of the remaining data as a validation set + train_features, train_targets = features[:-60 * 24], targets[:-60 * 24] + val_features, val_targets = features[-60 * 24:], targets[-60 * 24:] + + N_i = train_features.shape[1] + network = NeuralNetwork(N_i, hidden_nodes, output_nodes, learning_rate) + + losses = {'train': [], 'validation': []} + for ii in range(iterations): + # Go through a random batch of 128 records from the training data set + batch = np.random.choice(train_features.index, size=128) + X, y = train_features.ix[batch].values, train_targets.ix[batch]['cnt'] + + network.train(X, y) + + # Printing out the training progress + train_loss = MSE(network.run(train_features).T, train_targets['cnt'].values) + val_loss = MSE(network.run(val_features).T, val_targets['cnt'].values) + + losses['train'].append(train_loss) + losses['validation'].append(val_loss) + + # Test inputs to test network + inputs = np.array([[0.5, -0.2, 0.1]]) + targets = np.array([[0.4]]) + test_w_i_h = np.array([[0.1, -0.2], + [0.4, 0.5], + [-0.3, 0.2]]) + test_w_h_o = np.array([[0.3], + [-0.1]]) + + #Run the tests + suite = unittest.TestLoader().loadTestsFromModule(FirstNNTestMethods()) + unittest.TextTestRunner().run(suite)