Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add AverageLearner1D and AverageLearner2D #143

Open
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

basnijholt
Copy link
Member

@basnijholt basnijholt commented Dec 19, 2018

(original merge request on GitLab)

opened by Bas Nijholt (@basnijholt) at 2018-06-05T21:40:00.078Z

This merge request implements a Learner2D that can learn averages on the points, the AverageLearner2D.

When choosing points the learner can either

  • add more values at an existing points
  • add more triangles

The learner compares the loss of potential new triangles with the standard error of an existing point.

The relative importance of both can be adjusted by a hyperparameter learner.weight.
From the doc-string:

When weight > 1 adding more points to existing points will be
prioritized (making the standard error of a point more important,)
otherwise adding new triangles will be prioritized (making the
loss of a triangle more important.)

All tests that pass for the Learner2D currently pass for the AvererageLearner2D too.

Run with:

import adaptive
adaptive.notebook_extension()

def ring(xys, wait=False):
    import numpy as np
    from time import sleep
    from random import random
    xy, _ = xys
    if wait:
        sleep(random()/100)
    x, y = xy
    a = 0.2
    return (np.arctan((x**2 + y**2 - 0.75**2)/a**2)
            + 10 * np.exp(-(x**2 + y**2 - 0.75**2)**2/a**4) * (random() - 1/2))

learner = adaptive.AverageLearner2D(ring, bounds=[(-1, 1), (-1, 1)], weight=.1)
runner = adaptive.Runner(learner, goal=lambda l: l.loss() < 0.01, log=True)
runner.live_info()

which results in:

>>> print(learner.mean_values_per_point()) 
65.2737642585551328

and

learner.plot(tri_alpha=0.5) + learner.plot_std_or_n(which='std')

image

  • Before merging we should observe that this behaves reasonably when the function is heteroscedastic (noise depends on x).
  • Need to verify that δy between neighbouring points is comparable to std(y). This is best to do in 1D learner.
  • write docstring for AverageLearner1D
  • doc-string for AverageLearner2D is from Learner2D for auto complete
  • write doc-strings for properties in reference/adaptive.learner.average1D.html.

@basnijholt basnijholt force-pushed the AverageLearner2D branch 2 times, most recently from 8228cb7 to 79c9edf Compare March 5, 2019 16:52
@basnijholt basnijholt changed the title WIP: AverageLearner2D and AverageLearner1D add AverageLearner1D and AverageLearner2D Mar 5, 2019
@basnijholt basnijholt force-pushed the AverageLearner2D branch 4 times, most recently from a73c167 to 2696f86 Compare March 6, 2019 15:10
@basnijholt basnijholt requested a review from jbweston March 6, 2019 15:10
@basnijholt basnijholt force-pushed the AverageLearner2D branch 5 times, most recently from 5f3aeba to 51f4292 Compare March 7, 2019 13:13
@basnijholt basnijholt mentioned this pull request Mar 18, 2019
@basnijholt
Copy link
Member Author

@anton I have implemented what you suggested in chat:

It's not just that: the two options that make sense are:

  • increase the number of samples in a point by a fixed fraction (e.g. 1.1)
  • add a new point with the number of samples that's comparable to the number of samples in the neighboring points.

The problem now is that once a point has a lot of "seeds", increasing the number of seeds by 10% will give a big loss improvement, probably the biggest, so the number of values at that point will grow very big. Conceptually this shouldn't happen, so I probably made a mistake in the following method:

    def loss_per_existing_point(self):
        """Increase the number of seeds by 10%."""
        if len(self.data) < 4:
            return [], []
        scale = self.value_scale()
        points = []
        loss_improvements = []

        neighbors = self._get_neighbor_mapping_existing_points()
        mean_values_per_neighbor = self._mean_values_per_neighbor(neighbors)

        for p, sem in self.data_sem.items():
            n_neighbors = mean_values_per_neighbor[p]
            N = self.n_values(p)
            n_more = int(1.1 * N)  # increase the amount of points by 10%
            points.append((p, n_more))
            # This is the improvement considering we will add
            # n_more seeds to the stack.
            sem_improvement = (1 / sqrt(N) - 1 / sqrt(N + n_more)) * sem
            loss_improvement = self.weight * sem_improvement / scale  # XXX: Do I need to divide by the scale?
            loss_improvements.append(loss_improvement)
        return points, loss_improvements

@akhmerov
Copy link
Contributor

The problem now is that once a point has a lot of "seeds", increasing the number of seeds by 10% will give a big loss improvement, probably the biggest, so the number of values at that point will grow very big.

If you increase the number of points by 10%, the rms at the point drops by 5%; why would this be the biggest loss improvement?

@basnijholt basnijholt force-pushed the AverageLearner2D branch 3 times, most recently from fd30d36 to ddfc9b8 Compare March 28, 2019 20:18
@basnijholt basnijholt force-pushed the AverageLearner2D branch 4 times, most recently from 61afe1d to 8b448a5 Compare April 12, 2019 12:57
@basnijholt
Copy link
Member Author

I've noticed that the AverageLearner1D/2D aren't working for BalancingLearners because of the ask(..., tell_pending=False) when using bal_learner.strategy = 'loss_improvements'.

@basnijholt
Copy link
Member Author

I've added a cool plotting feature, on hovering over the points it displays extra information:
image

@basnijholt basnijholt force-pushed the AverageLearner2D branch 3 times, most recently from b84633f to 7e060e1 Compare April 29, 2019 21:21
@basnijholt basnijholt force-pushed the AverageLearner2D branch 3 times, most recently from 081b3a5 to ee808d3 Compare May 13, 2019 17:18
@basnijholt
Copy link
Member Author

The failing test test_saving[AverageLearner1D-random_linear_with_peak-learner_kwargs6] is because the y_scale not properly being updated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants