{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Setting up our imported libraries." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from functools import reduce\n", "import numpy as np\n", "from keras.models import Sequential\n", "from keras.layers import Dense\n", "from os.path import join" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Function definitions" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Used to format our input binary state.\n", "\n", "def format_input(acc, elem):\n", " hex_elem = (elem - (elem >> 4 << 4))\n", " for x in range(16):\n", " if x == hex_elem:\n", " acc.append(1)\n", " else:\n", " acc.append(0)\n", " hex_elem = (elem >> 4) % 16\n", " for x in range(16):\n", " if x == hex_elem:\n", " acc.append(1)\n", " else:\n", " acc.append(0)\n", " return acc\n", "\n", "# Calculate Manhattan distance between two points.\n", "\n", "def man_dist(x, y):\n", " for a, b in zip(x, y):\n", " a_one, a_two = x\n", " b_one, b_two = y\n", " \n", " return (abs(a_one - b_one) + abs(a_two - b_two))\n", " \n", "# Calculate Manhattan distance between each set of two points in a list.\n", " \n", "def man_dist_state(x, y):\n", " return sum(man_dist(a, b) for a, b in zip(x, y))\n", "\n", "# Used to format the positions we parsed from our binary input.\n", "\n", "def format_pos(acc, elem):\n", " hex_elem = (elem[1] - (elem[1] >> 4 << 4))\n", " if hex_elem == 0:\n", " acc.append((hex_elem, (3,3)))\n", " else:\n", " acc.append((hex_elem, ((15 - ((elem[0]) * 2)) % 4,int((15 - ((elem[0]) * 2)) / 4))))\n", " hex_elem = (elem[1] >> 4) % 16\n", " if hex_elem == 0:\n", " acc.append((hex_elem, (3,3)))\n", " else:\n", " acc.append((hex_elem, ((15 - ((elem[0]) * 2 + 1)) % 4,int((15 - ((elem[0]) * 2 + 1)) / 4))))\n", " \n", " return acc\n", "\n", "# The title of this function is slightly misleading.\n", "# I'm simply generating a list of positions that each\n", "# puzzle piece in the current parsed state SHOULD be at.\n", "# I organize this in order of the pieces as they were\n", "# parsed so the two lists line up perfectly.\n", "\n", "def generate_pos(acc, elem):\n", " if(elem[0] == 0):\n", " acc.append((3,3))\n", " else:\n", " acc.append((((elem[0] - 1) % 4), (int((elem[0] - 1)/4))))\n", " \n", " return acc\n", "\n", "# Used to format our ending Manhattan distance into a format\n", "# that can be compared with our 29 output neurons.\n", "\n", "def format_man_dist(elem):\n", " acc = []\n", " for x in range(28, -1, -1):\n", " if x == elem:\n", " acc.append(1)\n", " else:\n", " acc.append(0)\n", " return acc\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Parsing input" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "## Creating Target data\n", "\n", "For this cell, I wanted to clearly explain how the script past this point works. Since I don't want to parse all of the binary states from each file that I'm going to use all at once and hold them in RAM, this instead parses 1 binary state at a time (8 bytes, meaning 64 bits, and we ignore the 1st 4 bits), does the calculations and input formatting needed, and appends the end result per state to a list to be used later." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "target = []\n", "\n", "for i in range(29):\n", " filename = join('data', str(i) + '.bin')\n", " \n", " # Debugging to print the current file from which states are being parsed.\n", " #print(i)\n", " temp = []\n", " \n", " with open(filename, 'rb') as f:\n", " data = f.read(8)\n", " counter = 0\n", "\n", " while(data and counter < 1000):\n", " temp.append(format_man_dist(i))\n", " \n", " data = f.read(8)\n", " counter += 1\n", " \n", " target.append(temp)\n", " \n", "#print(target[28][500])" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "# Parsing and Training the neural network" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Setting up the neural network\n", "\n", "Before we run our training/parsing, we need to make sure Keras has configured the neural network properly to our specifications." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "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", "\n", "model = Sequential()\n", "\n", "# Adding layers to the model.\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=60, activation='tanh'))\n", "model.add(Dense(units=29, activation='sigmoid'))\n", "\n", "# Configure the learning process.\n", "\n", "model.compile(optimizer='sgd',\n", " loss='mean_squared_error',\n", " metrics=['accuracy'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Training the neural network\n", "\n", "Again, this part has the parsing and training in hand, since as we parse and format the states from our file input, we feed those batches to our neural network to train with." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for i in range(29):\n", " filename = join('data', str(i) + '.bin')\n", " \n", " # Debugging to print the current file from which states are being parsed.\n", " print(i)\n", " \n", " with open(filename, 'rb') as f:\n", " data = f.read(8)\n", " counter = 0\n", " training = []\n", "\n", " while(data and counter < 1000):\n", " bin_data = reduce(format_input, list(data), [])\n", " bin_data.reverse()\n", " bin_data = bin_data[16:]\n", " \n", " training.append(bin_data)\n", "\n", " data = f.read(8)\n", " counter += 1\n", "\n", " #print(training[0])\n", " # Train the network.\n", "\n", " model.fit(np.array(training), np.array(target[i]), epochs=5, batch_size=100)\n", " #model.train_on_batch(np.array(temp), np.array(target))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Testing the neural network" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "## Creating the testing target data\n", "\n", "Similarly, here is a separate cell that just parses and creates the necessary target and testing arrays that we will need to test the neural network using Keras." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Used for testing data\n", "\n", "with open('data/18.bin', 'rb') as f:\n", " \n", " for i in range(1000):\n", " data = f.read(8)\n", " \n", " data = f.read(8)\n", " \n", " counter = 0\n", " \n", " testing = []\n", " \n", " testing_target = []\n", " \n", " while(data):\n", " bin_data = reduce(format_input, list(data), [])\n", " bin_data.reverse()\n", " bin_data = bin_data[16:]\n", "\n", " testing.append(bin_data)\n", "\n", " pos_data = reduce(format_pos, enumerate(list(data)), [])\n", " pos_data.reverse()\n", " pos_data = pos_data[1:]\n", " \n", " state_pos = []\n", "\n", " for p in pos_data:\n", " state_pos.append(p[1])\n", " \n", " testing_target_pos = reduce(generate_pos, pos_data, [])\n", "\n", " testing_target.append(format_man_dist(man_dist_state(state_pos, testing_target_pos)))\n", " \n", " counter += 1\n", " data = f.read(8)\n", " \n", "#print(testing_target)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Evaluating our test data" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Evaluate accuracy\n", " \n", "loss_and_metrics = model.evaluate(np.array(testing),np.array(testing_target), batch_size=1000)\n", " \n", "# Generating predictions:\n", " \n", "predictions = model.predict(np.array(testing), batch_size=1000)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "output = []\n", "\n", "for p in range(len(predictions)):\n", " if np.argmax(testing_target[p]) < 18:\n", " output.append(100*((18 - (28 - np.argmax(predictions[p]))) / (18 - np.argmax(testing_target[p]))))\n", " else:\n", " output.append(0)\n", " \n", "#for i in range(len(output)):\n", "# print(output[i])\n", "\n", "print(np.array(output).mean())\n", "\n", "print(loss_and_metrics)\n", "\n", "print(model.metrics_names)" ] }, { "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 }