コード例 #1
0
ファイル: test_fixed_rank.py プロジェクト: pymanopt/pymanopt
    def setUp(self):
        self.m = m = 10
        self.n = n = 5
        self.k = k = 3
        self.manifold = FixedRankEmbedded(m, n, k)

        u, s, vt = self.manifold.random_point()
        matrix = (u * s) @ vt

        @pymanopt.function.autograd(self.manifold)
        def cost(u, s, vt):
            return np.linalg.norm((u * s) @ vt - matrix) ** 2

        self.cost = cost
コード例 #2
0
def run(backend=SUPPORTED_BACKENDS[0], quiet=True):
    m, n, rank = 5, 4, 2
    matrix = rnd.randn(m, n)

    cost, egrad = create_cost_egrad(backend, matrix, rank)
    manifold = FixedRankEmbedded(m, n, rank)
    problem = pymanopt.Problem(manifold, cost=cost, egrad=egrad)
    if quiet:
        problem.verbosity = 0

    solver = ConjugateGradient()
    left_singular_vectors, singular_values, right_singular_vectors = \
        solver.solve(problem)
    low_rank_approximation = (left_singular_vectors @ np.diag(singular_values)
                              @ right_singular_vectors)

    if not quiet:
        u, s, vt = la.svd(matrix, full_matrices=False)
        indices = np.argsort(s)[-rank:]
        low_rank_solution = (
            u[:, indices] @ np.diag(s[indices]) @ vt[indices, :])
        print("Analytic low-rank solution:")
        print()
        print(low_rank_solution)
        print()
        print("Rank-{} approximation:".format(rank))
        print()
        print(low_rank_approximation)
        print()
        print("Frobenius norm error:",
              la.norm(low_rank_approximation - low_rank_solution))
        print()
コード例 #3
0
def fixedrank(A, YT, r):
    """ Solves the AX=YT problem on the manifold of r-rank matrices with  
    """

    # Instantiate a manifold
    manifold = FixedRankEmbedded(N, r, r)

    # Define the cost function (here using autograd.numpy)
    def cost(X):
        U = X[0]
        cst = 0
        for n in range(N):
            cst = cst + huber(U[n, :])
        Mat = np.matmul(np.matmul(X[0], np.diag(X[1])), X[2])
        fidelity = LA.norm(np.subtract(np.matmul(A, Mat), YT))
        return cst + lambd * fidelity**2

    problem = Problem(manifold=manifold, cost=cost)
    solver = ConjugateGradient(maxiter=maxiter)

    # Let Pymanopt do the rest
    Xopt = solver.solve(problem)

    #Solve
    Sol = np.dot(np.dot(Xopt[0], np.diag(Xopt[1])), Xopt[2])

    return Sol
コード例 #4
0
    def setUp(self):
        self.m = m = 20
        self.n = n = 10
        self.rank = rank = 3

        A = np.random.normal(size=(m, n))
        self.manifold = Product([FixedRankEmbedded(m, n, rank), Euclidean(n)])

        @pymanopt.function.autograd(self.manifold)
        def cost(u, s, vt, x):
            return np.linalg.norm(((u * s) @ vt - A) @ x) ** 2

        self.cost = cost
        self.gradient = self.cost.get_gradient_operator()
        self.hessian = self.cost.get_hessian_operator()

        self.problem = pymanopt.Problem(self.manifold, self.cost)
コード例 #5
0
    def setUp(self):
        self.m = m = 20
        self.n = n = 10
        self.rank = rank = 3

        A = np.random.randn(m, n)

        @pymanopt.function.Autograd
        def cost(u, s, vt, x):
            return np.linalg.norm(((u * s) @ vt - A) @ x)**2

        self.cost = cost
        self.gradient = self.cost.compute_gradient()
        self.hvp = self.cost.compute_hessian_vector_product()

        self.manifold = Product([FixedRankEmbedded(m, n, rank), Euclidean(n)])
        self.problem = pymanopt.Problem(self.manifold, self.cost)
コード例 #6
0
def run(backend=SUPPORTED_BACKENDS[0], quiet=True):
    m, n, rank = 5, 4, 2
    matrix = np.random.normal(size=(m, n))

    manifold = FixedRankEmbedded(m, n, rank)
    cost, euclidean_gradient = create_cost_and_derivates(
        manifold, matrix, backend
    )
    problem = pymanopt.Problem(
        manifold, cost, euclidean_gradient=euclidean_gradient
    )

    optimizer = ConjugateGradient(
        verbosity=2 * int(not quiet), beta_rule="PolakRibiere"
    )
    (
        left_singular_vectors,
        singular_values,
        right_singular_vectors,
    ) = optimizer.run(problem).point
    low_rank_approximation = (
        left_singular_vectors
        @ np.diag(singular_values)
        @ right_singular_vectors
    )

    if not quiet:
        u, s, vt = np.linalg.svd(matrix, full_matrices=False)
        indices = np.argsort(s)[-rank:]
        low_rank_solution = (
            u[:, indices] @ np.diag(s[indices]) @ vt[indices, :]
        )
        print("Analytic low-rank solution:")
        print()
        print(low_rank_solution)
        print()
        print(f"Rank-{rank} approximation:")
        print()
        print(low_rank_approximation)
        print()
        print(
            "Frobenius norm error:",
            np.linalg.norm(low_rank_approximation - low_rank_solution),
        )
        print()
コード例 #7
0
import autograd.numpy as np
from pymanopt import Problem
from pymanopt.solvers import ConjugateGradient

# Let A be a (5 x 4) matrix to be approximated
A = np.random.randn(5, 4)
k = 2

# (a) Instantiation of a manifold
# points on the manifold are parameterized via their singular value
# decomposition (u, s, vt) where
# u is a 5 x 2 matrix with orthonormal columns,
# s is a vector of length 2,
# vt is a 2 x 4 matrix with orthonormal rows,
# so that u*diag(s)*vt is a 5 x 4 matrix of rank 2.
manifold = FixedRankEmbedded(A.shape[0], A.shape[1], k)


# (b) Definition of a cost function (here using autograd.numpy)
#       Note that the cost must be defined in terms of u, s and vt, where
#       X = u * diag(s) * vt.
def cost(usv):
    delta = .5
    u = usv[0]
    s = usv[1]
    vt = usv[2]
    X = np.dot(np.dot(u, np.diag(s)), vt)
    return np.sum(np.sqrt((X - A)**2 + delta**2) - delta)


# define the Pymanopt problem
コード例 #8
0
class TestFixedRankEmbeddedManifold(unittest.TestCase):
    def setUp(self):
        self.m = m = 10
        self.n = n = 5
        self.k = k = 3
        self.man = FixedRankEmbedded(m, n, k)

    def test_dim(self):
        assert self.man.dim == (self.m + self.n - self.k) * self.k

    def test_typicaldist(self):
        assert self.man.dim == self.man.typicaldist

    def test_dist(self):
        e = self.man
        a = e.rand()
        x = e.randvec(a)
        y = e.randvec(a)
        with self.assertRaises(NotImplementedError):
            e.dist(x, y)

    def test_inner(self):
        e = self.man
        x = e.rand()
        a = e.randvec(x)
        b = e.randvec(x)
        # First embed in the ambient space
        A = x[0].dot(a[1].dot(x[2])) + a[0].dot(x[2]) + x[0].dot(a[2].T)
        B = x[0].dot(b[1].dot(x[2])) + b[0].dot(x[2]) + x[0].dot(b[2].T)
        trueinner = np.sum(A * B)
        np_testing.assert_almost_equal(trueinner, e.inner(x, a, b))

    def test_proj_range(self):
        m = self.man
        x = m.rand()
        v = np.random.randn(self.m, self.n)

        g = m.proj(x, v)
        # Check that g is a true tangent vector
        np_testing.assert_allclose(np.dot(g[0].T, x[0]),
                                   np.zeros((self.k, self.k)),
                                   atol=1e-6)
        np_testing.assert_allclose(np.dot(g[2].T, x[2].T),
                                   np.zeros((self.k, self.k)),
                                   atol=1e-6)

    def test_proj(self):
        # Verify that proj gives the closest point within the tangent space
        # by displacing the result slightly and checking that this increases
        # the distance.
        m = self.man
        x = self.man.rand()
        v = np.random.randn(self.m, self.n)

        g = m.proj(x, v)
        # Displace g a little
        g_disp = g + 0.01 * m.randvec(x)

        # Return to the ambient representation
        g = m.tangent2ambient(x, g)
        g_disp = m.tangent2ambient(x, g_disp)
        g = g[0].dot(g[1]).dot(g[2].T)
        g_disp = g_disp[0].dot(g_disp[1]).dot(g_disp[2].T)

        assert np.linalg.norm(g - v) < np.linalg.norm(g_disp - v)

    def test_proj_tangents(self):
        # Verify that proj leaves tangent vectors unchanged
        e = self.man
        x = e.rand()
        u = e.randvec(x)
        A = e.proj(x, e.tangent2ambient(x, u))
        B = u
        # diff = [A[k]-B[k] for k in xrange(len(A))]
        np_testing.assert_allclose(A[0], B[0])
        np_testing.assert_allclose(A[1], B[1])
        np_testing.assert_allclose(A[2], B[2])

    def test_norm(self):
        e = self.man
        x = e.rand()
        u = e.randvec(x)
        np_testing.assert_almost_equal(np.sqrt(e.inner(x, u, u)), e.norm(x, u))

    def test_rand(self):
        e = self.man
        x = e.rand()
        y = e.rand()
        assert np.shape(x[0]) == (self.m, self.k)
        assert np.shape(x[1]) == (self.k, )
        assert np.shape(x[2]) == (self.k, self.n)
        np_testing.assert_allclose(x[0].T.dot(x[0]), np.eye(self.k), atol=1e-6)
        np_testing.assert_allclose(x[2].dot(x[2].T), np.eye(self.k), atol=1e-6)

        assert la.norm(x[0] - y[0]) > 1e-6
        assert la.norm(x[1] - y[1]) > 1e-6
        assert la.norm(x[2] - y[2]) > 1e-6

    def test_transp(self):
        s = self.man
        x = s.rand()
        y = s.rand()
        u = s.randvec(x)
        A = s.transp(x, y, u)
        B = s.proj(y, s.tangent2ambient(x, u))
        diff = [A[k] - B[k] for k in range(len(A))]
        np_testing.assert_almost_equal(s.norm(y, diff), 0)

    def test_apply_ambient(self):
        m = self.man
        z = np.random.randn(self.m, self.n)

        # Set u, s, v so that z = u.dot(s).dot(v.T)
        u, s, v = np.linalg.svd(z, full_matrices=False)
        s = np.diag(s)
        v = v.T

        w = np.random.randn(self.n, self.n)

        np_testing.assert_allclose(z.dot(w), m._apply_ambient(z, w))
        np_testing.assert_allclose(z.dot(w), m._apply_ambient((u, s, v), w))

    def test_apply_ambient_transpose(self):
        m = self.man
        z = np.random.randn(self.n, self.m)

        # Set u, s, v so that z = u.dot(s).dot(v.T)
        u, s, v = np.linalg.svd(z, full_matrices=False)
        s = np.diag(s)
        v = v.T

        w = np.random.randn(self.n, self.n)

        np_testing.assert_allclose(z.T.dot(w),
                                   m._apply_ambient_transpose(z, w))
        np_testing.assert_allclose(z.T.dot(w),
                                   m._apply_ambient_transpose((u, s, v), w))

    def test_tangent2ambient(self):
        m = self.man
        x = m.rand()
        z = m.randvec(x)

        z_ambient = (x[0].dot(z[1]).dot(x[2]) + z[0].dot(x[2]) +
                     x[0].dot(z[2].T))

        u, s, v = m.tangent2ambient(x, z)

        np_testing.assert_allclose(z_ambient, u.dot(s).dot(v.T))

    def test_ehess2rhess(self):
        pass

    def test_retr(self):
        # Test that the result is on the manifold and that for small
        # tangent vectors it has little effect.
        x = self.man.rand()
        u = self.man.randvec(x)

        y = self.man.retr(x, u)

        np_testing.assert_allclose(y[0].T.dot(y[0]), np.eye(self.k), atol=1e-6)
        np_testing.assert_allclose(y[2].dot(y[2].T), np.eye(self.k), atol=1e-6)

        u = u * 1e-6
        y = self.man.retr(x, u)
        y = y[0].dot(np.diag(y[1])).dot(y[2])

        u = self.man.tangent2ambient(x, u)
        u = u[0].dot(u[1]).dot(u[2].T)
        x = x[0].dot(np.diag(x[1])).dot(x[2])

        np_testing.assert_allclose(y, x + u, atol=1e-5)

    def test_egrad2rgrad(self):
        # Verify that egrad2rgrad and proj are equivalent.
        m = self.man
        x = m.rand()
        u, s, vt = x

        i = np.eye(self.k)

        f = 1 / (s[..., np.newaxis, :]**2 - s[..., :, np.newaxis]**2 + i)

        du = np.random.randn(self.m, self.k)
        ds = np.random.randn(self.k)
        dvt = np.random.randn(self.k, self.n)

        Up = (np.dot(np.dot(np.eye(self.m) - np.dot(u, u.T), du),
                     np.linalg.inv(np.diag(s))))
        M = (np.dot(f * (np.dot(u.T, du) - np.dot(du.T, u)), np.diag(s)) +
             np.dot(np.diag(s), f *
                    (np.dot(vt, dvt.T) - np.dot(dvt, vt.T))) + np.diag(ds))
        Vp = (np.dot(np.dot(np.eye(self.n) - np.dot(vt.T, vt), dvt.T),
                     np.linalg.inv(np.diag(s))))

        up, m, vp = m.egrad2rgrad(x, (du, ds, dvt))

        U, S, V = self.man.tangent2ambient(x, [Up, M, Vp])
        u, s, v = self.man.tangent2ambient(x, [up, m, vp])

        T = U.dot(S).dot(V.T)
        t = u.dot(s).dot(v.T)

        np_testing.assert_allclose(T, t)

    def test_randvec(self):
        e = self.man
        x = e.rand()
        u = e.randvec(x)

        # Check that u is a tangent vector
        assert np.shape(u[0]) == (self.m, self.k)
        assert np.shape(u[1]) == (self.k, self.k)
        assert np.shape(u[2]) == (self.n, self.k)
        np_testing.assert_allclose(np.dot(u[0].T, x[0]),
                                   np.zeros((self.k, self.k)),
                                   atol=1e-6)
        np_testing.assert_allclose(np.dot(u[2].T, x[2].T),
                                   np.zeros((self.k, self.k)),
                                   atol=1e-6)

        v = e.randvec(x)

        np_testing.assert_almost_equal(e.norm(x, u), 1)
        assert e.norm(x, u - v) > 1e-6


#if __name__ == '__main__':
#    test = TestFixedRankEmbeddedManifold()
#    test.setup()
#    test.test_egrad2rgrad()
コード例 #9
0
 def setUp(self):
     self.m = m = 10
     self.n = n = 5
     self.k = k = 3
     self.man = FixedRankEmbedded(m, n, k)
コード例 #10
0
m = 4
n = 2
k = 2

X = np.random.rand(m, n)
U, S, Vt = np.linalg.svd(X, full_matrices=False)

U = U[:, :k]
S = S[:k]
Vt = Vt[:k, :]

grad_f = grad(f)
grad_g = grad(g)

man = FixedRankEmbedded(m, n, k)

dU, dS, dVt = grad_g((U, S, Vt))

Up, M, Vp = man.egrad2rgrad((U, S, Vt), (dU, dS, dVt))
U_, S_, V_ = man.tangent2ambient((U, S, Vt), (Up, M, Vp))

tangent_grad = U_.dot(S_).dot(V_.T)

print
print
print 'X:'
print X
print
print 'U,S,Vt:'
print U, S, Vt
コード例 #11
0
        #e_correct_prediction = tf.equal(tf.argmax(e_y, 1), tf.argmax(y_, 1))
        #e_accuracy = tf.reduce_mean(tf.cast(e_correct_prediction, "float"))
        #e_accuracy_summary =tf.summary.scalar("e_accuracy", e_accuracy)

    summaries = tf.summary.merge_all()



    manifold_b = Euclidean(1,10)
    if use_parameterization:
        manifold_A = Euclidean(784, k)
        manifold_B = Euclidean(k, 10)
        manifold_W = Product([manifold_A,manifold_B])
        arg = [A, B, b]
    else:
        manifold_W = FixedRankEmbedded(784, 10, k)
        #manifold_W = Product([Stiefel(784,k), Euclidean(k), Stiefel(k,10)])
        arg = [A, M, B, b]

    manifold = Product([manifold_W, manifold_b])

    e_manifold_W = Euclidean(784, 10)
    e_arg = [eW, b]

    e_manifold = Product([e_manifold_W, manifold_b])

    problem = Problem(manifold=manifold, cost=loss, accuracy=accuracy, summary=summaries, arg=arg, data=[x,y_], verbosity=1)
    e_problem = Problem(manifold=e_manifold, cost=e_loss, accuracy=accuracy, summary=summaries, arg=e_arg, data=[x, y_],
                      verbosity=1)

    solver = SGD(maxiter=10000000,logverbosity=10)
コード例 #12
0
    if not os.path.isdir('result'):
        os.makedirs('result')
    path = os.path.join('result', experiment_name + '.csv')

    m, n, rank = 10, 8, 4
    p = 1 / 2

    for i in range(n_exp):
        matrix = rnd.randn(m, n)
        P_omega = np.zeros_like(matrix)
        for j in range(m):
            for k in range(n):
                P_omega[j][k] = random.choice([0, 1])

        cost = create_cost(matrix, P_omega)
        manifold = FixedRankEmbedded(m, n, rank)
        problem = pymanopt.Problem(manifold, cost=cost, egrad=None)

        res_list = []

        for beta_type in BetaTypes:
            solver = ConjugateGradient(beta_type=beta_type, maxiter=10000)
            res = solver.solve(problem)
            res_list.append(res[1])
            res_list.append(res[2])

        with open(path, 'a') as f:
            writer = csv.writer(f)
            writer.writerow(res_list)
コード例 #13
0
ファイル: test_fixed_rank.py プロジェクト: pymanopt/pymanopt
class TestFixedRankEmbeddedManifold(ManifoldTestCase):
    def setUp(self):
        self.m = m = 10
        self.n = n = 5
        self.k = k = 3
        self.manifold = FixedRankEmbedded(m, n, k)

        u, s, vt = self.manifold.random_point()
        matrix = (u * s) @ vt

        @pymanopt.function.autograd(self.manifold)
        def cost(u, s, vt):
            return np.linalg.norm((u * s) @ vt - matrix) ** 2

        self.cost = cost

    def test_dim(self):
        assert self.manifold.dim == (self.m + self.n - self.k) * self.k

    def test_typical_dist(self):
        assert self.manifold.dim == self.manifold.typical_dist

    def test_dist(self):
        e = self.manifold
        a = e.random_point()
        x = e.random_tangent_vector(a)
        y = e.random_tangent_vector(a)
        with self.assertRaises(NotImplementedError):
            e.dist(x, y)

    def test_inner_product(self):
        e = self.manifold
        x = e.random_point()
        a = e.random_tangent_vector(x)
        b = e.random_tangent_vector(x)
        # First embed in the ambient space
        A = x[0] @ a[1] @ x[2] + a[0] @ x[2] + x[0] @ a[2].T
        B = x[0] @ b[1] @ x[2] + b[0] @ x[2] + x[0] @ b[2].T
        trueinner = np.sum(A * B)
        np_testing.assert_almost_equal(trueinner, e.inner_product(x, a, b))

    def test_proj_range(self):
        m = self.manifold
        x = m.random_point()
        v = np.random.normal(size=(self.m, self.n))

        g = m.projection(x, v)
        # Check that g is a true tangent vector
        np_testing.assert_allclose(
            g[0].T @ x[0], np.zeros((self.k, self.k)), atol=1e-6
        )
        np_testing.assert_allclose(
            g[2].T @ x[2].T, np.zeros((self.k, self.k)), atol=1e-6
        )

    def test_projection(self):
        # Verify that proj gives the closest point within the tangent space
        # by displacing the result slightly and checking that this increases
        # the distance.
        m = self.manifold
        x = self.manifold.random_point()
        v = np.random.normal(size=(self.m, self.n))

        g = m.projection(x, v)
        # Displace g a little
        g_disp = g + 0.01 * m.random_tangent_vector(x)

        # Return to the ambient representation
        g = m.embedding(x, g)
        g_disp = m.embedding(x, g_disp)
        g = g[0] @ g[1] @ g[2].T
        g_disp = g_disp[0] @ g_disp[1] @ g_disp[2].T

        assert np.linalg.norm(g - v) < np.linalg.norm(g_disp - v)

    def test_proj_tangents(self):
        # Verify that proj leaves tangent vectors unchanged
        e = self.manifold
        x = e.random_point()
        u = e.random_tangent_vector(x)
        A = e.projection(x, e.embedding(x, u))
        B = u
        # diff = [A[k]-B[k] for k in range(len(A))]
        np_testing.assert_allclose(A[0], B[0])
        np_testing.assert_allclose(A[1], B[1])
        np_testing.assert_allclose(A[2], B[2])

    def test_norm(self):
        e = self.manifold
        x = e.random_point()
        u = e.random_tangent_vector(x)
        np_testing.assert_almost_equal(
            np.sqrt(e.inner_product(x, u, u)), e.norm(x, u)
        )

    def test_random_point(self):
        e = self.manifold
        x = e.random_point()
        y = e.random_point()
        assert np.shape(x[0]) == (self.m, self.k)
        assert np.shape(x[1]) == (self.k,)
        assert np.shape(x[2]) == (self.k, self.n)
        np_testing.assert_allclose(x[0].T @ x[0], np.eye(self.k), atol=1e-6)
        np_testing.assert_allclose(x[2] @ x[2].T, np.eye(self.k), atol=1e-6)

        assert np.linalg.norm(x[0] - y[0]) > 1e-6
        assert np.linalg.norm(x[1] - y[1]) > 1e-6
        assert np.linalg.norm(x[2] - y[2]) > 1e-6

    def test_transport(self):
        s = self.manifold
        x = s.random_point()
        y = s.random_point()
        u = s.random_tangent_vector(x)
        A = s.transport(x, y, u)
        B = s.projection(y, s.embedding(x, u))
        diff = [A[k] - B[k] for k in range(len(A))]
        np_testing.assert_almost_equal(s.norm(y, diff), 0)

    def test_apply_ambient(self):
        m = self.manifold
        z = np.random.normal(size=(self.m, self.n))

        # Set u, s, v so that z = u @ s @ v.T
        u, s, v = np.linalg.svd(z, full_matrices=False)
        s = np.diag(s)
        v = v.T

        w = np.random.normal(size=(self.n, self.n))

        np_testing.assert_allclose(z @ w, m._apply_ambient(z, w))
        np_testing.assert_allclose(z @ w, m._apply_ambient((u, s, v), w))

    def test_apply_ambient_transpose(self):
        m = self.manifold
        z = np.random.normal(size=(self.n, self.m))

        # Set u, s, v so that z = u @ s @ v.T
        u, s, v = np.linalg.svd(z, full_matrices=False)
        s = np.diag(s)
        v = v.T

        w = np.random.normal(size=(self.n, self.n))

        np_testing.assert_allclose(z.T @ w, m._apply_ambient_transpose(z, w))
        np_testing.assert_allclose(
            z.T @ w, m._apply_ambient_transpose((u, s, v), w)
        )

    def test_embedding(self):
        m = self.manifold
        x = m.random_point()
        z = m.random_tangent_vector(x)

        z_ambient = x[0] @ z[1] @ x[2] + z[0] @ x[2] + x[0] @ z[2].T

        u, s, v = m.embedding(x, z)

        np_testing.assert_allclose(z_ambient, u @ s @ v.T)

    def test_euclidean_to_riemannian_hessian(self):
        pass

    def test_retraction(self):
        # Test that the result is on the manifold and that for small
        # tangent vectors it has little effect.
        x = self.manifold.random_point()
        u = self.manifold.random_tangent_vector(x)

        y = self.manifold.retraction(x, u)

        np_testing.assert_allclose(y[0].T @ y[0], np.eye(self.k), atol=1e-6)
        np_testing.assert_allclose(y[2] @ y[2].T, np.eye(self.k), atol=1e-6)

        u = u * 1e-6
        y = self.manifold.retraction(x, u)
        y = y[0] @ np.diag(y[1]) @ y[2]

        u = self.manifold.embedding(x, u)
        u = u[0] @ u[1] @ u[2].T
        x = x[0] @ np.diag(x[1]) @ x[2]

        np_testing.assert_allclose(y, x + u, atol=1e-5)

    def test_euclidean_to_riemannian_gradient(self):
        # Verify that euclidean_to_riemannian_gradient and proj are equivalent.
        m = self.manifold
        x = m.random_point()
        u, s, vt = x

        i = np.eye(self.k)

        f = 1 / (s[..., np.newaxis, :] ** 2 - s[..., :, np.newaxis] ** 2 + i)

        du = np.random.normal(size=(self.m, self.k))
        ds = np.random.normal(size=self.k)
        dvt = np.random.normal(size=(self.k, self.n))

        Up = (np.eye(self.m) - u @ u.T) @ du @ np.linalg.inv(np.diag(s))
        M = (
            f * (u.T @ du - du.T @ u) @ np.diag(s)
            + np.diag(s) @ f * (vt @ dvt.T - dvt @ vt.T)
            + np.diag(ds)
        )
        Vp = (np.eye(self.n) - vt.T @ vt) @ dvt.T @ np.linalg.inv(np.diag(s))

        up, m, vp = m.euclidean_to_riemannian_gradient(x, (du, ds, dvt))

        np_testing.assert_allclose(Up, up)
        np_testing.assert_allclose(M, m)
        np_testing.assert_allclose(Vp, vp)

    def test_first_order_function_approximation(self):
        self.run_gradient_approximation_test()

    def test_random_tangent_vector(self):
        e = self.manifold
        x = e.random_point()
        u = e.random_tangent_vector(x)

        # Check that u is a tangent vector
        assert np.shape(u[0]) == (self.m, self.k)
        assert np.shape(u[1]) == (self.k, self.k)
        assert np.shape(u[2]) == (self.n, self.k)
        np_testing.assert_allclose(
            u[0].T @ x[0], np.zeros((self.k, self.k)), atol=1e-6
        )
        np_testing.assert_allclose(
            u[2].T @ x[2].T, np.zeros((self.k, self.k)), atol=1e-6
        )

        v = e.random_tangent_vector(x)

        np_testing.assert_almost_equal(e.norm(x, u), 1)
        assert e.norm(x, u - v) > 1e-6
コード例 #14
0
class TestFixedRankEmbeddedManifold(unittest.TestCase):
    def setUp(self):
        self.m = m = 10
        self.n = n = 5
        self.k = k = 3
        self.man = FixedRankEmbedded(m, n, k)

    def test_dim(self):
        assert self.man.dim == (self.m + self.n - self.k) * self.k

    def test_typicaldist(self):
        assert self.man.dim == self.man.typicaldist

    def test_dist(self):
        e = self.man
        a = e.rand()
        x = e.randvec(a)
        y = e.randvec(a)
        with self.assertRaises(NotImplementedError):
            e.dist(x, y)

    def test_inner(self):
        e = self.man
        x = e.rand()
        a = e.randvec(x)
        b = e.randvec(x)
        # First embed in the ambient space
        A = x[0].dot(a[1].dot(x[2])) + a[0].dot(x[2]) + x[0].dot(a[2].T)
        B = x[0].dot(b[1].dot(x[2])) + b[0].dot(x[2]) + x[0].dot(b[2].T)
        trueinner = np.sum(A*B)
        np_testing.assert_almost_equal(trueinner, e.inner(x, a, b))

    def test_proj_range(self):
        m = self.man
        x = m.rand()
        v = np.random.randn(self.m, self.n)

        g = m.proj(x, v)
        # Check that g is a true tangent vector
        np_testing.assert_allclose(np.dot(g[0].T, x[0]),
                                   np.zeros((self.k, self.k)),
                                   atol=1e-6)
        np_testing.assert_allclose(np.dot(g[2].T, x[2].T),
                                   np.zeros((self.k, self.k)),
                                   atol=1e-6)

    def test_proj(self):
        # Verify that proj gives the closest point within the tangent space
        # by displacing the result slightly and checking that this increases
        # the distance.
        m = self.man
        x = self.man.rand()
        v = np.random.randn(self.m, self.n)

        g = m.proj(x, v)
        # Displace g a little
        g_disp = g + 0.01 * m.randvec(x)

        # Return to the ambient representation
        g = m.tangent2ambient(x, g)
        g_disp = m.tangent2ambient(x, g_disp)
        g = g[0].dot(g[1]).dot(g[2].T)
        g_disp = g_disp[0].dot(g_disp[1]).dot(g_disp[2].T)

        assert np.linalg.norm(g - v) < np.linalg.norm(g_disp - v)

    def test_proj_tangents(self):
        # Verify that proj leaves tangent vectors unchanged
        e = self.man
        x = e.rand()
        u = e.randvec(x)
        A = e.proj(x, e.tangent2ambient(x, u))
        B = u
        # diff = [A[k]-B[k] for k in xrange(len(A))]
        np_testing.assert_allclose(A[0], B[0])
        np_testing.assert_allclose(A[1], B[1])
        np_testing.assert_allclose(A[2], B[2])

    def test_norm(self):
        e = self.man
        x = e.rand()
        u = e.randvec(x)
        np_testing.assert_almost_equal(np.sqrt(e.inner(x, u, u)), e.norm(x, u))

    def test_rand(self):
        e = self.man
        x = e.rand()
        y = e.rand()
        assert np.shape(x[0]) == (self.m, self.k)
        assert np.shape(x[1]) == (self.k,)
        assert np.shape(x[2]) == (self.k, self.n)
        np_testing.assert_allclose(x[0].T.dot(x[0]), np.eye(self.k), atol=1e-6)
        np_testing.assert_allclose(x[2].dot(x[2].T), np.eye(self.k), atol=1e-6)

        assert la.norm(x[0] - y[0]) > 1e-6
        assert la.norm(x[1] - y[1]) > 1e-6
        assert la.norm(x[2] - y[2]) > 1e-6

    def test_transp(self):
        s = self.man
        x = s.rand()
        y = s.rand()
        u = s.randvec(x)
        A = s.transp(x, y, u)
        B = s.proj(y, s.tangent2ambient(x, u))
        diff = [A[k]-B[k] for k in range(len(A))]
        np_testing.assert_almost_equal(s.norm(y, diff), 0)

    def test_apply_ambient(self):
        m = self.man
        z = np.random.randn(self.m, self.n)

        # Set u, s, v so that z = u.dot(s).dot(v.T)
        u, s, v = np.linalg.svd(z, full_matrices=False)
        s = np.diag(s)
        v = v.T

        w = np.random.randn(self.n, self.n)

        np_testing.assert_allclose(z.dot(w), m._apply_ambient(z, w))
        np_testing.assert_allclose(z.dot(w), m._apply_ambient((u, s, v), w))

    def test_apply_ambient_transpose(self):
        m = self.man
        z = np.random.randn(self.n, self.m)

        # Set u, s, v so that z = u.dot(s).dot(v.T)
        u, s, v = np.linalg.svd(z, full_matrices=False)
        s = np.diag(s)
        v = v.T

        w = np.random.randn(self.n, self.n)

        np_testing.assert_allclose(z.T.dot(w),
                                   m._apply_ambient_transpose(z, w))
        np_testing.assert_allclose(z.T.dot(w),
                                   m._apply_ambient_transpose((u, s, v), w))

    def test_tangent2ambient(self):
        m = self.man
        x = m.rand()
        z = m.randvec(x)

        z_ambient = (x[0].dot(z[1]).dot(x[2]) + z[0].dot(x[2]) +
                     x[0].dot(z[2].T))

        u, s, v = m.tangent2ambient(x, z)

        np_testing.assert_allclose(z_ambient, u.dot(s).dot(v.T))

    def test_ehess2rhess(self):
        pass

    def test_retr(self):
        # Test that the result is on the manifold and that for small
        # tangent vectors it has little effect.
        x = self.man.rand()
        u = self.man.randvec(x)

        y = self.man.retr(x, u)

        np_testing.assert_allclose(y[0].T.dot(y[0]), np.eye(self.k), atol=1e-6)
        np_testing.assert_allclose(y[2].dot(y[2].T), np.eye(self.k), atol=1e-6)

        u = u * 1e-6
        y = self.man.retr(x, u)
        y = y[0].dot(np.diag(y[1])).dot(y[2])

        u = self.man.tangent2ambient(x, u)
        u = u[0].dot(u[1]).dot(u[2].T)
        x = x[0].dot(np.diag(x[1])).dot(x[2])

        np_testing.assert_allclose(y, x + u, atol=1e-5)

    def test_egrad2rgrad(self):
        # Verify that egrad2rgrad and proj are equivalent.
        m = self.man
        x = m.rand()
        u, s, vt = x

        i = np.eye(self.k)

        f = 1 / (s[..., np.newaxis, :]**2 - s[..., :, np.newaxis]**2 + i)

        du = np.random.randn(self.m, self.k)
        ds = np.random.randn(self.k)
        dvt = np.random.randn(self.k, self.n)

        Up = (np.dot(np.dot(np.eye(self.m) - np.dot(u, u.T), du),
                     np.linalg.inv(np.diag(s))))
        M = (np.dot(f * (np.dot(u.T, du) - np.dot(du.T, u)), np.diag(s)) +
             np.dot(np.diag(s), f * (np.dot(vt, dvt.T) - np.dot(dvt, vt.T))) +
             np.diag(ds))
        Vp = (np.dot(np.dot(np.eye(self.n) - np.dot(vt.T, vt), dvt.T),
                     np.linalg.inv(np.diag(s))))

        up, m, vp = m.egrad2rgrad(x, (du, ds, dvt))

        np_testing.assert_allclose(Up, up)
        np_testing.assert_allclose(M, m)
        np_testing.assert_allclose(Vp, vp)

    def test_randvec(self):
        e = self.man
        x = e.rand()
        u = e.randvec(x)

        # Check that u is a tangent vector
        assert np.shape(u[0]) == (self.m, self.k)
        assert np.shape(u[1]) == (self.k, self.k)
        assert np.shape(u[2]) == (self.n, self.k)
        np_testing.assert_allclose(np.dot(u[0].T, x[0]),
                                   np.zeros((self.k, self.k)),
                                   atol=1e-6)
        np_testing.assert_allclose(np.dot(u[2].T, x[2].T),
                                   np.zeros((self.k, self.k)),
                                   atol=1e-6)

        v = e.randvec(x)

        np_testing.assert_almost_equal(e.norm(x, u), 1)
        assert e.norm(x, u - v) > 1e-6
コード例 #15
0
 def setUp(self):
     self.m = m = 10
     self.n = n = 5
     self.k = k = 3
     self.man = FixedRankEmbedded(m, n, k)