Now we try to build a supervised learner to locate pokemons given some distance levels and rankings inputs at several locations. First let us look at the most simple case - unordered, fixed-length inputs. The output in the case will be the estimated locations of each pokemons.
In [4]:
import numpy as np
import matplotlib.pyplot as plt
import random
import pandas as pd
import matplotlib.patches as patches
from scipy.stats import gennorm
from scipy.stats import gamma
from IPython import display
import pickle
%matplotlib inline
In [5]:
# borrowed helper functions
def generate_initial_coordinates(side_length=2000, n_pokemon=9):
pokemons = {}
for i in range(n_pokemon):
pokemons[i] = np.array([random.uniform(-side_length/2, side_length/2),
random.uniform(-side_length/2, side_length/2)])
return pokemons
def distance(coord1, coord2):
return np.sqrt((coord1[0] - coord2[0])**2 + (coord1[1] - coord2[1])**2)
# this is not visible to players
def pokemon_distances(player_coord, pokemons):
return {i: distance(player_coord, coord) for i, coord in pokemons.items()}
def rank(input):
output = [0] * len(input)
for i, x in enumerate(sorted(range(len(input)), key=lambda y: input[y])):
output[x] = i
return output
# player will be able to see this
# slight bug - we will not be able to see rankings of pokemons that are
# out of radar radius (but we can fix this later)
# def pokemon_rankings(player_coord, pokemons):
# dists = pokemon_distances(player_coord, pokemons)
# rankings = {}
# for i, x in enumerate(sorted(range(len(dists)), key=lambda y: dists[y])):
# rankings[x] = i
# return rankings
def pokemon_rankings(player_coord, pokemons):
dists = pokemon_distances(player_coord, pokemons)
return {i: v for i, v in zip( dists.keys(), np.argsort(np.argsort(list(dists.values()))) )}
def plot_pokemons(player_coord, pokemons, xylim=(-1100, 1100)):
plt.figure(figsize=(15,15))
# non-target pokemons
plt.scatter([x - player_coord[0] for x, y in [coord for coord in pokemons.values()]][1:],
[y - player_coord[1] for x, y in [coord for coord in pokemons.values()]][1:])
# target pokemon
plt.scatter([x - player_coord[0] for x, y in [coord for coord in pokemons.values()]][0],
[y - player_coord[1] for x, y in [coord for coord in pokemons.values()]][0],
marker="*", color='red', s=15)
plt.axes().set_aspect(1)
plt.axes().set_xlim(xylim)
plt.axes().set_ylim(xylim)
# player
plt.scatter(0, 0 , color='purple', s=15)
# detection radii
dists = {10:'green', 25:'blue', 100:'yellow', 1000:'red'}
for r in dists:
plt.axes().add_patch(plt.Circle((0,0), r, fill=False, color=dists[r]))
plt.show()
def footprint(distance):
if distance < 10:
return 0
elif distance < 25:
return 1
elif distance < 100:
return 2
elif distance < 1000:
return 3
else:
return 5
def distance_levels(player_coord, pokemons):
dists = pokemon_distances(player_coord, pokemons)
return {i: footprint(v) for i,v in dists.items()}
def distance_levels_and_rankings(player_coord, pokemons):
dists = pokemon_distances(player_coord, pokemons)
return {i: footprint(v) for i,v in dists.items()}, {i: v for i, v in
zip(dists.keys(),
np.argsort(np.argsort(list(dists.values()))))}
def make_rand_vector(dims):
vec = np.array([random.gauss(0, 1) for i in range(dims)])
mag = np.linalg.norm(vec)
return vec / mag
In [6]:
# training example generator
def generate_training_examples(radius=1000, n_points=30):
pokemons = generate_initial_coordinates(side_length=2000, n_pokemon=9)
samples = pd.DataFrame(columns=['player_coord', 'levels', 'rankings'])
for i in range(n_points):
point_distance = random.random() * radius
point_angle = random.random() * np.pi * 2
point = np.array([point_distance * np.cos(point_angle), point_distance * np.sin(point_angle)])
levels, rankings = distance_levels_and_rankings(point, pokemons)
samples.loc[i] = [point, levels, rankings]
return samples, pokemons
In [7]:
s, p = generate_training_examples()
s
Out[7]:
In [8]:
def flatten_training_example(samples, n_pokemons=9, radius=1000):
flat = pd.DataFrame({'pX': samples['player_coord'].apply(lambda x: x[0] / radius),
'pY': samples['player_coord'].apply(lambda x: x[1] / radius)})
for i in range(n_pokemons):
flat['lv' + str(i)] = samples['levels'].apply(lambda x: x[i])
flat['rg' + str(i)] = samples['rankings'].apply(lambda x: x[i])
return flat
In [9]:
flatten_training_example(s)
Out[9]:
In [18]:
def random_point(radius=1000):
point_distance = random.random() * radius
point_angle = random.random() * np.pi * 2
return np.array([point_distance * np.cos(point_angle), point_distance * np.sin(point_angle)])
def generate_training_ndarray(radius=500, n_points=50, n_examples=100, n_pokemons=9):
train = np.ndarray(shape=[n_examples, n_points, 2 + n_pokemons *2])
train.fill(0)
target = np.ndarray(shape=[n_examples, n_pokemons, 2])
for z in range(n_examples):
pokemons = generate_initial_coordinates(side_length=2000)
target[z, :, :] = list(pokemons.values())
for x in range(n_points):
train[z, x, 0:2] = random_point(radius)
levels, rankings = distance_levels_and_rankings(train[z, x, 0:2], pokemons)
train[z, x, 2:11] = list(levels.values())
train[z, x, 11:] = list(rankings.values())
return train, target
In [19]:
train, target = generate_training_ndarray(n_examples=100000)
In [20]:
pickle.dump({'train': train, 'target': target}, open('training_data.pickle', 'wb'))
In [21]:
obj = pickle.load(open('training_data.pickle', 'rb'))
obj['train'].shape
Out[21]:
In [ ]: