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"
Beispiel #2
0
    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"
Beispiel #4
0
    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)
Beispiel #5
0
    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})
Beispiel #6
0
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()}