From 8eaa3abd5b6b23e232ed1007631b1005a5a5e5c3 Mon Sep 17 00:00:00 2001 From: Alex Huddleston Date: Fri, 1 Dec 2017 19:14:32 +0000 Subject: [PATCH] Started a preliminary jupyter notebook with comments. Updated README. --- README.md | 141 +++++++++++++++++++++++++++- neural_network.ipynb | 215 +++++++++++++++++++++++++++++++++++++++++++ test.py | 2 +- 3 files changed, 356 insertions(+), 2 deletions(-) create mode 100644 neural_network.ipynb diff --git a/README.md b/README.md index 50c48b6..9bec3b1 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ See 420Project17fall.pdf -use this script to download the data files, because I'm not hosting them here. +Use this script to download the data files, because I'm not hosting them here. ~~~~ mkdir "data" @@ -9,3 +9,142 @@ do wget "http://courses.cse.tamu.edu/daugher/misc/PPP/homeworks/data/${i}states.bin" -O "data/${i}.bin" done ~~~~ + +I didn't include that as a shell script file because it's really better +in general for one to see the shell code they're running before they just +blindly trust a script to do what they want it to do. + +# Setup + +## Anaconda/Miniconda (optional) + +For my implementation, I'm using a native Python 3 install on Linux. + +However, if you want to be safe about preserving your Python environment +(essentially, if you want to compartmentalize your Python install so if you +mess up it won't affect your native Python environment), I suggest +instead installing Anaconda or Miniconda and going through the following process +from there in your terminal: + +~~~ +conda create -n project420 python +conda install -n project420 jupyter +conda install -n project420 tensorflow +conda install -n project420 keras +~~~ + +You can replace project420 with whatever you want to call the environment. + +After those are installed, when you want to activate that Python environment, +(which you'll have to do if you open a new terminal window) type: +~~~ +source activate project420 +~~~ + +## Installing natively + +### Linux + +If you would rather just install the necessary things to your native Python +environment, then here are the things you will need if you're on Linux: + +- TensorFlow (or equivalent backend for Keras) +- Keras +- Jupyter + +I suggest installing them through your respective repository's repos if you can. + +### Windows + +Well... I didn't set up on Windows, but the packages you will need remain the same. + +I would suggest considering using the native pip install method: + +~~~ +pip install tensorflow +pip install keras +pip install jupyter +~~~ + +# Getting Started + +## Parsing the .bin files + +Basically, we're being instructed to parse through these .bin files in order +to get "states" of a 15-piece puzzle, illustrated in the project documentation. + +Each of these n.bin files contains the corresponding states that are n many +turns away from the solution. That part of the instruction is essential to +understand before we go any further. +To illustrate better: this means that 0.bin contains every state in which +the puzzle is 0 moves away from being solved, and so on for each n.bin file. + +In order to parse these binary files, we need to tell python to read in the +file in binary mode and then we need to translate that binary to a hex string +format. I've already written out some preliminary code that will do the for +you in the included "test.py" script. + +Just run: +~~~ +python test.py +~~~ + +and the output that you are given is the only state in the 0.bin file, which +represents the state of the puzzle when it is solved. + +There's a lot of terminology being thrown around in the documentation about +what this hex string means, so I'm going to simplify it: + +Each letter in the hex string represents a 4 bit integer. + +We know that hexadecimal values can only range from 0 to f (or, at least, +you should know considering you are a senior computer science major). + +This means that every 4 bits that we read in correspond to a hexadecimal +character, which represents a value from 0 to 15. These corresponding +values map perfectly to our puzzle to represent which numbered tile is +in which space. If we refer back to our documentation we see that the first +row of the solved puzzle is "1, 2, 3 ,4", and the corresponding first 4 +hex characters of our string are "f, 2, 3, 4", and so on. + +Now you may be questioning why this isn't exactly the same as our puzzle. +This is where the concept of negative entropy can be explained. We don't +need to define what the first place in our puzzle is because we can deduce +it from what we already know. The puzzle only has 16 pieces, and we know +where the other 15 pieces are, so what's left is the piece 1. We remove +the first 4 bits because adding that information is simply unnecessary. + +That much is explained to you now and I hope that can get you started +on understanding what we need to do as far as parsing the bin files. + +## Using Keras + +There are a lot of comments in the included Jupyter Notebook in this +github repo, but here's just how to get started and a brief explanation +of what we're doing here. + +First, you'll want to run jupyter notebook to see what we're doing. + +Jupyter is a tool for python that runs an interactive HTTP server that +can allow users to test python scripts and bits of python code as well +as write reports in an interactive fashion, it's typically used for +research, and what we're doing here will be much more helpful to be +able to quickly run constantly and make modifications. + +To run Jupyter, just type into a terminal: +~~~ +jupyter notebook +~~~ + +This will open an HTTP server that will then open a window in your +current default browser allowing you to select a notebook to open +from your filesystem. + +Or, if you want to directly open the journal from command-line: +~~~ +jupyter notebook neural_network.ipynb +~~~ + +# Well there you go + +I hope that helps you guys get started... LMK if you have more questions. diff --git a/neural_network.ipynb b/neural_network.ipynb new file mode 100644 index 0000000..28b5399 --- /dev/null +++ b/neural_network.ipynb @@ -0,0 +1,215 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Using TensorFlow backend.\n" + ] + } + ], + "source": [ + "# If you're really new to python this code might be\n", + "# a bit unreadable, but I tried to make it as simple\n", + "# as possible.\n", + "\n", + "# Setting up our imported libraries.\n", + "import numpy as np\n", + "from keras.models import Sequential\n", + "from keras.layers import Dense\n", + "\n", + "# We're going to use numpy for some easy\n", + "# array functionality with keras, and keras\n", + "# is our library for handling most of our neural network\n", + "# stuff. That being said, you need to have some sort of\n", + "# backend for keras to work with, such as the recommended\n", + "# TensorFlow, which I'm using here.\n", + "# Since keras uses those as a backend, you don't inherently\n", + "# need to import it." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "240000\n", + "240\n", + "[[ 0.88203814 0.94907443 0.32403829 ..., 0.55091702 0.10493225\n", + " 0.89821938]\n", + " [ 0.02144088 0.15692337 0.99218119 ..., 0.42989668 0.70931057\n", + " 0.61624769]\n", + " [ 0.24650157 0.68008751 0.65118644 ..., 0.44870335 0.3114548\n", + " 0.63668488]\n", + " ..., \n", + " [ 0.6794534 0.05525846 0.7217934 ..., 0.71333628 0.1438383\n", + " 0.07574106]\n", + " [ 0.11292803 0.19181161 0.89034259 ..., 0.60669516 0.11716027\n", + " 0.76495791]\n", + " [ 0.59152954 0.92534686 0.77183522 ..., 0.61204755 0.84179215\n", + " 0.50034833]]\n" + ] + } + ], + "source": [ + "# Generating dummy data so I can understand how to input.\n", + "data = np.random.random((1000,240))\n", + "output = np.random.random((1000, 29))\n", + "\n", + "# Here's some printouts to see exactly what I'm doing here.\n", + "print(data.size)\n", + "print(data[0].size)\n", + "print(data)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch 1/5\n", + "1000/1000 [==============================] - 1s 626us/step - loss: 0.0922 - acc: 0.0370\n", + "Epoch 2/5\n", + "1000/1000 [==============================] - 0s 158us/step - loss: 0.0895 - acc: 0.0360\n", + "Epoch 3/5\n", + "1000/1000 [==============================] - 0s 149us/step - loss: 0.0884 - acc: 0.0340\n", + "Epoch 4/5\n", + "1000/1000 [==============================] - 0s 163us/step - loss: 0.0879 - acc: 0.0310\n", + "Epoch 5/5\n", + "1000/1000 [==============================] - 0s 165us/step - loss: 0.0877 - acc: 0.0340\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Sets up a Sequential model, Sequential is all\n", + "# that should need to be used for this project,\n", + "# considering that it will only be dealing with\n", + "# a linear stack of layers of neurons.\n", + "model = Sequential()\n", + "\n", + "# Adding layers to the model.\n", + "\n", + "# Dense is the type of layer I think, don't need\n", + "# to look into this more since this is all I should\n", + "# need to use.\n", + "\n", + "# units = the number of neurons for this layer.\n", + "\n", + "# activation = the activation function for this layer.\n", + "# our project doc says to use hyperbolic tangent, so\n", + "# I set this to tanh. Except for the output layer,\n", + "# which I set to sigmoid.\n", + "\n", + "# input_dim = the dimension of the input list,\n", + "# should only be set for the input layer.\n", + "\n", + "model.add(Dense(units=240, activation='tanh', input_dim=240))\n", + "model.add(Dense(units=120, activation='tanh'))\n", + "model.add(Dense(units=29, activation='sigmoid'))\n", + "\n", + "# Configure the learning process.\n", + "# \n", + "\n", + "# optimizer = I'm just using \n", + "# Stomchastic gradient descent for this,\n", + "# remember that this uses essentially staggered\n", + "# aggregation by step to calculate gradient\n", + "# descent towards our target, which is faster\n", + "# than doing all of the calculation together.\n", + "\n", + "# loss = the loss function, currently I'm using\n", + "# mean squared error, but might change to\n", + "# mean_absolute_percentage_error, considering\n", + "# I think we're supposed to calculate cost\n", + "# based on the percentage we are away from the\n", + "# correct number of moves away from the solved state.\n", + "\n", + "# metrics = evaluation metrics...\n", + "# I think all I care about is accuracy in this case,\n", + "# if anything.\n", + "\n", + "model.compile(optimizer='sgd',\n", + " loss='mean_squared_error',\n", + " metrics=['accuracy'])\n", + "\n", + "# This is where we're configuring how we train the network:\n", + "\n", + "# data = the input sets of training data for this network,\n", + "# in my case I'm unsure what exactly that will be.\n", + "\n", + "# output = the input sets of target data for the network,\n", + "# I believe this should just be a set of the same size\n", + "# as the training data all containing the number\n", + "# of steps until being solved for each state... I think.\n", + "\n", + "# epochs = it seems like this is how many times this\n", + "# training should be run...\n", + "\n", + "# batch_size = I'm pretty sure this directly correlates\n", + "# to how many input sets we train per step.\n", + "\n", + "model.fit(data, output, epochs=5, batch_size=10)\n", + "\n", + "# Generating predictions should look like this:\n", + "\n", + "# predictions = model.predict(testing_data, batch_size=10)\n", + "\n", + "# I've commented it out since I don't have any real\n", + "# data to predict yet." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "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.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/test.py b/test.py index b7dee32..0c63a35 100644 --- a/test.py +++ b/test.py @@ -1,4 +1,4 @@ -with open('data/0.bin', 'rb') as f: +with open('data/1.bin', 'rb') as f: data = f.read() print(hex(int.from_bytes(data, byteorder='little', signed=False)))