def test_one_hot_5d(): array = np.array([[4, 4, 1], [3, 0, 2]]) a = one_hot(array, 5) b = np.array([[[0, 0, 0, 0, 1], [0, 0, 0, 0, 1], [0, 1, 0, 0, 0]], [[0, 0, 0, 1, 0], [1, 0, 0, 0, 0], [0, 0, 1, 0, 0]]]) assert np.array_equal(a, b), "with depth 5, not correctly onehot encoded"
def decode(self, z, apply_softmax=False, apply_onehot=False): """ Decodes multiple latent variables. """ x_hat = self.decoder(z) if apply_softmax: return tf.nn.softmax(x_hat, axis=-1) if apply_onehot: return one_hot(tf.argmax(x_hat, axis=-1).numpy()) return x_hat
def test_one_hot_default(): array = np.array([[4, 6, 10], [3, 0, 2]]) a = one_hot(array) b = np.array([[[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0]], [[0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]]]) assert np.array_equal( a, b), "with default depth, not correctly onehot encoded"
def find_positions(self, entries, save_entries=True, frecency=False): positions = [] for agent_entries in entries: artefacts = np.array( [entry["artefact"] for entry in agent_entries]) x = reverse_sequences(one_hot(artefacts)) zs = self.rvae.encode(x) if save_entries: self.save(agent_entries, zs, frecency=frecency) positions.append(np.mean(zs[0], axis=0)) return np.array(positions)
def save(self, entries, zs=None, frecency=False): """ Stores entries in the reposity, generates latent encodings if not provided. """ if zs is None: artefacts = np.array([entry["artefact"] for entry in entries]) x = reverse_sequences(one_hot(artefacts)) zs = self.rvae.encode(x) for entry, z_mean, z_logvar, z in zip(entries, *zs): domain_entry = { **entry, "domain_z_mean": z_mean.numpy(), "domain_z_logvar": z_logvar.numpy(), "domain_z": z.numpy() } self.repository.append(domain_entry) if frecency: self.frecency.update({entry['id']: 10})
def run_simulation(args): start_time = time.time() parameters = pd.Series(vars(args)) data = { "parameters": parameters, "evaluations": [], "reconstructions": [], "interactions": [] } # ----------------------------------------------------------------------------------------- # -- SETUP domain_seed_path = os.path.join(data_path, "seeds", "domain_seed.npy") agent_seeds_path = os.path.join(data_path, "seeds", "agent_seeds.npy") try: domain_seed = np.load(domain_seed_path, allow_pickle=True) agent_seeds = np.load(agent_seeds_path, allow_pickle=True) except IOError as e: print(e.args) return 1 recommender = Recommender(domain_seed, init_epochs=args.i_epochs) agents = [ Agent(i, seed, init_epochs=args.i_epochs) for i, seed in enumerate(agent_seeds) ] # -- Other sim settings uniform_mode = args.interaction_mode == 'uniform' frecency_mode = args.interaction_mode == 'frecency' density_mode = args.interaction_mode == 'density' # ----------------------------------------------------------------------------------------- # -- EPOCH 0 # -- prepare initial artefacts # seed[np.random.choice(np.arange(len(seed)), size=args.n_select, replace=False)] # returns the artefacts and their z_means initial_artefacts = [ agent.build(agent.sample(1, args.n_select)) for agent in agents ] for agent, (artefacts, z_means) in zip(agents, initial_artefacts): initial_entries = [ make_entry(0, agent, artefact, z_mean) for artefact, z_mean in zip(artefacts, z_means) ] recommender.save(initial_entries, frecency=frecency_mode) selected = [artefact[0] for artefact in initial_artefacts] assert np.array(selected).shape == (args.n_agents, args.n_select, 16, 12) if args.interaction_mode == "density": # -- generate the first ball tree recommender.generate_ball_tree() print("\nStarting simulation with the following parameters:") print(parameters.to_string(), end="\n\n") # ----------------------------------------------------------------------------------------- # -- LOOP for epoch in range(1, args.n_epochs + 1): print(f"Epoch {epoch:03d}...", end=" ") epoch_start = time.time() # ------------------------------------------------------------------------------------- # -- INDIVIDUALS new_entries = [] evaluation = {} reconstruction = {} for i, agent in enumerate(agents): # learn z_means = agent.learn(selected[i], args.budget) # sample n new artefacts if args.production_mode == "interpolate": z = agent.interpolate(z_means) if args.production_mode == "origin": z = agent.sample(args.novelty_preference, args.n_artefacts) # calculate novelty values? artefacts, _ = agent.build(z) # entry = make_entry(epoch, agent, artefacts[0], z_mean) agent_entries = [ make_entry(epoch, agent, artefacts[0], 0) for artefact in artefacts ] # store new_entries.append(agent_entries) # ------------------------------------------------------------------------------------- # -- DOMAIN positions = recommender.find_positions(new_entries, save_entries=True, frecency=frecency_mode) # ------------------------------------------------------------------------------------- # -- FIELD selected_ids = [] # TODO: implement different social interaction policies. for i, agent in enumerate(agents): # -- FIELD NEIGHBOURS # calculate distances to other agents distances = np.linalg.norm(positions[i] - positions, axis=1) # get neighbours, sort, return indices, remove current agent neighbours = [ nghbr for nghbr in np.argsort(distances) if nghbr != agent.id ] assert agent.id not in neighbours, "Current agent is present in neighbour list." # record interactions data["interactions"] += [{ "epoch": epoch, "agent_id": agent.id, "position": positions[i], "neighbours": neighbours, "distances": distances }] # gather artefacts created by the field available_artefacts = recommender.select_artefacts( agent.id, with_ids=(not uniform_mode)) for neighbour_id in neighbours: neighbour_artefacts = recommender.select_artefacts( neighbour_id, with_ids=(not uniform_mode)) available_artefacts = np.vstack( [available_artefacts, neighbour_artefacts]) # -- FIELD MODE # default is uniform, which means no ideology in the population probabilities = None if not uniform_mode: artefact_ids = available_artefacts[:, 0] available_artefacts = np.vstack(available_artefacts[:, 1]) # if based on density, the population favors artefacts which are "more" # unique, based on the estimated density in their space. # Calculates the inverse in order to favor low density artefacts. if density_mode: # artefact_ids = available_artefacts[:, 0] densities = 1 / recommender.find_densities(artefact_ids) probabilities = densities / np.sum(densities) # if based on frecency, the populations doesn't linger on the past. # it favors recent and frequent creations. if frecency_mode: # artefact_ids = available_artefacts[:, 0] counts = recommender.get_frecency_counts(artefact_ids) probabilities = counts / np.sum(counts) # -- FIELD SELECTION choices = np.random.choice(np.arange(len(available_artefacts)), size=args.n_select, replace=False, p=probabilities) selected_artefacts = available_artefacts[choices] if args.interaction_mode == "frecency": selected_ids.append(artefact_ids[choices]) # make the choices one hot gaain selected[i] = one_hot(selected_artefacts) # -- WRAP UP EVALUATIONS FOR EACH AGENT agent_entries = recommender.select_entries(agent.id) agent_artefacts = one_hot( np.array([entry["artefact"] for entry in agent_entries])) # NOTE: considerable computational resources, consider every n epochs # CONSIDER: Evaluate on the seed? data["evaluations"] += [{ "epoch": epoch, "agent_id": agent.id, **agent.evaluate(agent_artefacts) }] # NOTE: considerable computational resources, consider every n epochs data["reconstructions"] += agent.reconstruct( epoch, agent_entries, agent_artefacts) # ------------------------------------------------------------------------------------- # -- ON EPOCH END UPDATES # -- with the new artefacts generate a new ball tree if args.interaction_mode == "density": recommender.generate_ball_tree() if args.interaction_mode == 'frecency': recommender.update_frecency(np.hstack(selected_ids)) epoch_log_time = f"{time.time() - epoch_start:0.3f}s".ljust(15, " ") print(epoch_log_time, end=("\r" if epoch < args.n_epochs else "\n")) end_time = time.time() elapsed = end_time - start_time print(f"Total time elapsed: {elapsed:0.3f}s") # ------------------------------------------------------------------------------------- # -- FINALIZE # -- export domain data["domain"] = pd.DataFrame(recommender.export()) # -- sample from agents after_sample = [] for agent in agents: z = np.random.normal(0.0, 0.25, size=(200, 32)) artefacts = np.argmax(agent.rvae.decode(z, apply_onehot=False), axis=-1) after_sample.append([(agent.id, artefact) for artefact in artefacts]) data["after_sample"] = [{k: v for k, v in row} for row in zip(*after_sample)] data["timings"] = pd.Series({ "duration": elapsed, "start_time": time.strftime('%Y-%m-%dT%H-%M-%S', time.localtime(start_time)), "end_time": time.strftime('%Y-%m-%dT%H-%M-%S', time.localtime(end_time)) }) return {k: v if is_pd(v) else pd.DataFrame(v) for k, v in data.items()}