From cd6aff41d349707708450e4afca9cf18f62487d0 Mon Sep 17 00:00:00 2001 From: Navjinder Virdee Date: Sun, 10 Jun 2018 14:06:12 +0530 Subject: [PATCH] Updated the code. --- Architecture/Architecture.JPG | Bin 0 -> 90472 bytes GamePlay.ipynb | 530 +++++++++++++++++++++++ Loss/Loss.png | Bin 0 -> 11821 bytes Loss/Loss1.png | Bin 0 -> 11153 bytes Score/Score.png | Bin 0 -> 16795 bytes Score/Scores.png | Bin 0 -> 15349 bytes Train-2048.ipynb | 764 ++++++++++++++++++++++++++++++++++ 7 files changed, 1294 insertions(+) create mode 100644 Architecture/Architecture.JPG create mode 100644 GamePlay.ipynb create mode 100644 Loss/Loss.png create mode 100644 Loss/Loss1.png create mode 100644 Score/Score.png create mode 100644 Score/Scores.png create mode 100644 Train-2048.ipynb diff --git a/Architecture/Architecture.JPG b/Architecture/Architecture.JPG new file mode 100644 index 0000000000000000000000000000000000000000..9f4864f3c75bff1348f0e488a1877e8b9650523d GIT binary patch literal 90472 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 literal 0 HcmV?d00001 diff --git a/GamePlay.ipynb b/GamePlay.ipynb new file mode 100644 index 0000000..6fbabfa --- /dev/null +++ b/GamePlay.ipynb @@ -0,0 +1,530 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "collapsed": true + }, + "source": [ + "# Play 2048 using Trained Weights" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Import Required Libraries" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import tensorflow as tf\n", + "import numpy as np\n", + "import pandas as pd\n", + "from copy import deepcopy\n", + "import random \n", + "import math\n", + "import time\n", + "from tkinter import *" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Restore Architecture" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "#conv layer1 depth\n", + "depth1 = 128\n", + "\n", + "#conv layer2 depth\n", + "depth2 = 128\n", + "\n", + "#input depth\n", + "input_depth = 16\n", + "\n", + "#fully conneted hidden layer\n", + "hidden_units = 256\n", + "\n", + "#output layer\n", + "output_units = 4\n", + "\n", + "#shape of weights\n", + "conv1_layer1_shape = [2,1,input_depth,depth1]\n", + "conv1_layer2_shape = [2,1,depth1,depth2]\n", + "conv2_layer1_shape = [1,2,input_depth,depth1]\n", + "conv2_layer2_shape = [1,2,depth1,depth2]\n", + "\n", + "fc_layer1_w_shape = [3*4*depth1*2+ 4*2*depth2*2 + 3*3*depth2*2,hidden_units]\n", + "fc_layer1_b_shape = [hidden_units]\n", + "fc_layer2_w_shape = [hidden_units,output_units]\n", + "fc_layer2_b_shape = [output_units]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Load The parameters" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "parameters = dict()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "path = r'E:\\Study n Work\\Projects\\2048\\Final Weights'\n", + "parameters['conv1_layer1'] = np.array(pd.read_csv(path + r'\\conv1_layer1_weights.csv')['Weight']).reshape(conv1_layer1_shape)\n", + "parameters['conv1_layer2'] = np.array(pd.read_csv(path + r'\\conv1_layer2_weights.csv')['Weight']).reshape(conv1_layer2_shape)\n", + "parameters['conv2_layer1'] = np.array(pd.read_csv(path + r'\\conv2_layer1_weights.csv')['Weight']).reshape(conv2_layer1_shape)\n", + "parameters['conv2_layer2'] = np.array(pd.read_csv(path + r'\\conv2_layer2_weights.csv')['Weight']).reshape(conv2_layer2_shape)\n", + "parameters['fc_layer1_w'] = np.array(pd.read_csv(path + r'\\fc_layer1_weights.csv')['Weight']).reshape(fc_layer1_w_shape)\n", + "parameters['fc_layer1_b'] = np.array(pd.read_csv(path + r'\\fc_layer1_biases.csv')['Weight']).reshape(fc_layer1_b_shape)\n", + "parameters['fc_layer2_w'] = np.array(pd.read_csv(path + r'\\fc_layer2_weights.csv')['Weight']).reshape(fc_layer2_w_shape)\n", + "parameters['fc_layer2_b'] = np.array(pd.read_csv(path + r'\\fc_layer2_biases.csv')['Weight']).reshape(fc_layer2_b_shape)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Game Logic" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def new_game(n):\n", + " matrix = []\n", + "\n", + " for i in range(n):\n", + " matrix.append([0] * n)\n", + " return matrix\n", + "\n", + "def add_two(mat):\n", + " empty_cells = []\n", + " for i in range(len(mat)):\n", + " for j in range(len(mat)):\n", + " if(mat[i][j]==0):\n", + " empty_cells.append((i,j))\n", + " if(len(empty_cells)==0):\n", + " return mat\n", + " index_pair = empty_cells[random.randint(0,len(empty_cells)-1)]\n", + " \n", + " num = np.random.random(1)\n", + " if(num>0.9):\n", + " mat[index_pair[0]][index_pair[1]]=4\n", + " else:\n", + " mat[index_pair[0]][index_pair[1]]=2\n", + " return mat\n", + "\n", + "def game_state(mat):\n", + " for i in range(len(mat)-1): #intentionally reduced to check the row on the right and below\n", + " for j in range(len(mat[0])-1): #more elegant to use exceptions but most likely this will be their solution\n", + " if mat[i][j]==mat[i+1][j] or mat[i][j+1]==mat[i][j]:\n", + " return 'not over'\n", + " for i in range(len(mat)): #check for any zero entries\n", + " for j in range(len(mat[0])):\n", + " if mat[i][j]==0:\n", + " return 'not over'\n", + " for k in range(len(mat)-1): #to check the left/right entries on the last row\n", + " if mat[len(mat)-1][k]==mat[len(mat)-1][k+1]:\n", + " return 'not over'\n", + " for j in range(len(mat)-1): #check up/down entries on last column\n", + " if mat[j][len(mat)-1]==mat[j+1][len(mat)-1]:\n", + " return 'not over'\n", + " return 'lose'\n", + "\n", + "def reverse(mat):\n", + " new=[]\n", + " for i in range(len(mat)):\n", + " new.append([])\n", + " for j in range(len(mat[0])):\n", + " new[i].append(mat[i][len(mat[0])-j-1])\n", + " return new\n", + "\n", + "def transpose(mat):\n", + " new=[]\n", + " for i in range(len(mat[0])):\n", + " new.append([])\n", + " for j in range(len(mat)):\n", + " new[i].append(mat[j][i])\n", + " return new\n", + "\n", + "def cover_up(mat):\n", + " new=[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]\n", + " done=False\n", + " for i in range(4):\n", + " count=0\n", + " for j in range(4):\n", + " if mat[i][j]!=0:\n", + " new[i][count]=mat[i][j]\n", + " if j!=count:\n", + " done=True\n", + " count+=1\n", + " return (new,done)\n", + "\n", + "def merge(mat):\n", + " done=False\n", + " score = 0\n", + " for i in range(4):\n", + " for j in range(3):\n", + " if mat[i][j]==mat[i][j+1] and mat[i][j]!=0:\n", + " mat[i][j]*=2\n", + " score += mat[i][j] \n", + " mat[i][j+1]=0\n", + " done=True\n", + " return (mat,done,score)\n", + "\n", + "\n", + "def up(game):\n", + " game=transpose(game)\n", + " game,done=cover_up(game)\n", + " temp=merge(game)\n", + " game=temp[0]\n", + " done=done or temp[1]\n", + " game=cover_up(game)[0]\n", + " game=transpose(game)\n", + " return (game,done,temp[2])\n", + "\n", + "def down(game):\n", + " game=reverse(transpose(game))\n", + " game,done=cover_up(game)\n", + " temp=merge(game)\n", + " game=temp[0]\n", + " done=done or temp[1]\n", + " game=cover_up(game)[0]\n", + " game=transpose(reverse(game))\n", + " return (game,done,temp[2])\n", + "\n", + "def left(game):\n", + " game,done=cover_up(game)\n", + " temp=merge(game)\n", + " game=temp[0]\n", + " done=done or temp[1]\n", + " game=cover_up(game)[0]\n", + " return (game,done,temp[2])\n", + "\n", + "def right(game):\n", + " game=reverse(game)\n", + " game,done=cover_up(game)\n", + " temp=merge(game)\n", + " game=temp[0]\n", + " done=done or temp[1]\n", + " game=cover_up(game)[0]\n", + " game=reverse(game)\n", + " return (game,done,temp[2])\n", + " \n", + "\n", + "def findemptyCell(mat):\n", + " count = 0\n", + " for i in range(len(mat)):\n", + " for j in range(len(mat)):\n", + " if(mat[i][j]==0):\n", + " count+=1\n", + " return count\n", + "\n", + "def change_values(X):\n", + " power_mat = np.zeros(shape=(1,4,4,16),dtype=np.float32)\n", + " for i in range(4):\n", + " for j in range(4):\n", + " if(X[i][j]==0):\n", + " power_mat[0][i][j][0] = 1.0\n", + " else:\n", + " power = int(math.log(X[i][j],2))\n", + " power_mat[0][i][j][power] = 1.0\n", + " return power_mat" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Controls" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "controls = {0:up,1:left,2:right,3:down}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Resore the Graph" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "learned_graph = tf.Graph()\n", + "\n", + "with learned_graph.as_default():\n", + " \n", + " #input data\n", + " single_dataset = tf.placeholder(tf.float32,shape=(1,4,4,16))\n", + " \n", + " #weights\n", + " \n", + " #conv layer1 weights\n", + " conv1_layer1_weights = tf.constant(parameters['conv1_layer1'],dtype=tf.float32)\n", + " conv1_layer2_weights = tf.constant(parameters['conv1_layer2'],dtype=tf.float32)\n", + " \n", + " #conv layer2 weights\n", + " conv2_layer1_weights = tf.constant(parameters['conv2_layer1'],dtype=tf.float32)\n", + " conv2_layer2_weights = tf.constant(parameters['conv2_layer2'],dtype=tf.float32)\n", + " \n", + " #fully connected parameters\n", + " fc_layer1_weights = tf.constant(parameters['fc_layer1_w'],dtype=tf.float32)\n", + " fc_layer1_biases = tf.constant(parameters['fc_layer1_b'],dtype=tf.float32)\n", + " fc_layer2_weights = tf.constant(parameters['fc_layer2_w'],dtype=tf.float32)\n", + " fc_layer2_biases = tf.constant(parameters['fc_layer2_b'],dtype=tf.float32)\n", + " \n", + " \n", + " #model\n", + " def model(dataset):\n", + " #layer1\n", + " conv1 = tf.nn.conv2d(dataset,conv1_layer1_weights,[1,1,1,1],padding='VALID') \n", + " conv2 = tf.nn.conv2d(dataset,conv2_layer1_weights,[1,1,1,1],padding='VALID') \n", + "\n", + " #layer1 relu activation\n", + " relu1 = tf.nn.relu(conv1)\n", + " relu2 = tf.nn.relu(conv2)\n", + "\n", + " #layer2\n", + " conv11 = tf.nn.conv2d(relu1,conv1_layer2_weights,[1,1,1,1],padding='VALID') \n", + " conv12 = tf.nn.conv2d(relu1,conv2_layer2_weights,[1,1,1,1],padding='VALID') \n", + "\n", + " conv21 = tf.nn.conv2d(relu2,conv1_layer2_weights,[1,1,1,1],padding='VALID') \n", + " conv22 = tf.nn.conv2d(relu2,conv2_layer2_weights,[1,1,1,1],padding='VALID') \n", + "\n", + " #layer2 relu activation\n", + " relu11 = tf.nn.relu(conv11)\n", + " relu12 = tf.nn.relu(conv12)\n", + " relu21 = tf.nn.relu(conv21)\n", + " relu22 = tf.nn.relu(conv22)\n", + "\n", + " #get shapes of all activations\n", + " shape1 = relu1.get_shape().as_list()\n", + " shape2 = relu2.get_shape().as_list()\n", + "\n", + " shape11 = relu11.get_shape().as_list()\n", + " shape12 = relu12.get_shape().as_list()\n", + " shape21 = relu21.get_shape().as_list()\n", + " shape22 = relu22.get_shape().as_list()\n", + "\n", + " #expansion\n", + " hidden1 = tf.reshape(relu1,[shape1[0],shape1[1]*shape1[2]*shape1[3]])\n", + " hidden2 = tf.reshape(relu2,[shape2[0],shape2[1]*shape2[2]*shape2[3]])\n", + "\n", + " hidden11 = tf.reshape(relu11,[shape11[0],shape11[1]*shape11[2]*shape11[3]])\n", + " hidden12 = tf.reshape(relu12,[shape12[0],shape12[1]*shape12[2]*shape12[3]])\n", + " hidden21 = tf.reshape(relu21,[shape21[0],shape21[1]*shape21[2]*shape21[3]])\n", + " hidden22 = tf.reshape(relu22,[shape22[0],shape22[1]*shape22[2]*shape22[3]])\n", + "\n", + " #concatenation\n", + " hidden = tf.concat([hidden1,hidden2,hidden11,hidden12,hidden21,hidden22],axis=1)\n", + "\n", + " #full connected layers\n", + " hidden = tf.matmul(hidden,fc_layer1_weights) + fc_layer1_biases\n", + " hidden = tf.nn.relu(hidden)\n", + "\n", + " #output layer\n", + " output = tf.matmul(hidden,fc_layer2_weights) + fc_layer2_biases\n", + "\n", + " #return output\n", + " return output\n", + "\n", + " #for single example\n", + " single_output = model(single_dataset)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Enjoy the Game!" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "SIZE = 500\n", + "GRID_LEN = 4\n", + "GRID_PADDING = 10\n", + "\n", + "BACKGROUND_COLOR_GAME = \"#92877d\"\n", + "BACKGROUND_COLOR_CELL_EMPTY = \"#9e948a\"\n", + "BACKGROUND_COLOR_DICT = { 2:\"#eee4da\", 4:\"#ede0c8\", 8:\"#f2b179\", 16:\"#f59563\", \\\n", + " 32:\"#f67c5f\", 64:\"#f65e3b\", 128:\"#edcf72\", 256:\"#edcc61\", \\\n", + " 512:\"#edc850\", 1024:\"#edc53f\", 2048:\"#edc22e\" }\n", + "\n", + "CELL_COLOR_DICT = { 2:\"#776e65\", 4:\"#776e65\", 8:\"#f9f6f2\", 16:\"#f9f6f2\", \\\n", + " 32:\"#f9f6f2\", 64:\"#f9f6f2\", 128:\"#f9f6f2\", 256:\"#f9f6f2\", \\\n", + " 512:\"#f9f6f2\", 1024:\"#f9f6f2\", 2048:\"#f9f6f2\" }\n", + "\n", + "FONT = (\"Verdana\", 40, \"bold\")\n", + "\n", + "learned_sess = tf.Session(graph=learned_graph)\n", + "\n", + "class GameGrid(Frame):\n", + " def __init__(self):\n", + " Frame.__init__(self)\n", + "\n", + " self.grid()\n", + " self.master.title('2048')\n", + "\n", + " self.grid_cells = []\n", + " self.init_grid()\n", + " self.init_matrix()\n", + " self.update_grid_cells()\n", + " \n", + " self.wait_visibility()\n", + " self.after(10,self.make_move)\n", + " \n", + " def init_grid(self):\n", + " background = Frame(self, bg=BACKGROUND_COLOR_GAME, width=SIZE, height=SIZE)\n", + " background.grid()\n", + " for i in range(GRID_LEN):\n", + " grid_row = []\n", + " for j in range(GRID_LEN):\n", + " cell = Frame(background, bg=BACKGROUND_COLOR_CELL_EMPTY, width=SIZE/GRID_LEN, height=SIZE/GRID_LEN)\n", + " cell.grid(row=i, column=j, padx=GRID_PADDING, pady=GRID_PADDING)\n", + " # font = Font(size=FONT_SIZE, family=FONT_FAMILY, weight=FONT_WEIGHT)\n", + " t = Label(master=cell, text=\"\", bg=BACKGROUND_COLOR_CELL_EMPTY, justify=CENTER, font=FONT, width=4, height=2)\n", + " t.grid()\n", + " grid_row.append(t)\n", + "\n", + " self.grid_cells.append(grid_row)\n", + "\n", + " def gen(self):\n", + " return randint(0, GRID_LEN - 1)\n", + "\n", + " def init_matrix(self):\n", + " self.matrix = new_game(4)\n", + "\n", + " self.matrix=add_two(self.matrix)\n", + " self.matrix=add_two(self.matrix)\n", + "\n", + " def update_grid_cells(self):\n", + " for i in range(GRID_LEN):\n", + " for j in range(GRID_LEN):\n", + " new_number = self.matrix[i][j]\n", + " if new_number == 0:\n", + " self.grid_cells[i][j].configure(text=\"\", bg=BACKGROUND_COLOR_CELL_EMPTY)\n", + " else:\n", + " self.grid_cells[i][j].configure(text=str(new_number), bg=BACKGROUND_COLOR_DICT[new_number], fg=CELL_COLOR_DICT[new_number])\n", + " self.update_idletasks()\n", + " \n", + " def make_move(self):\n", + " output = learned_sess.run([single_output],feed_dict = {single_dataset:change_values(self.matrix)})\n", + " move = np.argmax(output[0])\n", + " self.matrix,done,tempo = controls[move](self.matrix)\n", + " done=True\n", + " \n", + " #if game_state(self.matrix)=='win':\n", + " # self.grid_cells[1][1].configure(text=\"You\",bg=BACKGROUND_COLOR_CELL_EMPTY)\n", + " # self.grid_cells[1][2].configure(text=\"Win!\",bg=BACKGROUND_COLOR_CELL_EMPTY)\n", + " # done=False\n", + " if game_state(self.matrix)=='lose':\n", + " self.grid_cells[1][1].configure(text=\"You\",bg=BACKGROUND_COLOR_CELL_EMPTY)\n", + " self.grid_cells[1][2].configure(text=\"Lose!\",bg=BACKGROUND_COLOR_CELL_EMPTY)\n", + " done=False\n", + " \n", + " self.matrix = add_two(self.matrix)\n", + " self.update_grid_cells()\n", + " \n", + " \n", + " if(done==True):\n", + " self.after(7,self.make_move)\n", + " else:\n", + " time.sleep(3)\n", + " self.init_matrix()\n", + " self.update_grid_cells()\n", + " self.after(7,self.make_move)\n", + "\n", + " def generate_next(self):\n", + " empty_cells = []\n", + " for i in range(len(mat)):\n", + " for j in range(len(mat)):\n", + " if(mat[i][j]==0):\n", + " empty_cells.append((i,j))\n", + " if(len(empty_cells)==0):\n", + " return 0,false\n", + " index_pair = empty_cells[random.randint(0,len(empty_cells)-1)]\n", + " index = index_pair\n", + " self.matrix[index[0]][index[1]] = 2\n", + "\n", + "root = Tk()\n", + "gamegrid = GameGrid()\n", + "root.mainloop()" + ] + } + ], + "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.1" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Loss/Loss.png b/Loss/Loss.png new file mode 100644 index 0000000000000000000000000000000000000000..8281f73f1b733cb54ad761064e50afa0d0487bac GIT binary patch literal 11821 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 R2YPDBG*xv}N*~*N{6AtZzI^}y literal 0 HcmV?d00001 diff --git a/Score/Score.png b/Score/Score.png new file mode 100644 index 0000000000000000000000000000000000000000..f55e9e55fc1431a055efeb52fdab2731eb5cfe2e GIT binary patch literal 16795 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 R*tZLk7FQ4}`C#DtzW}t=4z~aR literal 0 HcmV?d00001 diff --git a/Train-2048.ipynb b/Train-2048.ipynb new file mode 100644 index 0000000..61d614b --- /dev/null +++ b/Train-2048.ipynb @@ -0,0 +1,764 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "collapsed": true + }, + "source": [ + "# 2048 Deep Reinforcement Learning" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Import Required Libraries" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import tensorflow as tf\n", + "import numpy as np\n", + "from copy import deepcopy\n", + "import random \n", + "import math\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Game Logic" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "#initialize a new game\n", + "def new_game(n):\n", + " matrix = np.zeros([n,n])\n", + " return matrix\n", + "\n", + "#add 2 or 4 in the matrix\n", + "def add_two(mat):\n", + " empty_cells = []\n", + " for i in range(len(mat)):\n", + " for j in range(len(mat[0])):\n", + " if(mat[i][j]==0):\n", + " empty_cells.append((i,j))\n", + " if(len(empty_cells)==0):\n", + " return mat\n", + " \n", + " index_pair = empty_cells[random.randint(0,len(empty_cells)-1)]\n", + " \n", + " prob = random.random()\n", + " if(prob>=0.9):\n", + " mat[index_pair[0]][index_pair[1]]=4\n", + " else:\n", + " mat[index_pair[0]][index_pair[1]]=2\n", + " return mat\n", + "\n", + "#to check state of the game\n", + "def game_state(mat):\n", + " #if 2048 in mat:\n", + " # return 'win'\n", + " \n", + " for i in range(len(mat)-1): #intentionally reduced to check the row on the right and below\n", + " for j in range(len(mat[0])-1): #more elegant to use exceptions but most likely this will be their solution\n", + " if mat[i][j]==mat[i+1][j] or mat[i][j+1]==mat[i][j]:\n", + " return 'not over'\n", + " \n", + " for i in range(len(mat)): #check for any zero entries\n", + " for j in range(len(mat[0])):\n", + " if mat[i][j]==0:\n", + " return 'not over'\n", + " \n", + " for k in range(len(mat)-1): #to check the left/right entries on the last row\n", + " if mat[len(mat)-1][k]==mat[len(mat)-1][k+1]:\n", + " return 'not over'\n", + " \n", + " for j in range(len(mat)-1): #check up/down entries on last column\n", + " if mat[j][len(mat)-1]==mat[j+1][len(mat)-1]:\n", + " return 'not over'\n", + " \n", + " return 'lose'\n", + "\n", + "\n", + "def reverse(mat):\n", + " new=[]\n", + " for i in range(len(mat)):\n", + " new.append([])\n", + " for j in range(len(mat[0])):\n", + " new[i].append(mat[i][len(mat[0])-j-1])\n", + " return new\n", + "\n", + "def transpose(mat):\n", + " new=[]\n", + " for i in range(len(mat[0])):\n", + " new.append([])\n", + " for j in range(len(mat)):\n", + " new[i].append(mat[j][i])\n", + " \n", + " return np.transpose(mat)\n", + "\n", + "def cover_up(mat):\n", + " new = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]\n", + " done = False\n", + " for i in range(4):\n", + " count = 0\n", + " for j in range(4):\n", + " if mat[i][j]!=0:\n", + " new[i][count] = mat[i][j]\n", + " if j!=count:\n", + " done=True\n", + " count+=1\n", + " return (new,done)\n", + "\n", + "def merge(mat):\n", + " done=False\n", + " score = 0\n", + " for i in range(4):\n", + " for j in range(3):\n", + " if mat[i][j]==mat[i][j+1] and mat[i][j]!=0:\n", + " mat[i][j]*=2\n", + " score += mat[i][j] \n", + " mat[i][j+1]=0\n", + " done=True\n", + " return (mat,done,score)\n", + "\n", + "#up move\n", + "def up(game):\n", + " game = transpose(game)\n", + " game,done = cover_up(game)\n", + " temp = merge(game)\n", + " game = temp[0]\n", + " done = done or temp[1]\n", + " game = cover_up(game)[0]\n", + " game = transpose(game)\n", + " return (game,done,temp[2])\n", + "\n", + "#down move\n", + "def down(game):\n", + " game=reverse(transpose(game))\n", + " game,done=cover_up(game)\n", + " temp=merge(game)\n", + " game=temp[0]\n", + " done=done or temp[1]\n", + " game=cover_up(game)[0]\n", + " game=transpose(reverse(game))\n", + " return (game,done,temp[2])\n", + "\n", + "#left move\n", + "def left(game):\n", + " game,done=cover_up(game)\n", + " temp=merge(game)\n", + " game=temp[0]\n", + " done=done or temp[1]\n", + " game=cover_up(game)[0]\n", + " return (game,done,temp[2])\n", + "\n", + "#right move\n", + "def right(game):\n", + " game=reverse(game)\n", + " game,done=cover_up(game)\n", + " temp=merge(game)\n", + " game=temp[0]\n", + " done=done or temp[1]\n", + " game=cover_up(game)[0]\n", + " game=reverse(game)\n", + " return (game,done,temp[2])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Controls" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "controls = {0:up,1:left,2:right,3:down}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Important Functions\n", + "* Find Empty Cell Function (Used in Reward)\n", + "* Convert Input Values" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "#convert the input game matrix into corresponding power of 2 matrix.\n", + "def change_values(X):\n", + " power_mat = np.zeros(shape=(1,4,4,16),dtype=np.float32)\n", + " for i in range(4):\n", + " for j in range(4):\n", + " if(X[i][j]==0):\n", + " power_mat[0][i][j][0] = 1.0\n", + " else:\n", + " power = int(math.log(X[i][j],2))\n", + " power_mat[0][i][j][power] = 1.0\n", + " return power_mat \n", + "\n", + "#find the number of empty cells in the game matrix.\n", + "def findemptyCell(mat):\n", + " count = 0\n", + " for i in range(len(mat)):\n", + " for j in range(len(mat)):\n", + " if(mat[i][j]==0):\n", + " count+=1\n", + " return count" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Hyper Parameters" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "#hyper parameters\n", + "start_learning_rate = 0.0005\n", + "\n", + "#gamma for Q-learning\n", + "gamma = 0.9\n", + "\n", + "#epsilon greedy approach\n", + "epsilon = 0.9\n", + "\n", + "#to store states and lables of the game for training\n", + "#states of the game\n", + "replay_memory = list()\n", + "\n", + "#labels of the states\n", + "replay_labels = list()\n", + "\n", + "#capacity of memory\n", + "mem_capacity = 6000" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Network Architecture\n", + "\n", + "" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "#first convolution layer depth\n", + "depth1 = 128\n", + "\n", + "#second convolution layer depth\n", + "depth2 = 128\n", + "\n", + "#batch size for batch gradient descent\n", + "batch_size = 512\n", + "\n", + "#input units\n", + "input_units = 16\n", + "\n", + "#fully connected layer neurons\n", + "hidden_units = 256\n", + "\n", + "#output neurons = number of moves\n", + "output_units = 4" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Let's make the Tensorflow Graph\n", + "* Loss = mean ( square( Q(st,at) - (r + gamma x max(Q(st+1,a))) ) )\n", + "* Activation = RELU\n", + "* Optimizer = RMSProp" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "#input data\n", + "tf_batch_dataset = tf.placeholder(tf.float32,shape=(batch_size,4,4,16))\n", + "tf_batch_labels = tf.placeholder(tf.float32,shape=(batch_size,output_units))\n", + "\n", + "single_dataset = tf.placeholder(tf.float32,shape=(1,4,4,16))\n", + "\n", + "\n", + "#CONV LAYERS\n", + "#conv layer1 weights\n", + "conv1_layer1_weights = tf.Variable(tf.truncated_normal([1,2,input_units,depth1],mean=0,stddev=0.01))\n", + "conv2_layer1_weights = tf.Variable(tf.truncated_normal([2,1,input_units,depth1],mean=0,stddev=0.01))\n", + "\n", + "#conv layer2 weights\n", + "conv1_layer2_weights = tf.Variable(tf.truncated_normal([1,2,depth1,depth2],mean=0,stddev=0.01))\n", + "conv2_layer2_weights = tf.Variable(tf.truncated_normal([2,1,depth1,depth2],mean=0,stddev=0.01))\n", + "\n", + "\n", + "\n", + "#FUllY CONNECTED LAYERS\n", + "expand_size = 2*4*depth2*2 + 3*3*depth2*2 + 4*3*depth1*2\n", + "fc_layer1_weights = tf.Variable(tf.truncated_normal([expand_size,hidden_units],mean=0,stddev=0.01))\n", + "fc_layer1_biases = tf.Variable(tf.truncated_normal([1,hidden_units],mean=0,stddev=0.01))\n", + "fc_layer2_weights = tf.Variable(tf.truncated_normal([hidden_units,output_units],mean=0,stddev=0.01))\n", + "fc_layer2_biases = tf.Variable(tf.truncated_normal([1,output_units],mean=0,stddev=0.01))\n", + "\n", + "\n", + "#model\n", + "def model(dataset):\n", + " #layer1\n", + " conv1 = tf.nn.conv2d(dataset,conv1_layer1_weights,[1,1,1,1],padding='VALID') \n", + " conv2 = tf.nn.conv2d(dataset,conv2_layer1_weights,[1,1,1,1],padding='VALID') \n", + " \n", + " #layer1 relu activation\n", + " relu1 = tf.nn.relu(conv1)\n", + " relu2 = tf.nn.relu(conv2)\n", + " \n", + " #layer2\n", + " conv11 = tf.nn.conv2d(relu1,conv1_layer2_weights,[1,1,1,1],padding='VALID') \n", + " conv12 = tf.nn.conv2d(relu1,conv2_layer2_weights,[1,1,1,1],padding='VALID') \n", + "\n", + " conv21 = tf.nn.conv2d(relu2,conv1_layer2_weights,[1,1,1,1],padding='VALID') \n", + " conv22 = tf.nn.conv2d(relu2,conv2_layer2_weights,[1,1,1,1],padding='VALID') \n", + "\n", + " #layer2 relu activation\n", + " relu11 = tf.nn.relu(conv11)\n", + " relu12 = tf.nn.relu(conv12)\n", + " relu21 = tf.nn.relu(conv21)\n", + " relu22 = tf.nn.relu(conv22)\n", + " \n", + " #get shapes of all activations\n", + " shape1 = relu1.get_shape().as_list()\n", + " shape2 = relu2.get_shape().as_list()\n", + " \n", + " shape11 = relu11.get_shape().as_list()\n", + " shape12 = relu12.get_shape().as_list()\n", + " shape21 = relu21.get_shape().as_list()\n", + " shape22 = relu22.get_shape().as_list()\n", + "\n", + " #expansion\n", + " hidden1 = tf.reshape(relu1,[shape1[0],shape1[1]*shape1[2]*shape1[3]])\n", + " hidden2 = tf.reshape(relu2,[shape2[0],shape2[1]*shape2[2]*shape2[3]])\n", + " \n", + " hidden11 = tf.reshape(relu11,[shape11[0],shape11[1]*shape11[2]*shape11[3]])\n", + " hidden12 = tf.reshape(relu12,[shape12[0],shape12[1]*shape12[2]*shape12[3]])\n", + " hidden21 = tf.reshape(relu21,[shape21[0],shape21[1]*shape21[2]*shape21[3]])\n", + " hidden22 = tf.reshape(relu22,[shape22[0],shape22[1]*shape22[2]*shape22[3]])\n", + "\n", + " #concatenation\n", + " hidden = tf.concat([hidden1,hidden2,hidden11,hidden12,hidden21,hidden22],axis=1)\n", + "\n", + " #full connected layers\n", + " hidden = tf.matmul(hidden,fc_layer1_weights) + fc_layer1_biases\n", + " hidden = tf.nn.relu(hidden)\n", + "\n", + " #output layer\n", + " output = tf.matmul(hidden,fc_layer2_weights) + fc_layer2_biases\n", + " \n", + " #return output\n", + " return output\n", + "\n", + "#for single example\n", + "single_output = model(single_dataset)\n", + "\n", + "#for batch data\n", + "logits = model(tf_batch_dataset)\n", + "\n", + "#loss\n", + "loss = tf.square(tf.subtract(tf_batch_labels,logits))\n", + "loss = tf.reduce_sum(loss,axis=1,keep_dims=True)\n", + "loss = tf.reduce_mean(loss)/2.0\n", + "\n", + "#optimizer\n", + "global_step = tf.Variable(0) # count the number of steps taken.\n", + "learning_rate = tf.train.exponential_decay(float(start_learning_rate), global_step, 1000, 0.90, staircase=True)\n", + "optimizer = tf.train.RMSPropOptimizer(learning_rate).minimize(loss, global_step=global_step)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "#loss\n", + "J = []\n", + "\n", + "#scores\n", + "scores = []\n", + "\n", + "#to store final parameters\n", + "final_parameters = {}\n", + "\n", + "#number of episodes\n", + "M = 200001" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Create training dataset and Train Simultaneously\n", + "* Current Reward = number of merges + log(new max,2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "with tf.Session() as session:\n", + " tf.global_variables_initializer().run()\n", + " print(\"Initialized\")\n", + " \n", + " global epsilon\n", + " global replay_labels\n", + " global replay_memory\n", + "\n", + " #for episode with max score\n", + " maximum = -1\n", + " episode = -1\n", + " \n", + " #total_iters \n", + " total_iters = 1\n", + " \n", + " #number of back props\n", + " back=0\n", + " \n", + " for ep in range(M):\n", + " global board\n", + " board = new_game(4)\n", + " add_two(board)\n", + " add_two(board)\n", + " \n", + " #whether episode finished or not\n", + " finish = 'not over'\n", + " \n", + " #total_score of this episode\n", + " total_score = 0\n", + " \n", + " #iters per episode\n", + " local_iters = 1\n", + " \n", + " while(finish=='not over'):\n", + " prev_board = deepcopy(board)\n", + " \n", + " #get the required move for this state\n", + " state = deepcopy(board)\n", + " state = change_values(state)\n", + " state = np.array(state,dtype = np.float32).reshape(1,4,4,16)\n", + " feed_dict = {single_dataset:state}\n", + " control_scores = session.run(single_output,feed_dict=feed_dict)\n", + " \n", + " #find the move with max Q value\n", + " control_buttons = np.flip(np.argsort(control_scores),axis=1)\n", + " \n", + " #copy the Q-values as labels\n", + " labels = deepcopy(control_scores[0])\n", + " \n", + " #generate random number for epsilon greedy approach\n", + " num = random.uniform(0,1)\n", + " \n", + " #store prev max\n", + " prev_max = np.max(prev_board)\n", + " \n", + " #num is less epsilon generate random move\n", + " if(num10000) or (epsilon>0.1 and total_iters%2500==0)):\n", + " epsilon = epsilon/1.005\n", + " \n", + " \n", + " #change the matrix values and store them in memory\n", + " prev_state = deepcopy(prev_board)\n", + " prev_state = change_values(prev_state)\n", + " prev_state = np.array(prev_state,dtype=np.float32).reshape(1,4,4,16)\n", + " replay_labels.append(labels)\n", + " replay_memory.append(prev_state)\n", + " \n", + " \n", + " #back-propagation\n", + " if(len(replay_memory)>=mem_capacity):\n", + " back_loss = 0\n", + " batch_num = 0\n", + " z = list(zip(replay_memory,replay_labels))\n", + " np.random.shuffle(z)\n", + " np.random.shuffle(z)\n", + " replay_memory,replay_labels = zip(*z)\n", + " \n", + " for i in range(0,len(replay_memory),batch_size):\n", + " if(i + batch_size>len(replay_memory)):\n", + " break\n", + " \n", + " batch_data = deepcopy(replay_memory[i:i+batch_size])\n", + " batch_labels = deepcopy(replay_labels[i:i+batch_size])\n", + " \n", + " batch_data = np.array(batch_data,dtype=np.float32).reshape(batch_size,4,4,16)\n", + " batch_labels = np.array(batch_labels,dtype=np.float32).reshape(batch_size,output_units)\n", + " \n", + " feed_dict = {tf_batch_dataset: batch_data, tf_batch_labels: batch_labels}\n", + " _,l = session.run([optimizer,loss],feed_dict=feed_dict)\n", + " back_loss += l \n", + " \n", + " print(\"Mini-Batch - {} Back-Prop : {}, Loss : {}\".format(batch_num,back,l))\n", + " batch_num +=1\n", + " back_loss /= batch_num\n", + " J.append(back_loss)\n", + " \n", + " #store the parameters in a dictionary\n", + " final_parameters['conv1_layer1_weights'] = session.run(conv1_layer1_weights)\n", + " final_parameters['conv1_layer2_weights'] = session.run(conv1_layer2_weights)\n", + " final_parameters['conv2_layer1_weights'] = session.run(conv2_layer1_weights)\n", + " final_parameters['conv2_layer2_weights'] = session.run(conv2_layer2_weights)\n", + " final_parameters['conv1_layer1_biases'] = session.run(conv1_layer1_biases)\n", + " final_parameters['conv1_layer2_biases'] = session.run(conv1_layer2_biases)\n", + " final_parameters['conv2_layer1_biases'] = session.run(conv2_layer1_biases)\n", + " final_parameters['conv2_layer2_biases'] = session.run(conv2_layer2_biases)\n", + " final_parameters['fc_layer1_weights'] = session.run(fc_layer1_weights)\n", + " final_parameters['fc_layer2_weights'] = session.run(fc_layer2_weights)\n", + " final_parameters['fc_layer1_biases'] = session.run(fc_layer1_biases)\n", + " final_parameters['fc_layer2_biases'] = session.run(fc_layer2_biases)\n", + " \n", + " #number of back-props\n", + " back+=1\n", + " \n", + " #make new memory \n", + " replay_memory = list()\n", + " replay_labels = list()\n", + " \n", + " \n", + " if(local_iters%400==0):\n", + " print(\"Episode : {}, Score : {}, Iters : {}, Finish : {}\".format(ep,total_score,local_iters,finish))\n", + " \n", + " local_iters += 1\n", + " total_iters += 1\n", + " \n", + " scores.append(total_score)\n", + " print(\"Episode {} finished with score {}, result : {} board : {}, epsilon : {}, learning rate : {} \".format(ep,total_score,finish,board,epsilon,session.run(learning_rate)))\n", + " print()\n", + " \n", + " if((ep+1)%1000==0):\n", + " print(\"Maximum Score : {} ,Episode : {}\".format(maximum,episode)) \n", + " print(\"Loss : {}\".format(J[len(J)-1]))\n", + " print()\n", + " \n", + " if(maximum