From 3f20fe83f1576ab41b742ac8f68704ee28980c31 Mon Sep 17 00:00:00 2001 From: Liyao Zhu <l.zhu34@student.unimelb.edu.au> Date: Wed, 12 Jun 2019 04:11:30 +1000 Subject: [PATCH] jupyter notebook added --- Collective_risk_game120619.ipynb | 1044 ++++++++++++++++++++++++++++++ 1 file changed, 1044 insertions(+) create mode 100644 Collective_risk_game120619.ipynb diff --git a/Collective_risk_game120619.ipynb b/Collective_risk_game120619.ipynb new file mode 100644 index 0000000..a98cd20 --- /dev/null +++ b/Collective_risk_game120619.ipynb @@ -0,0 +1,1044 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "name": "Collective-risk-game120619.ipynb", + "version": "0.3.2", + "provenance": [] + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + } + }, + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "-clQqk9qowkW", + "colab_type": "text" + }, + "source": [ + "First, run the model classes." + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "qeMe96-ForDP", + "colab_type": "code", + "colab": {} + }, + "source": [ + "import matplotlib.pyplot as plt\n", + "from matplotlib import cm\n", + "from mpl_toolkits.mplot3d import Axes3D\n", + "import numpy as np\n", + "from scipy import stats\n", + "\n", + "\n", + "class Agent:\n", + "\n", + " def __init__(self, rounds, initialWealth, availableActions, alpha=0.1,\n", + " gamma=0.9, epsilon=0.1, multiArm='greedy'):\n", + "\n", + " self.R = rounds\n", + " self.initialWealth = initialWealth\n", + " self.wealth = initialWealth\n", + " self.availableActions = availableActions\n", + " self.iteration = 0\n", + "\n", + " \"\"\"initialise Q table to small random numbers\"\"\"\n", + " self.qTable = np.random.rand(self.R, len(self.availableActions)) * 0.01\n", + "\n", + " \"Q-Learning Parameters\"\n", + " self.learnRate = alpha\n", + " self.discount = gamma\n", + " self.epsilon = epsilon\n", + " self.multiArm = multiArm\n", + "\n", + " def updateReward(self, round, action, loss):\n", + " \"\"\"\n", + " updates the Q-table by receiving a payoff\n", + " \"\"\"\n", + " newWealth = self.wealth * (1-action) * (1-loss)\n", + " reward = newWealth - self.wealth\n", + " self.wealth = newWealth\n", + "\n", + " index = self.availableActions.index(action)\n", + " if round == self.R - 1:\n", + " \"\"\" at goal state, no future value\"\"\"\n", + " maxNextQ = 0\n", + " elif round < self.R - 1:\n", + " \"\"\" not at goal state\"\"\"\n", + " maxNextQ = max(self.qTable[round + 1])\n", + " else:\n", + " print(\"ERROR: Illegal round number\")\n", + " exit(2)\n", + "\n", + " \"\"\"Update function\"\"\"\n", + " self.qTable[round][index] += self.learnRate * (\n", + " reward + self.discount * maxNextQ - self.qTable[round][index])\n", + "\n", + " # if self.iteration == 999:\n", + " # print(\"QTABLE:\", self.qTable)\n", + "\n", + " if round == self.R - 1:\n", + " self.iteration += 1\n", + " # print(\"Player iteration +1 =\", self.iteration)\n", + "\n", + "\n", + " def chooseAction(self, roundNumber):\n", + " \"\"\"\n", + " Choose an action based on current round number\n", + " :return: an action (float type)\n", + " \"\"\"\n", + " randomAct = False\n", + " if self.multiArm == 'decrease':\n", + " \"\"\"Epsilon Decrease\"\"\"\n", + " if np.random.uniform(0, 1) <= 1 * self.epsilon ** self.iteration:\n", + " randomAct = True\n", + "\n", + " elif self.multiArm == 'greedy':\n", + " \"\"\"EPSILON GREEDY\"\"\"\n", + " if np.random.uniform(0, 1) <= self.epsilon:\n", + " randomAct = True\n", + "\n", + " if randomAct:\n", + " return np.random.choice(self.availableActions)\n", + " else:\n", + " index = np.argmax(self.qTable[roundNumber])\n", + " return self.availableActions[index]\n", + "\n", + " def getStrategy(self):\n", + " \"\"\"\n", + " Get the current strategy without randomness, for analytical use\n", + " :return: a dictionary of actions in all rounds\n", + " \"\"\"\n", + " strategy = {}\n", + " for r in range(self.R):\n", + " index = np.argmax(self.qTable[r])\n", + " strategy[r] = self.availableActions[index]\n", + " return strategy\n", + "\n", + "\n", + " def getWealth(self):\n", + " return self.wealth\n", + "\n", + " def resetWealth(self):\n", + " self.wealth = self.initialWealth\n", + " \n", + " \n", + " \n", + "class Graph:\n", + " def __init__(self, N, K, P):\n", + " self.N = N # Number of players\n", + " self.K = K # Number of edges/connections each player has originally\n", + " self.P = P # Rewiring probability\n", + " self.edges = []\n", + " self.selectedNodes = {}\n", + "\n", + " if K == N - 1:\n", + " \"\"\"Well-mixed graph, no rewiring\"\"\"\n", + " for i in range(N):\n", + " for j in range(i + 1, N):\n", + " self.edges.append((i, j))\n", + "\n", + " elif K < N - 1:\n", + " assert K % 2 == 0\n", + " k_half = int(K/2)\n", + "\n", + " \"\"\"Create the original graph (equal to p = 0)\"\"\"\n", + " for i in range(N):\n", + " for j in range(1, k_half + 1):\n", + " self.edges.append((i, (i + j) % N))\n", + "\n", + " \"\"\"Randomly rewire each edge with prob p, start from distance 1\"\"\"\n", + " for j in range(1, k_half + 1):\n", + " for i in range(N):\n", + " if P > np.random.uniform(0, 1):\n", + " new_set = [v for v in range(N) if v != i and (i, v) not\n", + " in self.edges and (v, i) not in self.edges]\n", + " if len(new_set) > 0:\n", + " new = np.random.choice(new_set)\n", + " self.edges.append((i, new))\n", + " old = (i + j) % self.N\n", + " self.edges.remove((i, old))\n", + " # print(\"Rewiring (\", i, old, \") to: (\", i, new)\n", + "\n", + " else:\n", + " print(\"ERROR: Illegal K or N value.\")\n", + " exit(3)\n", + "\n", + " def select(self):\n", + " \"\"\"\n", + " Randomly select edges from the graph, so that each player is drawn at\n", + " least once.\n", + " :return: A list of tuples, containing players' index\n", + " \"\"\"\n", + " edges = self.edges\n", + " nodes = list(range(self.N))\n", + " select = []\n", + " selectedNodes = {i: 0 for i in range(self.N)}\n", + "\n", + " if self.K == self.N - 1: #Well-mixed graph\n", + " permutation = np.random.permutation(self.N)\n", + " selectedNodes = {i: 1 for i in range(self.N)}\n", + " if self.N % 2 == 1:\n", + " extraNode = np.random.randint(0, self.N)\n", + " while extraNode == permutation[self.N - 1]:\n", + " extraNode = np.random.randint(0, self.N)\n", + " permutation = np.append(permutation, extraNode)\n", + " selectedNodes[extraNode] += 1\n", + "\n", + " select = permutation.reshape((int(len(permutation)/2), 2))\n", + " else:\n", + " while edges: # Loop when edges is not empty\n", + " i, j = edges[np.random.randint(0, len(edges))]\n", + " # print(\"selected nodes:\", i, j)\n", + " select.append((i, j))\n", + " nodes.remove(i)\n", + " nodes.remove(j)\n", + " selectedNodes[i] += 1\n", + " selectedNodes[j] += 1\n", + " # print(\"Remaining nodes:\", nodes)\n", + " edges = [(a, b) for (a, b) in edges if (a != i) and (a != j)\n", + " and (b != i) and (b != j)]\n", + " # print(\"after removal\", edges)\n", + "\n", + " while nodes:\n", + " v = nodes.pop(np.random.randint(0, len(nodes)))\n", + " v_edges = [(i, j) for (i, j) in self.edges if i == v or j == v]\n", + " i, j = v_edges[np.random.randint(len(v_edges))]\n", + " select.append((i, j))\n", + " selectedNodes[i] += 1\n", + " selectedNodes[j] += 1\n", + "\n", + " # print(\"Number of each nodes selected:\", selectedNodes)\n", + " self.selectedNodes = selectedNodes\n", + " return select\n", + "\n", + "\n", + " def getNodesNumber(self):\n", + " \"\"\"\n", + " :return: A dictionary specify how many times each player are drawn from\n", + " the last select()\n", + " \"\"\"\n", + " return self.selectedNodes\n", + "\n", + " def getEdgeList(self):\n", + " return self.edges\n", + " \n", + "\n", + " \n", + "class Game:\n", + " def __init__(self, N=100, R=1, K=99, P=0, Actions=[0, 0.2, 0.4, 0.6, 0.8],\n", + " I=1000, RF=0, alpha=1, epsilon=0.1,multiArm='greedy',\n", + " threshold=0.8):\n", + " self.N = N\n", + " self.M = 2\n", + " self.RF = RF\n", + " self.alpha = alpha\n", + " self.R = R\n", + " self.threshold = threshold\n", + " self.actions = Actions\n", + " self.iterations = I\n", + "\n", + " \"\"\"\n", + " | 2-Player Game Graph Model: (Small-world network)\n", + " |\n", + " | P: Probability of rewiring each original edge in the graph\n", + " |\n", + " | K: The number of edges(games) connected to each player. Has to be an \n", + " | even number. Max k: n - 2 (for even n) | n - 1 (for odd n)\n", + " | k can only be odd as n - 1 (for all n). In cases k = n - 1 -> a \n", + " | fully connected graph\n", + " \"\"\"\n", + " self.rewire_p = P\n", + " self.rewire_k = K\n", + " # assert (self.rewire_k < self.N)\n", + " self.graph = Graph(self.N, self.rewire_k, self.rewire_p)\n", + "\n", + " \"Create players\"\n", + " self.players = []\n", + " IW = 100 # Initial Wealth\n", + " self.totalWealth = self.M * IW\n", + " for i in range(self.N):\n", + " self.players.append(Agent(self.R, IW, self.actions,\n", + " epsilon=epsilon, multiArm=multiArm))\n", + "\n", + " def riskfunc(self, contribution, totalwealth):\n", + " \"\"\"\n", + " Implemented different risk functions here.\n", + " :return: the probability of disaster happening, given contribution\n", + " and total wealth\n", + " \"\"\"\n", + "\n", + " proportion = contribution / totalwealth\n", + "\n", + " if self.RF == 0:\n", + " # probably parse more parameters here\n", + " return 1 - proportion\n", + "\n", + "\n", + " elif self.RF == 1:\n", + " if proportion >= self.threshold:\n", + " return 0\n", + " else:\n", + " return 1\n", + "\n", + "\n", + " elif self.RF == 2:\n", + "\n", + " if proportion < self.threshold:\n", + " return 1 - proportion / self.threshold\n", + " else:\n", + " return 0\n", + "\n", + " return \"error\"\n", + "\n", + " def play(self):\n", + " \"\"\"\n", + " Play a whole trial of I (1000) iterations, N (100) players games\n", + " :return: a 3d numpy matrix, recording the averaged counted number of\n", + " all actions in each round in all iterations.\n", + " \"\"\"\n", + "\n", + " results = np.zeros((self.iterations, self.R, len(self.actions)))\n", + " \"\"\"ITERATION\"\"\"\n", + " for iter in range(self.iterations):\n", + " # print(\"GAME ITERATION\", iter)\n", + "\n", + " actionTable = np.zeros((self.N, self.R))\n", + " strategyTable = np.zeros((self.R, self.N)) # DIFFERENT AXIS R-N\n", + " lossTable = np.zeros((self.N, self.R))\n", + "\n", + " for playerIndex in range(self.N): # For each player\n", + " player = self.players[playerIndex]\n", + " player.resetWealth() # reset initial wealth\n", + " for r in range(self.R): # For each round\n", + " action = player.chooseAction(r)\n", + " actionTable[playerIndex][r] = action\n", + " strategyTable[r][playerIndex] = player.getStrategy()[r]\n", + "\n", + " playersNo = self.graph.select()\n", + " for r in range(self.R):\n", + " for [i, j] in playersNo:\n", + " pool = 0\n", + " pool += self.players[i].getWealth() * actionTable[i][r] + \\\n", + " self.players[j].getWealth() * actionTable[j][r]\n", + " risk = self.riskfunc(pool, self.totalWealth)\n", + "\n", + " for p in [i, j]:\n", + " if np.random.uniform(0, 1) < risk:\n", + " lossTable[p, r] += self.alpha / \\\n", + " self.graph.getNodesNumber()[p]\n", + " for i in range(self.N):\n", + " self.players[i].updateReward(r, actionTable[i][r],\n", + " lossTable[i][r])\n", + "\n", + " for r in range(self.R):\n", + " unique, count = np.unique(strategyTable[r], return_counts=True)\n", + " round_counter = dict(zip(unique, count))\n", + " # print(\"Round \", r, round_counter)\n", + "\n", + " for a in range(len(self.actions)):\n", + " if self.actions[a] not in round_counter:\n", + " pass\n", + " else:\n", + " results[iter, r, a] = round_counter[self.actions[a]]\n", + "\n", + " return results" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "0rTn1unXotNt", + "colab_type": "text" + }, + "source": [ + "Then, run the supporting graphic and t-test definitions." + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "m8B4PBOUpsZe", + "colab_type": "code", + "colab": {} + }, + "source": [ + "def stackPlot(data, r, Actions, Iterations, legendLoc='best', titleComment=\"\"):\n", + " \"\"\"\n", + " Draw a stack plot from averaged data of round r.\n", + " \"\"\"\n", + " A = len(Actions)\n", + " x = range(Iterations)\n", + " y = np.zeros((Iterations, A))\n", + " for i in range(Iterations):\n", + " y[i] = data[i][r]\n", + " y = np.vstack(y.T)\n", + "\n", + " fig, ax = plt.subplots()\n", + " ax.stackplot(x, y, labels=Actions, colors=[str(0.9 - 0.9 * x) for x in\n", + " Actions])\n", + " ax.legend(loc=legendLoc)\n", + " plt.ylabel('Percentage of each action')\n", + " plt.xlabel('Time(iterations)')\n", + "\n", + " title = 'Average Composition of Actions in Round ' + str(r + 1)\n", + " if titleComment:\n", + " title += \"\\n\" + titleComment\n", + "\n", + " plt.title(title)\n", + "\n", + " # plt.savefig(titleComment + \" in round \" + str(r+1) + \".png\")\n", + "\n", + " plt.show()\n", + "\n", + "\n", + "def rep(repeat=30, R=1, Actions=[0, 0.2, 0.4, 0.6, 0.8], I=1000, **kwargs):\n", + " \"\"\"\n", + " Repeat the game over (30) trials and retrieve the average data of\n", + " game.play()\n", + " :return: Averaged game results, same shape as the return of game.play()\n", + " \"\"\"\n", + " data = np.zeros((I, R, len(Actions)))\n", + " Actions.sort()\n", + " for re in range(repeat):\n", + "# print(\"REP\", re)\n", + " g = Game(R=R, Actions=Actions, I=I, **kwargs)\n", + " result = g.play()\n", + " data += result\n", + " data /= repeat\n", + " return data\n", + "\n", + "\n", + "def averageOfLast(data, Actions, N=100, r=0, lastIterations=100):\n", + " \"\"\"\n", + " Averaged contribution and action counter of last (100) iterations from the\n", + " data produced by rep()\n", + " :return: a tuple: (average contribution, a dictionary as action counter)\n", + " \"\"\"\n", + " sum = 0\n", + " action_counter = {action: 0 for action in Actions}\n", + "\n", + " for i in range(-1, -lastIterations - 1, -1):\n", + " sum += np.sum(data[i, r] * Actions)\n", + " for a in range(len(Actions)):\n", + " action_counter[Actions[a]] += data[i, r, a] / lastIterations\n", + " return (sum / (lastIterations * N), action_counter)\n", + "\n", + "\n", + "def graph_kp3d(Actions, Klist=[2, 4, 8, 10], Plist=[0, 0.3, 0.6, 0.9],\n", + " repeat=30, N=100, **kwargs):\n", + " \"\"\"\n", + " Draw a 3D graph for graph-based model, showing the effect of K and P on\n", + " average contributions. (No effect observed)\n", + " \"\"\"\n", + "\n", + " K = Klist\n", + " P = Plist\n", + " meanA = np.zeros((len(K), len(P)))\n", + "\n", + " for k in range(len(K)):\n", + " for p in range(len(P)):\n", + " data = rep(repeat, K=K[k], P=P[p], Actions=Actions, **kwargs)\n", + " meanA[k][p] = averageOfLast(data, Actions, lastIterations=100,\n", + " N=N)[0]\n", + " print(\"k, p, mean\", k, p, meanA[k][p])\n", + "\n", + " P, K = np.meshgrid(P, K)\n", + "\n", + " fig = plt.figure()\n", + " ax = fig.gca(projection='3d')\n", + "\n", + " surf = ax.plot_surface(P, K, meanA, cmap=cm.coolwarm,\n", + " linewidth=0, antialiased=False)\n", + "\n", + " fig.colorbar(surf, shrink=0.5, aspect=5)\n", + " plt.show()\n", + "\n", + "\n", + "def graph3d_alpha_threshold(Actions, repeat=30,\n", + " AlphaList=np.arange(0, 1.01, 0.05),\n", + " ThreshList=np.arange(0.1, 1.05, 0.05),\n", + " N=100, **kwargs):\n", + " \"\"\"\n", + " Draw two 3D graphs showing the average contribution and the average\n", + " contribution divided by threshold on two parameters: alpha and threshold\n", + " \"\"\"\n", + " mean = np.zeros((len(ThreshList), len(AlphaList)))\n", + " ratio_by_threshold = np.zeros((len(ThreshList), len(AlphaList)))\n", + "\n", + " for t in range(len(ThreshList)):\n", + " for a in range(len(AlphaList)):\n", + " print(\"Calculating... t, alpha = \", t, a)\n", + " data = rep(repeat=repeat, Actions=Actions, alpha=AlphaList[a],\n", + " threshold=ThreshList[t], **kwargs)\n", + " mean[t][a] = averageOfLast(data, Actions, lastIterations=100,\n", + " N=N)[0]\n", + " ratio_by_threshold[t] = mean[t] / ThreshList[t]\n", + "\n", + " A, T = np.meshgrid(AlphaList, ThreshList)\n", + "\n", + " fig = plt.figure()\n", + " ax = fig.gca(projection='3d')\n", + "\n", + " surf = ax.plot_surface(A, T, mean, cmap=cm.Greys,\n", + " linewidth=0, antialiased=False)\n", + " ax.set_xlabel('Alpha')\n", + " # ax.invert_xaxis()\n", + " ax.set_ylabel('Threshold')\n", + " ax.set_zlabel('Average contribution')\n", + " fig.colorbar(surf, shrink=0.5, aspect=5)\n", + " # plt.show()\n", + "\n", + "\n", + " fig2 = plt.figure()\n", + " ax2 = fig2.gca(projection='3d')\n", + " surf2 = ax2.plot_surface(A, T, ratio_by_threshold, cmap=cm.Greys,\n", + " linewidth=0, antialiased=False)\n", + " ax2.set_xlabel('Alpha')\n", + " # ax.invert_xaxis()\n", + " ax2.set_ylabel('Threshold')\n", + " # ax.invert_yaxis()\n", + " ax2.set_zlabel('Average contribution by threshold')\n", + " fig2.colorbar(surf2, shrink=0.5, aspect=5)\n", + " plt.show()\n", + "\n", + "\n", + "def stackBar(r, Actions, repeat=30, multiArm='greedy', legendLoc='best',\n", + " **kwargs):\n", + " \"\"\"\n", + " Draw a stack bar graph, to compare the composition of actions on one\n", + " parameter, specified as a list in **kwargs\n", + " \"\"\"\n", + "\n", + " key = -1\n", + " alist = []\n", + " for k, v in kwargs.items():\n", + " if isinstance(v, list):\n", + " if key == -1:\n", + " key = k\n", + " alist = v\n", + " else:\n", + " print(\"ERROR, Stack Bar Graph Expects Only 1 List to Compare\")\n", + " exit(4)\n", + " del kwargs[key]\n", + "\n", + " print(\"Comparing:\", key)\n", + " print(\"On:\", alist)\n", + "\n", + " A = len(Actions)\n", + " p = []\n", + " count = np.zeros((A, len(alist))) # of each action in each iter\n", + " ind = np.arange(len(alist))\n", + " width = 0.3\n", + "\n", + " for al in range(len(alist)):\n", + " newKwargs = {**{key: alist[al]}, **kwargs}\n", + " if key == 'N':\n", + " newKwargs['K'] = alist[al] - 1\n", + " elif 'N' not in newKwargs.keys():\n", + " newKwargs['N'] = 100 # default value\n", + " data = rep(repeat, Actions=Actions, multiArm=multiArm, **newKwargs) /\\\n", + " newKwargs['N'] * 100\n", + " action_counter = averageOfLast(data, Actions, r=r,\n", + " lastIterations=100)[1]\n", + " for a in range(A):\n", + " count[a, al] = action_counter[Actions[a]]\n", + " base = 0\n", + "\n", + " for a in range(A):\n", + " p.append(plt.bar(ind, count[a], width, bottom=base,\n", + " color=str(0.9 - 0.9 * Actions[a])))\n", + " base += count[a]\n", + "\n", + " plt.ylabel('Percentage of Actions')\n", + " if key == 'epsilon':\n", + " plt.xlabel(key + ' (' + multiArm + ')')\n", + " else:\n", + " plt.xlabel(key)\n", + " plt.title('Average Composition of Actions in Round ' + str(r + 1))\n", + " plt.xticks(ind, alist)\n", + " plt.yticks(np.arange(0, 101, 10))\n", + " plt.legend(tuple([p[x][0] for x in range(A)][::-1]), tuple(Actions[::-1]),\n", + " loc=legendLoc)\n", + " plt.show()\n", + "\n", + "\n", + "def t_test(repeat, Actions, r=0, R=1, I=1000, lastIterations=100, N=100,\n", + " byThreshold=False, **kwargs):\n", + " \"\"\"\n", + " Compute the p-value of average contributions on two values of one\n", + " parameter, specified as a tuple in **kwargs\n", + " \"\"\"\n", + " key = -1\n", + " atuple = ()\n", + " for k, v in kwargs.items():\n", + " if isinstance(v, tuple):\n", + " if key == -1:\n", + " key = k\n", + " atuple = v\n", + " else:\n", + " print(\"ERROR, T-Test Expects Only 1 Tuple to Compare\")\n", + " exit(5)\n", + " del kwargs[key]\n", + "\n", + " samples = np.zeros((2, repeat))\n", + "\n", + " for s in (0, 1):\n", + " newArgs = {**{key: atuple[s]}, **kwargs}\n", + " samples[s] = repHist(repeat, Actions, R, r, I, lastIterations, N,\n", + " **newArgs)\n", + " if byThreshold:\n", + " samples[s] /= newArgs[\"threshold\"]\n", + " print(\"Sample\", s, samples[s])\n", + "\n", + " print(stats.ttest_ind(samples[0], samples[1]))\n", + "\n", + "\n", + "def repHist(repeat, Actions, R=1, r=0, I=1000, lastIterations=100, N=100,\n", + " **kwargs):\n", + " \"\"\"\n", + " :return: A list of average contributions of all repetitions\n", + " \"\"\"\n", + " hist = np.zeros(repeat)\n", + " for re in range(repeat):\n", + " # print(\"HistREP\", re)\n", + " g = game.Game(R=R, Actions=Actions, I=I, N=N, **kwargs)\n", + " result = g.play()\n", + " hist[re] = averageOfLast(result, Actions, N, r, lastIterations)[0]\n", + " return hist" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "ObdagnBgpzed", + "colab_type": "text" + }, + "source": [ + "Before generating results, define the default values.\n", + "* lower repeat value to yield faster results, but less accurate\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "-BQBZ9qOqCa3", + "colab_type": "code", + "colab": {} + }, + "source": [ + "N = 100\n", + "R = 1\n", + "K = 99\n", + "P = 0\n", + "I = 1000\n", + "RF = 0\n", + "alpha = 1\n", + "Actions = [0, 0.2, 0.4, 0.6, 0.8]\n", + "repeat = 30" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "9CzS0FO6qNW-", + "colab_type": "text" + }, + "source": [ + "Figure 2:" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "Pbu5TljSqXun", + "colab_type": "code", + "colab": {} + }, + "source": [ + "data = rep(repeat=repeat, N=100, alpha=0.8, R=8)\n", + "stackPlot(data, r=0, Iterations=I, Actions=Actions, legendLoc='lower right')" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "iqNPxiiMqXAR", + "colab_type": "text" + }, + "source": [ + "Figure 3:" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "VOrAvfEMrFwN", + "colab_type": "code", + "colab": {} + }, + "source": [ + "stackBar(0, Actions, repeat=repeat,\n", + " alpha=[0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1],\n", + " legendLoc='lower left')" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "FvfkveaVr1yq", + "colab_type": "text" + }, + "source": [ + "Figure 4:" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "yhHJH0N8r1DE", + "colab_type": "code", + "colab": {} + }, + "source": [ + "data = rep(repeat, R=8)\n", + "for r in [0, 1, 3]:\n", + " stackPlot(data, r, Actions, I, legendLoc='lower right')" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "iOZCEyuZr0FH", + "colab_type": "text" + }, + "source": [ + "Figure 5:" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "KM96KjnQsDMJ", + "colab_type": "code", + "colab": {} + }, + "source": [ + "stackBar(0, Actions, repeat=repeat,\n", + " threshold=[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1],\n", + " legendLoc='upper left', RF=2)" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "MWqvxW5ssTGW", + "colab_type": "text" + }, + "source": [ + "Figure 6:" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "qOggilpGsSy1", + "colab_type": "code", + "colab": {} + }, + "source": [ + "data = rep(repeat=repeat, Actions=Actions, R=1, I=I, RF=2, threshold=0.2)\n", + "stackPlot(data, r=0, Iterations=I, Actions=Actions,\n", + " titleComment=\"threshold = 0.2\")" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "tZzJYF6OsZK1", + "colab_type": "text" + }, + "source": [ + "Figure 7 & 8 : 3D graph comparing alpha and threshold" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "LGbBOdpzsY8V", + "colab_type": "code", + "colab": {} + }, + "source": [ + "graph3d_alpha_threshold(Actions, repeat=repeat, RF=2)" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "JDxeu4KesjN-", + "colab_type": "text" + }, + "source": [ + "Figure 9 : simple line graph comparing alpha for threshold=0.2" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "6GZkRJ6EsjBL", + "colab_type": "code", + "colab": {} + }, + "source": [ + "alphaList = np.arange(0, 1.01, 0.02)\n", + "mean = np.zeros(len(alphaList))\n", + "for i in range(len(alphaList)):\n", + " data = rep(repeat, alpha=alphaList[i], threshold=0.2, RF=2)\n", + " mean[i] = averageOfLast(data, Actions)[0]\n", + "\n", + "plt.plot([0.2, 0.2], '--', color='0.5')\n", + "plt.plot(alphaList, mean, color='black')\n", + "\n", + "plt.ylabel('Average Contributions')\n", + "plt.xlabel('Alpha, the loss fraction')\n", + "plt.show()" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "ENMPhvNwsvYp", + "colab_type": "text" + }, + "source": [ + "Figure 10 : Comparing composition on epsilon (greedy)" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "VW3O-JWfs0nE", + "colab_type": "code", + "colab": {} + }, + "source": [ + "stackBar(0, Actions, repeat=repeat, multiArm='greedy',\n", + " legendLoc='lower right',\n", + " epsilon=[0.05, 0.1, 0.15, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8,0.9])" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Z_SsvVFos93T", + "colab_type": "text" + }, + "source": [ + "Figure 11 : Extending 0.2-greedy to 5000 iterations" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "ZYVSFfKys5MY", + "colab_type": "code", + "colab": {} + }, + "source": [ + "data = rep(repeat=repeat, Actions=Actions, multiArm='greedy',\n", + " epsilon=0.2, I=5000)\n", + "stackPlot(data, r=0, Iterations=5000, Actions=Actions,\n", + " titleComment=\"0.2 - greedy\", legendLoc='lower left')" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "pBIM37BHtP0Q", + "colab_type": "text" + }, + "source": [ + "Figure 12 : Comparing composition on epsilon (decrease)" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "bexqMZLttPkZ", + "colab_type": "code", + "colab": {} + }, + "source": [ + "stackBar(0, Actions, repeat=repeat, multiArm='decrease',\n", + " legendLoc='lower left',\n", + " epsilon=[0.1, 0.4, 0.8, 0.9, 0.95, 0.98, 0.99, 0.999, 0.9999])" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "s-7lBnTMtZBF", + "colab_type": "text" + }, + "source": [ + "Figure 13 : Extending 0.999-decrease to 5000 iterations" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "o3P9yUCXtY3Y", + "colab_type": "code", + "colab": {} + }, + "source": [ + "data = rep(repeat=repeat, Actions=Actions, multiArm='decrease',\n", + " epsilon=0.999, I=5000)\n", + "stackPlot(data, r=0, Iterations=5000, Actions=Actions,\n", + " titleComment=\"0.999 - decrease\", legendLoc='lower left')" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "CyJQ8h4ptgR6", + "colab_type": "text" + }, + "source": [ + "T-tests 1: Average contribution of different T" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "6OxMY-g9tgHp", + "colab_type": "code", + "colab": {} + }, + "source": [ + "t_test(30, Actions, alpha=1, RF=2, threshold=(0.9, 1.0)) #p=0.2708\n", + "t_test(30, Actions, alpha=1, RF=2, threshold=(0.8, 1.0)) #p=0.1096\n", + "t_test(30, Actions, alpha=1, RF=2, threshold=(0.7, 1.0)) #p=0.1633\n", + "t_test(30, Actions, alpha=1, RF=2, threshold=(0.6, 1.0)) #p=0.2208\n", + "\n", + "t_test(30, Actions, alpha=1, RF=2, threshold=(0.5, 1.0)) #p=2.2067e-08" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "MXQ3ac_ptsUu", + "colab_type": "text" + }, + "source": [ + "T-test 2 : Average contribution of different alpha when T=0.2" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "QSvs63Xsts3Z", + "colab_type": "code", + "colab": {} + }, + "source": [ + "base = repHist(30, Actions, alpha=1, RF=2, threshold=0.2)\n", + "for alpha in np.arange(0.8, 1, 0.01):\n", + " compare = repHist(30, Actions, alpha=alpha, RF=2, threshold=0.2)\n", + " print(\"Alpha=\", alpha, stats.ttest_ind(base, compare))" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "vsnklN-xtz_r", + "colab_type": "text" + }, + "source": [ + "T-test 3 : Avg contribution of Epsilon-decrease 0.99 with 0.1 and 0.999" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "MWKw3TGTtze3", + "colab_type": "code", + "colab": {} + }, + "source": [ + "base = repHist(30, Actions, multiArm='decrease', epsilon=0.99)\n", + "for epsilon in (0.1, 0.999):\n", + " compare = repHist(30, Actions, multiArm='decrease', epsilon=epsilon)\n", + " print(\"Epsilon=\", epsilon, stats.ttest_ind(base, compare))" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "AzunuVd9t92Q", + "colab_type": "text" + }, + "source": [ + " T-test 4. Avg contribution of 0.999-decrease 5000 iterations with 0.9" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "rN-QXQxJuDOy", + "colab_type": "code", + "colab": {} + }, + "source": [ + "base = repHist(30, Actions, multiArm='decrease', epsilon=0.9)\n", + "compare = repHist(30, Actions, multiArm='decrease', epsilon=0.999, I=5000)\n", + "print(stats.ttest_ind(base, compare))" + ], + "execution_count": 0, + "outputs": [] + } + ] +} \ No newline at end of file -- GitLab