Beispiel #1
0
def test_samplingpath_oddcase():
    x0 = np.array([
        0.19833663, 0.49931288, 0.62744967, 0.47308545, 0.48858042, 0.49025685,
        0.48481497, 0.49068977, 0.49562456, 0.51102634
    ])
    v0 = np.array([
        -0.00053468, -0.00106889, 0.0012165, 0.00737494, 0.00152363,
        -0.00164736, 0.00371493, 0.02057758, -0.00260349, 0.01266826
    ])
    L0 = 0.
    path = SamplingPath(x0, v0, L0)
    for i in range(-10, 11):
        if i != 0:
            path.extrapolate(i)
Beispiel #2
0
    def start_path(self, ui, region):
        """Start new trajectory path."""
        # print("new direction:", self.scale, self.noutside_regions, self.nrejects, self.naccepts)

        v = self.generate_direction(ui, region, scale=self.scale)
        assert (v**2).sum() > 0, (v, self.scale)
        assert region.inside(ui.reshape((1, -1))).all(), ui
        self.path = ContourSamplingPath(SamplingPath(ui, v, 0.0), region)
        if self.grad_function is not None:
            self.path.gradient = self.grad_function

        if not (ui > 0).all() or not (ui < 1).all() or not region.inside(ui.reshape((1, -1))):
            assert False, ui

        self.direction = +1
        self.lasti = 0
        self.cache = {0: (True, ui, self.last[1])}
        self.deadends = set()
        # self.iresets += 1
        if self.log:
            print()
            print("starting new direction", v, 'from', ui)
Beispiel #3
0
    def start_direction(self, region):
        """Choose a new random direction."""
        if self.log:
            print("choosing random direction")
        ui, Li = self.last
        v = generate_random_direction(ui, region, scale=self.scale)
        # v = generate_region_random_direction(ui, region, scale=self.scale)

        self.nrestarts += 1

        if self.sampler is None or True:
            samplingpath = SamplingPath(ui, v, Li)
            contourpath = ContourSamplingPath(samplingpath, region)
            if self.samplername == 'steps':
                self.sampler = ClockedStepSampler(contourpath, log=self.log)
                self.stepper = DirectJumper(self.sampler, self.nsteps, log=self.log)
            elif self.samplername == 'bisect':
                self.sampler = ClockedBisectSampler(contourpath, log=self.log)
                self.stepper = DirectJumper(self.sampler, self.nsteps, log=self.log)
            elif self.samplername == 'nuts':
                self.sampler = ClockedNUTSSampler(contourpath, log=self.log)
                self.stepper = IntervalJumper(self.sampler, self.nsteps, log=self.log)
            else:
                assert False
Beispiel #4
0
def test_reversible_gradient(plot=False):
    def loglike(x):
        x, y = x.transpose()
        return -0.5 * (x**2 + ((y - 0.5) / 0.2)**2)

    def transform(u):
        return u

    Lmin = -0.5

    for i in [84] + list(range(1, 100)):
        print("setting seed = %d" % i)
        np.random.seed(i)
        points = np.random.uniform(size=(10000, 2))
        L = loglike(points)
        mask = L > Lmin
        points = points[mask, :][:100, :]
        active_u = points
        active_values = L[mask][:100]

        transformLayer = AffineLayer(wrapped_dims=[])
        transformLayer.optimize(points, points)
        region = MLFriends(points, transformLayer)
        region.maxradiussq, region.enlarge = region.compute_enlargement(
            nbootstraps=30)
        region.create_ellipsoid()
        nclusters = transformLayer.nclusters
        assert nclusters == 1
        assert np.allclose(region.unormed,
                           region.transformLayer.transform(
                               points)), "transform should be reproducible"
        assert region.inside(
            points).all(), "live points should lie near live points"

        if i == 84:
            v = np.array([0.03477044, -0.01977415])
            reflpoint = np.array([0.09304075, 0.29114574])
        elif i == 4:
            v = np.array([0.03949306, -0.00634806])
            reflpoint = np.array([0.9934771, 0.55358031])

        else:
            v = np.random.normal(size=2)
            v /= (v**2).sum()**0.5
            v *= 0.04
            j = np.random.randint(len(active_u))
            reflpoint = np.random.normal(active_u[j, :], 0.04)
            if not (reflpoint < 1).all() and not (reflpoint > 0).all():
                continue

        bpts = region.transformLayer.transform(reflpoint).reshape((1, -1))
        tt = get_sphere_tangents(region.unormed, bpts)
        t = region.transformLayer.untransform(tt * 1e-3 +
                                              region.unormed) - region.u
        # compute new vector
        normal = t / norm(t, axis=1).reshape((-1, 1))
        print("reflecting at  ", reflpoint, "with direction", v)
        mask_forward1, angles, anglesnew = get_reflection_angles(normal, v)
        if mask_forward1.any():
            j = np.argmin(
                ((region.unormed[mask_forward1, :] - bpts)**2).sum(axis=1))
            k = np.arange(len(normal))[mask_forward1][j]
            angles_used = angles[k]
            normal_used = normal[k, :]
            print("chose normal", normal_used, k)
            #chosen_point = region.u[k,:]
            vnew = -(v - 2 * angles_used * normal_used)
            assert vnew.shape == v.shape

            mask_forward2, angles2, anglesnew2 = get_reflection_angles(
                normal, vnew)
            #j2 = np.argmin(((region.unormed[mask_forward2,:] - bpts)**2).sum(axis=1))
            #chosen_point2 = region.u[mask_forward2,:][0,:]
            #assert j2 == j, (j2, j)
            assert mask_forward2[k]
            #assert_allclose(chosen_point, chosen_point2)

            #for m, a, b, m2, a2, b2 in zip(mask_forward1, angles, anglesnew, mask_forward2, angles2, anglesnew2):
            #    if m != m2:
            #        print('  ', m, a, b, m2, a2, b2)

            #print("using normal", normal)
            #print("changed v from", v, "to", vnew)

            #angles2 = -(normal * (vnew / norm(vnew))).sum(axis=1)
            #mask_forward2 = angles < 0
            if plot:
                plt.figure(figsize=(5, 5))
                plt.title('%d' % mask_forward1.sum())
                plt.plot((reflpoint + v)[0], (reflpoint + v)[1],
                         '^',
                         color='orange')
                plt.plot((reflpoint + vnew)[:, 0], (reflpoint + vnew)[:, 1],
                         '^ ',
                         color='lime')
                plt.plot(reflpoint[0], reflpoint[1], '^ ', color='r')
                plt.plot(region.u[:, 0], region.u[:, 1], 'x ', ms=2, color='k')
                plt.plot(region.u[mask_forward1, 0],
                         region.u[mask_forward1, 1],
                         'o ',
                         ms=6,
                         mfc='None',
                         mec='b')
                plt.plot(region.u[mask_forward2, 0],
                         region.u[mask_forward2, 1],
                         's ',
                         ms=8,
                         mfc='None',
                         mec='g')
                plt.xlim(0, 1)
                plt.ylim(0, 1)
                plt.savefig('test_flatnuts_reversible_gradient_%d.png' % i,
                            bbox_inches='tight')
                plt.close()
            assert mask_forward1[k] == mask_forward2[k], (mask_forward1[k],
                                                          mask_forward2[k])

            print("reflecting at  ", reflpoint, "with direction", v)
            # make that step, then try to go back
            j = np.arange(len(normal))[mask_forward1][0]
            normal = normal[j, :]
            angles = (normal * (v / norm(v))).sum()
            v2 = v - 2 * angle(normal, v) * normal

            print("reflecting with", normal, "new direction", v2)

            #newpoint = reflpoint + v2
            #angles2 = (normal * (v2 / norm(v2))).sum()
            v3 = v2 - 2 * angle(normal, v2) * normal

            print("re-reflecting gives direction", v3)
            assert_allclose(v3, v)

            print()
            print("FORWARD:", v, reflpoint)
            samplingpath = SamplingPath(reflpoint - v, v, active_values[0])
            contourpath = ContourSamplingPath(samplingpath, region)
            normal = contourpath.gradient(reflpoint)
            if normal is not None:
                assert normal.shape == v.shape, (normal.shape, v.shape)

                print("BACKWARD:", v, reflpoint)
                v2 = -(v - 2 * angle(normal, v) * normal)
                normal2 = contourpath.gradient(reflpoint)
                assert_allclose(normal, normal2)
                normal2 = normal
                v3 = -(v2 - 2 * angle(normal2, v2) * normal2)
                assert_allclose(v3, v)
Beispiel #5
0
def test_samplingpath_cubereflect():
    x0 = np.array([0.1, 0.1])
    v0 = np.array([0.1, 0.01])
    L0 = 0.
    path = SamplingPath(x0, v0, L0)
    path.add(-1, x0 - v0, v0, 1.0)
Beispiel #6
0
def test_samplingpath():
    x0 = np.array([0.5, 0.5])
    v0 = np.array([0.1, 0.0])
    L0 = 0.
    path = SamplingPath(x0, v0, L0)
    assert path.interpolate(0) == (x0, v0, L0, True)
    try:
        path.interpolate(1)
        assert False
    except KeyError:
        pass
    try:
        path.interpolate(-1)
        assert False
    except KeyError:
        pass

    path.add(-1, x0 - v0, v0, 1.0)
    x1, v1, L1, on_path = path.interpolate(-1)
    assert_allclose(x1, x0 - v0)
    assert_allclose(v1, v0)
    assert_allclose(L1, 1.0)
    assert on_path

    path.add(4, x0 + 4 * v0, v0, 4.0)
    x1, v1, L1, on_path = path.interpolate(1)
    assert_allclose(x1, x0 + v0)
    assert_allclose(v1, v0)
    assert L1 is None, L1
    assert on_path
Beispiel #7
0
def test_detailed_balance():
    def loglike(x):
        x, y = x.transpose()
        return -0.5 * (x**2 + ((y - 0.5) / 0.2)**2)

    def transform(u):
        return u

    Lmin = -0.5
    for i in range(1, 100):
        print()
        print("---- seed=%d ----" % i)
        print()
        np.random.seed(i)
        points = np.random.uniform(size=(10000, 2))
        L = loglike(points)
        mask = L > Lmin
        points = points[mask, :][:400, :]
        active_u = points
        active_values = L[mask][:400]

        transformLayer = AffineLayer(wrapped_dims=[])
        transformLayer.optimize(points, points)
        region = MLFriends(points, transformLayer)
        region.maxradiussq, region.enlarge = region.compute_enlargement(
            nbootstraps=30)
        region.create_ellipsoid()
        nclusters = transformLayer.nclusters
        assert nclusters == 1
        assert np.allclose(region.unormed,
                           region.transformLayer.transform(
                               points)), "transform should be reproducible"
        assert region.inside(
            points).all(), "live points should lie near live points"

        v = np.random.normal(size=2)
        v /= (v**2).sum()**0.5
        v *= 0.04

        print("StepSampler ----")
        print("FORWARD SAMPLING FROM", 0, active_u[0], v, active_values[0])
        samplingpath = SamplingPath(active_u[0], v, active_values[0])
        problem = dict(loglike=loglike, transform=transform, Lmin=Lmin)
        sampler = ClockedStepSampler(ContourSamplingPath(samplingpath, region))
        check_starting_point(sampler, active_u[0], active_values[0], **problem)
        sampler.expand_onestep(fwd=True, **problem)
        sampler.expand_onestep(fwd=True, **problem)
        sampler.expand_onestep(fwd=True, **problem)
        sampler.expand_onestep(fwd=True, **problem)
        sampler.expand_onestep(fwd=False, **problem)
        sampler.expand_to_step(4, **problem)
        sampler.expand_to_step(-4, **problem)
        check_starting_point(sampler, active_u[0], active_values[0], **problem)

        starti, startx, startv, startL = max(sampler.points)

        print()
        print("BACKWARD SAMPLING FROM", starti, startx, startv, startL)
        samplingpath2 = SamplingPath(startx, -startv, startL)
        sampler2 = ClockedStepSampler(
            ContourSamplingPath(samplingpath2, region))
        check_starting_point(sampler2, startx, startL, **problem)
        sampler2.expand_to_step(starti, **problem)
        check_starting_point(sampler2, startx, startL, **problem)

        starti2, startx2, startv2, startL2 = max(sampler2.points)
        assert_allclose(active_u[0], startx2)
        assert_allclose(v, -startv2)

        starti, startx, startv, startL = min(sampler.points)
        print()
        print("BACKWARD SAMPLING FROM", starti, startx, startv, startL)
        samplingpath3 = SamplingPath(startx, startv, startL)
        sampler3 = ClockedStepSampler(
            ContourSamplingPath(samplingpath3, region))
        check_starting_point(sampler3, startx, startL, **problem)
        sampler3.expand_to_step(-starti, **problem)
        check_starting_point(sampler3, startx, startL, **problem)

        starti3, startx3, startv3, startL3 = max(sampler3.points)
        assert_allclose(active_u[0], startx3)
        assert_allclose(v, startv3)
        print()

        print("BisectSampler ----")
        log = dict(log=True)
        print("FORWARD SAMPLING FROM", 0, active_u[0], v, active_values[0])
        samplingpath = SamplingPath(active_u[0], v, active_values[0])
        sampler = ClockedBisectSampler(
            ContourSamplingPath(samplingpath, region), **log)
        check_starting_point(sampler, active_u[0], active_values[0], **problem)
        sampler.expand_to_step(10, **problem)
        check_starting_point(sampler, active_u[0], active_values[0], **problem)

        starti, startx, startv, startL = max(sampler.points)
        print()
        print("BACKWARD SAMPLING FROM", starti, startx, startv, startL)
        samplingpath2 = SamplingPath(startx, -startv, startL)
        sampler2 = ClockedBisectSampler(
            ContourSamplingPath(samplingpath2, region), **log)
        check_starting_point(sampler2, startx, startL, **problem)
        sampler2.expand_to_step(starti, **problem)
        check_starting_point(sampler2, startx, startL, **problem)

        starti2, startx2, startv2, startL2 = max(sampler2.points)
        if gap_free_path(sampler, 0, starti, **problem) and gap_free_path(
                sampler2, 0, starti2, **problem):
            assert_allclose(active_u[0], startx2)
            assert_allclose(v, -startv2)

        starti, startx, startv, startL = min(sampler.points)
        print()
        print("BACKWARD SAMPLING FROM", starti, startx, startv, startL)
        samplingpath3 = SamplingPath(startx, -startv, startL)
        sampler3 = ClockedBisectSampler(
            ContourSamplingPath(samplingpath3, region), **log)
        check_starting_point(sampler3, startx, startL, **problem)
        sampler3.expand_to_step(starti, **problem)
        check_starting_point(sampler3, startx, startL, **problem)

        starti3, startx3, startv3, startL3 = min(sampler3.points)
        if gap_free_path(sampler, 0, starti, **problem) and gap_free_path(
                sampler3, 0, starti3, **problem):
            assert_allclose(active_u[0], startx3)
            assert_allclose(v, -startv3)
        print()

        print("NUTSSampler ----")
        print("FORWARD SAMPLING FROM", 0, active_u[0], v, active_values[0])
        samplingpath = SamplingPath(active_u[0], v, active_values[0])
        np.random.seed(i)
        sampler = ClockedNUTSSampler(ContourSamplingPath(samplingpath, region))
        sampler.get_independent_sample(**problem)
Beispiel #8
0
def test_directjumper():
    Lmin = -1.0
    us = 0.5 + np.zeros((100, 2))
    #Ls = np.zeros(100)
    region = make_region(2)

    def transform(x):
        return x

    def loglike(x):
        return 0.0

    def gradient(x, plot=False):
        j = np.argmax(np.abs(x - 0.5))
        v = np.zeros(len(x))
        v[j] = -1 if x[j] > 0.5 else 1
        return v

    def nocall(x):
        assert False

    ui = us[np.random.randint(len(us)), :]
    v = np.array([0.01, 0.01])
    path = ContourSamplingPath(SamplingPath(ui, v, 0.0), region)
    path.gradient = nocall
    sampler = ClockedBisectSampler(path)
    stepper = DirectJumper(sampler, 4)

    assert (stepper.naccepts, stepper.nrejects) == (0, 0), (stepper.naccepts,
                                                            stepper.nrejects)
    assert stepper.isteps == 0, stepper.isteps
    x, L = makejump(stepper, sampler, transform, loglike, Lmin)
    assert_allclose(x, [0.54, 0.54])
    assert (stepper.naccepts, stepper.nrejects) == (4, 0), (stepper.naccepts,
                                                            stepper.nrejects)
    assert stepper.isteps == 4, stepper.isteps

    print()
    print("make reflect")
    print()

    def loglike(x):
        return 0.0 if x[0] < 0.505 else -100

    path = ContourSamplingPath(SamplingPath(ui, v, 0.0), region)
    path.gradient = gradient
    sampler = ClockedBisectSampler(path)
    stepper = DirectJumper(sampler, 4)
    assert (stepper.naccepts, stepper.nrejects) == (0, 0), (stepper.naccepts,
                                                            stepper.nrejects)
    assert stepper.isteps == 0, stepper.isteps
    x, L = makejump(stepper, sampler, transform, loglike, Lmin)
    assert_allclose(x, [0.47, 0.55])
    assert (stepper.naccepts, stepper.nrejects) == (4, 0), (stepper.naccepts,
                                                            stepper.nrejects)
    assert stepper.isteps == 4, stepper.isteps

    print()
    print("make stuck")
    print()

    # make stuck
    def loglike(x):
        return -100

    path = ContourSamplingPath(SamplingPath(ui, v, 0.0), region)
    path.gradient = gradient
    sampler = ClockedBisectSampler(path)
    stepper = DirectJumper(sampler, 4)
    assert (stepper.naccepts, stepper.nrejects) == (0, 0), (stepper.naccepts,
                                                            stepper.nrejects)
    assert stepper.isteps == 0, stepper.isteps
    x, L = makejump(stepper, sampler, transform, loglike, Lmin)
    assert_allclose(x, [0.50, 0.50])
    assert (stepper.naccepts, stepper.nrejects) == (0, 4), (stepper.naccepts,
                                                            stepper.nrejects)
    assert stepper.isteps == 4, stepper.isteps
Beispiel #9
0
    def move(self, ui, region, ndraw=1, plot=False):
        """Advance by slice sampling on the path."""
        if self.interval is None:
            v = self.generate_direction(ui, region, scale=self.scale)
            self.path = ContourSamplingPath(
                SamplingPath(ui, v, 0.0), region)

            if not (ui > 0).all() or not (ui < 1).all() or not region.inside(ui.reshape((1, -1))):
                assert False, ui

            # unit hypercube diagonal gives a reasonable maximum path length
            maxlength = len(ui)**0.5

            # expand direction until it is surely outside
            left = -1
            right = +1
            while abs(left * self.scale) < maxlength:
                xj, vj = self.path.extrapolate(left)
                if not (xj > 0).all() or not (xj < 1).all() or not region.inside(xj.reshape((1, -1))):
                    break
                # self.path.add(left, xj, vj, 0.0)
                left *= 2

            while abs(right * self.scale) < maxlength:
                xj, _ = self.path.extrapolate(right)
                if not (xj > 0).all() or not (xj < 1).all() or not region.inside(xj.reshape((1, -1))):
                    break
                # self.path.add(right, xj, vj, 0.0)
                right *= 2

            scale = max(-left, right)
            # print("scale %f gave %d %d " % (self.scale, left, right))
            if scale < 5:
                self.scale /= 1.1
            # if scale > 100:
            #     self.scale *= 1.1

            assert self.scale > 1e-10, self.scale
            self.interval = (left, right, None)
        else:
            left, right, mid = self.interval
            # we rejected mid, and shrink corresponding side
            if mid < 0:
                left = mid
            elif mid > 0:
                right = mid

        # shrink direction if outside
        while True:
            mid = np.random.randint(left, right + 1)
            # print("interpolating %d - %d - %d" % (left, mid, right),
            #     self.path.points)
            if mid == 0:
                _, xj, _, _ = self.path.points[0]
            else:
                xj, _ = self.path.extrapolate(mid)

            if region.inside(xj.reshape((1, -1))):
                self.interval = (left, right, mid)
                return xj.reshape((1, -1))
            else:
                if mid < 0:
                    left = mid
                else:
                    right = mid
                self.interval = (left, right, mid)