Example #1
0
def test_cosine_analytical(d, allclose):
    pytest.importorskip("scipy")  # beta, betainc, betaincinv

    dt = 0.0001
    x = np.arange(-1 + dt, 1, dt)

    def p(x, d):
        # unnormalized CosineSimilarity distribution, derived by Eric H.
        return (1 - x * x) ** ((d - 3) / 2.0)

    dist = CosineSimilarity(d)

    pdf_exp = dist.pdf(x)
    pdf_act = p(x, d)

    cdf_exp = dist.cdf(x)
    cdf_act = np.cumsum(pdf_act) / np.sum(pdf_act)

    # Check that we get the expected pdf after normalization
    assert allclose(pdf_exp / np.sum(pdf_exp), pdf_act / np.sum(pdf_act), atol=0.01)

    # Check that this accumulates to the expected cdf
    assert allclose(cdf_exp, cdf_act, atol=0.01)

    # Check that the inverse cdf gives back x
    assert allclose(dist.ppf(cdf_exp), x, atol=0.01)
Example #2
0
def test_distributions():
    check_init_args(PDF, ["x", "p"])
    check_repr(PDF([1, 2, 3], [0.1, 0.8, 0.1]))
    assert (repr(PDF(
        [1, 2], [0.4, 0.6])) == "PDF(x=array([1., 2.]), p=array([0.4, 0.6]))")

    check_init_args(Uniform, ["low", "high", "integer"])
    check_repr(Uniform(1, 3))
    check_repr(Uniform(1, 4, integer=True))
    assert repr(Uniform(0, 1)) == "Uniform(low=0, high=1)"
    assert repr(Uniform(
        0, 5, integer=True)) == "Uniform(low=0, high=5, integer=True)"

    check_init_args(Gaussian, ["mean", "std"])
    check_repr(Gaussian(0, 2))
    assert repr(Gaussian(1, 0.1)) == "Gaussian(mean=1, std=0.1)"

    check_init_args(Exponential, ["scale", "shift", "high"])
    check_repr(Exponential(2.0))
    check_repr(Exponential(2.0, shift=0.1))
    check_repr(Exponential(2.0, shift=0.1, high=10.0))
    assert repr(Exponential(2.0)) == "Exponential(scale=2.0)"

    check_init_args(UniformHypersphere, ["surface", "min_magnitude"])
    check_repr(UniformHypersphere())
    check_repr(UniformHypersphere(surface=True))
    check_repr(UniformHypersphere(min_magnitude=0.3))
    assert repr(UniformHypersphere()) == "UniformHypersphere()"
    assert repr(
        UniformHypersphere(surface=True)) == "UniformHypersphere(surface=True)"

    check_init_args(Choice, ["options", "weights"])
    check_repr(Choice([3, 2, 1]))
    check_repr(Choice([3, 2, 1], weights=[0.1, 0.2, 0.7]))
    assert repr(Choice([1, 2, 3])) == "Choice(options=array([1., 2., 3.]))"
    assert (repr(
        Choice([1, 2, 3], weights=[0.1, 0.5, 0.4])
    ) == "Choice(options=array([1., 2., 3.]), weights=array([0.1, 0.5, 0.4]))")

    check_init_args(Samples, ["samples"])
    check_repr(Samples([3, 2, 1]))
    assert repr(Samples([3, 2, 1])) == "Samples(samples=array([3., 2., 1.]))"

    check_init_args(SqrtBeta, ["n", "m"])
    check_repr(SqrtBeta(3))
    check_repr(SqrtBeta(3, m=2))
    assert repr(SqrtBeta(3)) == "SqrtBeta(n=3)"
    assert repr(SqrtBeta(3, 2)) == "SqrtBeta(n=3, m=2)"

    check_init_args(SubvectorLength, ["dimensions", "subdimensions"])
    check_repr(SubvectorLength(6))
    check_repr(SubvectorLength(6, 2))
    assert repr(SubvectorLength(3)) == "SubvectorLength(dimensions=3)"

    check_init_args(CosineSimilarity, ["dimensions"])
    check_repr(CosineSimilarity(6))
    assert repr(CosineSimilarity(6)) == "CosineSimilarity(dimensions=6)"
Example #3
0
def test_cosine_sample_shape(seed, allclose):
    """"Tests that CosineSimilarity sample has correct shape."""
    # sampling (n, d) should be the exact same as sampling (n*d,)
    n = 3
    d = 4
    dist = CosineSimilarity(2)
    a = dist.sample(n, d, rng=np.random.RandomState(seed))
    b = dist.sample(n * d, rng=np.random.RandomState(seed))
    assert allclose(a.flatten(), b)
Example #4
0
def test_cosine_intercept(d, p, rng, allclose):
    """Tests CosineSimilarity inverse cdf for finding intercepts."""
    pytest.importorskip("scipy")  # betaincinv

    num_samples = 500

    exp_dist = UniformHypersphere(surface=True)
    act_dist = CosineSimilarity(d)

    dots = exp_dist.sample(num_samples, d, rng=rng)[:, 0]

    # Find the desired intercept so that dots >= c with probability p
    c = act_dist.ppf(1 - p)
    assert allclose(np.sum(dots >= c) / float(num_samples), p, atol=0.05)
Example #5
0
def test_cosine_similarity(d, rng):
    """Tests CosineSimilarity sampling."""
    num_samples = 2500
    num_bins = 8

    # Check that it gives a single dimension from UniformHypersphere
    exp_dist = UniformHypersphere(surface=True)
    act_dist = CosineSimilarity(d)

    exp = exp_dist.sample(num_samples, d, rng=rng)[:, 0]
    act = act_dist.sample(num_samples, rng=rng)

    exp_hist, _ = np.histogram(exp, bins=num_bins)
    act_hist, _ = np.histogram(act, bins=num_bins)

    assert np.all(np.abs(np.asfarray(exp_hist - act_hist) / num_samples) < 0.15)
Example #6
0
def prob_cleanup(similarity, dimensions, vocab_size):
    """Estimate the chance of successful cleanup.

    This returns the chance that, out of *vocab_size* randomly chosen
    vectors, none of them will be closer to a particular
    vector than the value given by *similarity*. To use this, compare
    your noisy vector with the ideal vector, pass that value in as
    the similarity parameter, and set *vocab_size* to be the number of
    competing vectors.

    Requires SciPy.
    """
    p = CosineSimilarity(dimensions).cdf(similarity)
    if similarity < 1. and p == 1.:
        raise ArithmeticError(
            "Insufficient floating point precision to compute value.")
    return p**vocab_size
Example #7
0
def test_argreprs():
    def check_init_args(cls, args):
        assert getfullargspec(cls.__init__).args[1:] == args

    def check_repr(obj):
        assert eval(repr(obj)) == obj

    check_init_args(PDF, ['x', 'p'])
    check_repr(PDF([1, 2, 3], [0.1, 0.8, 0.1]))

    check_init_args(Uniform, ['low', 'high', 'integer'])
    check_repr(Uniform(1, 3))
    check_repr(Uniform(1, 4, integer=True))

    check_init_args(Gaussian, ['mean', 'std'])
    check_repr(Gaussian(0, 2))

    check_init_args(Exponential, ['scale', 'shift', 'high'])
    check_repr(Exponential(2.))
    check_repr(Exponential(2., shift=0.1))
    check_repr(Exponential(2., shift=0.1, high=10.))

    check_init_args(UniformHypersphere, ['surface', 'min_magnitude'])
    check_repr(UniformHypersphere())
    check_repr(UniformHypersphere(surface=True))
    check_repr(UniformHypersphere(min_magnitude=0.3))

    check_init_args(Choice, ['options', 'weights'])
    check_repr(Choice([3, 2, 1]))
    check_repr(Choice([3, 2, 1], weights=[0.1, 0.2, 0.7]))

    check_init_args(Samples, ['samples'])
    check_repr(Samples([3, 2, 1]))

    check_init_args(SqrtBeta, ['n', 'm'])
    check_repr(SqrtBeta(3))
    check_repr(SqrtBeta(3, m=2))

    check_init_args(SubvectorLength, ['dimensions', 'subdimensions'])
    check_repr(SubvectorLength(6))
    check_repr(SubvectorLength(6, 2))

    check_init_args(CosineSimilarity, ['dimensions'])
    check_repr(CosineSimilarity(6))
Example #8
0
def test_argreprs():
    def check_init_args(cls, args):
        assert getfullargspec(cls.__init__).args[1:] == args

    def check_repr(obj):
        assert eval(repr(obj)) == obj

    check_init_args(PDF, ["x", "p"])
    check_repr(PDF([1, 2, 3], [0.1, 0.8, 0.1]))

    check_init_args(Uniform, ["low", "high", "integer"])
    check_repr(Uniform(1, 3))
    check_repr(Uniform(1, 4, integer=True))

    check_init_args(Gaussian, ["mean", "std"])
    check_repr(Gaussian(0, 2))

    check_init_args(Exponential, ["scale", "shift", "high"])
    check_repr(Exponential(2.0))
    check_repr(Exponential(2.0, shift=0.1))
    check_repr(Exponential(2.0, shift=0.1, high=10.0))

    check_init_args(UniformHypersphere, ["surface", "min_magnitude"])
    check_repr(UniformHypersphere())
    check_repr(UniformHypersphere(surface=True))
    check_repr(UniformHypersphere(min_magnitude=0.3))

    check_init_args(Choice, ["options", "weights"])
    check_repr(Choice([3, 2, 1]))
    check_repr(Choice([3, 2, 1], weights=[0.1, 0.2, 0.7]))

    check_init_args(Samples, ["samples"])
    check_repr(Samples([3, 2, 1]))

    check_init_args(SqrtBeta, ["n", "m"])
    check_repr(SqrtBeta(3))
    check_repr(SqrtBeta(3, m=2))

    check_init_args(SubvectorLength, ["dimensions", "subdimensions"])
    check_repr(SubvectorLength(6))
    check_repr(SubvectorLength(6, 2))

    check_init_args(CosineSimilarity, ["dimensions"])
    check_repr(CosineSimilarity(6))
Example #9
0
def VTB(n_neurons,
        dimensions,
        unbind_left=False,
        unbind_right=False,
        **kwargs):
    r"""Compute vector-derived transformation binding (VTB).

    VTB uses elementwise addition for superposition. The binding operation
    :math:`\mathcal{B}(x, y)` is defined as

    .. math::

       \mathcal{B}(x, y) := V_y x = \left[\begin{array}{ccc}
           V_y' &    0 &    0 \\
              0 & V_y' &    0 \\
              0 &    0 & V_y'
           \end{array}\right] x

    with

    .. math::

       V_y' = d^{\frac{1}{4}} \left[\begin{array}{cccc}
           y_1            & y_2            & \dots  & y_{d'}  \\
           y_{d' + 1}     & y_{d' + 2}     & \dots  & y_{2d'} \\
           \vdots         & \vdots         & \ddots & \vdots  \\
           y_{d - d' + 1} & y_{d - d' + 2} & \dots  & y_d
       \end{array}\right]

    and

    .. math:: d'^2 = d.

    The approximate inverse :math:`y^+` for :math:`y` is permuting the elements
    such that :math:`V_{y^+} = V_y`.

    Note that VTB requires the vector dimensionality to be square.

    The VTB binding operation is neither associative nor commutative.

    Publications with further information are forthcoming.

    Parameters
    ----------
    n_neurons : int
        Number of neurons to use in each product computation.
    dimensions : int
        The number of dimensions of the input and output vectors. Needs to be a
        square number.
    unbind_left : bool
        Whether to unbind the left input vector from the right input vector.
    unbind_right : bool
        Whether to unbind the right input vector from the left input vector.
    kwargs : dict
        Arguments to pass through to the `nengo.Network` constructor.

    Returns
    -------
    nengo.Network
        The newly built product network with attributes:

         * **input_left** (`nengo.Node`): The left operand vector to be bound.
         * **input_right** (`nengo.Node`): The right operand vector to be
           bound.
         * **mat** (`nengo.Node`): Representation of the matrix :math:`V_y'`.
         * **vec** (`nengo.Node`): Representation of the vector :math:`y`.
         * **matmuls** (`list`): Matrix multiplication networks.
         * **output** (`nengo.Node`): The resulting bound vector.
    """
    sub_d = calc_sub_d(dimensions)

    shape_left = (sub_d, sub_d)
    shape_right = (sub_d, 1)

    with nengo.Network(**kwargs) as net:
        net.input_left = nengo.Node(size_in=dimensions)
        net.input_right = nengo.Node(size_in=dimensions)
        net.output = nengo.Node(size_in=dimensions)

        net.mat = nengo.Node(size_in=dimensions)
        net.vec = nengo.Node(size_in=dimensions)

        if unbind_left and unbind_right:
            raise ValueError("Cannot unbind both sides at the same time.")
        elif unbind_left:
            nengo.Connection(net.input_left,
                             net.mat,
                             transform=inversion_matrix(dimensions),
                             synapse=None)
            nengo.Connection(net.input_right,
                             net.vec,
                             transform=swapping_matrix(dimensions),
                             synapse=None)
        else:
            nengo.Connection(net.input_left, net.vec, synapse=None)
            if unbind_right:
                tr = inversion_matrix(dimensions)
            else:
                tr = 1.
            nengo.Connection(net.input_right,
                             net.mat,
                             transform=tr,
                             synapse=None)

        with nengo.Config(nengo.Ensemble) as cfg:
            cfg[nengo.Ensemble].intercepts = CosineSimilarity(dimensions + 2)
            cfg[nengo.Ensemble].eval_points = CosineSimilarity(dimensions + 2)
            net.matmuls = [
                MatrixMult(n_neurons, shape_left, shape_right)
                for i in range(sub_d)
            ]

        for i in range(sub_d):
            mm = net.matmuls[i]
            sl = slice(i * sub_d, (i + 1) * sub_d)
            nengo.Connection(net.mat, mm.input_left, synapse=None)
            nengo.Connection(net.vec[sl], mm.input_right, synapse=None)
            nengo.Connection(mm.output,
                             net.output[sl],
                             transform=np.sqrt(sub_d),
                             synapse=None)

    return net