Esempio n. 1
0
    def apply_gradients(self, metric_grads_and_vars):
        """Makes optimization step.
        Args:
            metric_grads_and_vars: zip(metric, grads, vars), metric is
            a list of real valued tensors of shape (..., q, p, 2, q, p, 2),
            grad is a list of real valued tensors of shape (..., q, p, 2),
            vars is a list of real valued tf Variables of shape
            (..., q, p, 2)"""

        for mgv in metric_grads_and_vars:
            metric, grad, var = mgv
            var_c = m.real_to_complex(var)
            grad_c = m.real_to_complex(grad)
            rgrad_c = self.manifold.egrad_to_rgrad(metric, var_c, grad_c)
            lr = tf.cast(self._hyper["learning_rate"], dtype=var_c.dtype)
            new_var = self.manifold.retraction(var_c, -lr * rgrad_c)
            var.assign(m.complex_to_real(new_var))
Esempio n. 2
0
 def body(i, loss):
     with tf.GradientTape() as tape:
         qc = manifolds.real_to_complex(q)
         loss = tf.math.real(tf.linalg.trace(
             tf.linalg.adjoint(qc) @ h @ qc))
     grad = tape.gradient(loss, q)
     opt.apply_gradients(zip([grad], [q]))
     return i + 1, loss
Esempio n. 3
0
    def _resource_apply_dense(self, grad, var):

        # Complex version of grad
        complex_grad = m.real_to_complex(grad)

        # MERA like update
        _, u, v = tf.linalg.svd(adj(complex_grad))
        var.assign(m.convert.complex_to_real(-v @ adj(u)))
Esempio n. 4
0
    def _resource_apply_dense(self, grad, var):

        # Complex version of grad and var
        complex_var = m.real_to_complex(var)
        complex_grad = m.real_to_complex(grad)

        # learning rate
        eps = tf.cast(self._get_hyper("eps"), dtype=complex_grad.dtype)

        # noise
        noise = tf.random.normal(var.shape, dtype=var.dtype)
        noise = m.real_to_complex(noise)
        noise = noise * math.sqrt(eps)

        # search direction
        r = -self.manifold.egrad_to_rgrad(complex_var,
                                          0.5 * eps * complex_grad + noise)

        # New value of var
        new_var = self.manifold.retraction(complex_var, r)

        # Update of var
        var.assign(m.complex_to_real(new_var))
Esempio n. 5
0
    def _egrad_to_rgrad(self):
        """
        Checking egrad_to_rgrad method.
        1) rgrad is in the tangent space of a manifold's point
        2) <v1 egrad> = <v1 rgrad>_m (matching between egrad and rgrad)
        Args:

        Returns:
            list with two tf scalars that give maximum
            violation of two conditions
        """

        # vector that plays the role of a gradient
        xi = tf.random.normal(self.u.shape + (2,))
        xi = manifolds.real_to_complex(xi)
        xi = tf.cast(xi, dtype=self.u.dtype)

        # rgrad
        rgrad = self.m.egrad_to_rgrad(self.u, xi)

        err1 = rgrad - self.m.proj(self.u, rgrad)
        if self.m.rank == 2:
            err1 = tf.math.real(tf.linalg.norm(err1, axis=(-2, -1)))
        elif self.m.rank == 3:
            err1 = tf.math.real(rank3_norm(err1))

        if self.m.rank == 2:
            err2 = tf.reduce_sum(tf.math.conj(self.v1) * xi, axis=(-2, -1)) -\
                            self.m.inner(self.u, self.v1, rgrad)[..., 0, 0]
        elif self.m.rank == 3:
            err2 = tf.reduce_sum(tf.math.conj(self.v1) * xi, axis=(-3, -2, -1)) -\
                            self.m.inner(self.u, self.v1, rgrad)[..., 0, 0, 0]

        err2 = tf.abs(tf.math.real(err2))

        err1 = tf.reduce_max(err1)
        err2 = tf.reduce_max(err2)
        return err1, err2
Esempio n. 6
0
    def _egrad_to_rgrad(self):
        """
        Checking egrad to rgrad.
        1) rgrad is in a tangent space
        2) <v1 egrad> = inner<v1 rgrad>
        Args:

        Returns:
            error 1), dtype float32
            error 2), dtype float32
        """

        xi = tf.random.normal(self.u.shape + (2, ))
        xi = manifolds.real_to_complex(xi)
        xi = tf.cast(xi, dtype=self.u.dtype)
        rgrad = self.m.egrad_to_rgrad(self.u, xi)
        err1 = rgrad - self.m.proj(self.u, rgrad)
        err1 = tf.abs(tf.linalg.norm(err1))

        err2 = tf.reduce_sum(tf.math.conj(self.v1) * xi, axis=(-2, -1)) -\
                        self.m.inner(self.u, self.v1, rgrad)
        err2 = tf.abs(tf.math.real(err2))
        return tf.cast(err1, dtype=tf.float32), tf.cast(err2, dtype=tf.float32)
Esempio n. 7
0
    def _resource_apply_dense(self, grad, var):

        self.iter = self.iter + 1

        # Complex version of grad and var
        complex_var = m.real_to_complex(var)
        complex_grad = m.real_to_complex(grad)

        # learning rate
        lr = tf.cast(self._get_hyper("learning_rate"), complex_grad.dtype)

        # Riemannian gradient
        rgrad = self.manifold.egrad_to_rgrad(complex_var, complex_grad)

        # Complex versions of m and v
        momentum = self.get_slot(var, "momentum")
        v = self.get_slot(var, "v")
        if self.ams:
            v_hat = self.get_slot(var, "v_hat")
            v_hat_complex = m.real_to_complex(v_hat)
        momentum_complex = m.real_to_complex(momentum)
        v_complex = m.real_to_complex(v)

        # Update m, v and v_hat
        beta1 = tf.cast(self._get_hyper("beta1"), dtype=momentum_complex.dtype)
        beta2 = tf.cast(self._get_hyper("beta2"), dtype=momentum_complex.dtype)
        momentum_complex = beta1 * momentum_complex +\
            (1 - beta1) * rgrad
        v_complex = beta2 * v_complex +\
            (1 - beta2) * self.manifold.inner(complex_var,
                                              rgrad,
                                              rgrad)
        if self.ams:
            v_hat_complex = tf.maximum(tf.math.real(v_complex),
                                       tf.math.real(v_hat_complex))
            v_hat_complex = tf.cast(v_hat_complex, dtype=v_complex.dtype)

        # Bias correction
        lr_corr = lr * tf.math.sqrt(1 - beta2 ** self.iter) /\
            (1 - beta1 ** self.iter)

        # New value of var
        if self.ams:
            # Search direction
            search_dir = -lr_corr * momentum_complex /\
                (tf.sqrt(v_hat_complex) + self.eps)
            new_var, momentum_complex =\
                self.manifold.retraction_transport(complex_var,
                                                   momentum_complex,
                                                   search_dir)
        else:
            # Search direction
            search_dir = - lr_corr * momentum_complex /\
                (tf.sqrt(v_complex) + self.eps)
            new_var, momentum_complex =\
                self.manifold.retraction_transport(complex_var,
                                                   momentum_complex,
                                                   search_dir)

        # Assigning new value of momentum
        momentum.assign(m.complex_to_real(momentum_complex))
        # Assigning new value of v and v_hat
        v.assign(m.complex_to_real(v_complex))
        if self.ams:
            v_hat.assign(m.complex_to_real(v_hat_complex))

        # Update of var
        var.assign(m.complex_to_real(new_var))
Esempio n. 8
0
    def _resource_apply_dense(self, grad, var):

        # Complex version of grad and var
        complex_var = m.real_to_complex(var)
        complex_grad = m.real_to_complex(grad)

        # learning rate
        lr = tf.cast(self._get_hyper("learning_rate"),
                     dtype=complex_grad.dtype)

        # Riemannian gradient
        rgrad = self.manifold.egrad_to_rgrad(complex_var, complex_grad)

        # Upadte of vars (step and retruction)
        if self._momentum:

            if self._use_nesterov:

                # Update momentum
                momentum_var = self.get_slot(var, "momentum")
                momentum_complex_old = m.real_to_complex(momentum_var)
                momentum = tf.cast(self._get_hyper("momentum"),
                                   dtype=momentum_complex_old.dtype)
                momentum_complex_new = momentum * momentum_complex_old +\
                    (1 - momentum) * rgrad

                # Transport and retruction
                new_var, momentum_complex =\
                    self.manifold.retraction_transport(complex_var,
                                                       momentum_complex_new,
                                                       -lr * momentum_complex_new -\
                                                       lr * momentum *\
                                                       (momentum_complex_new -\
                                                        momentum_complex_old))

                momentum_var.assign(m.complex_to_real(momentum_complex))

            else:

                # Update momentum
                momentum_var = self.get_slot(var, "momentum")
                momentum_complex = m.real_to_complex(momentum_var)
                momentum = tf.cast(self._get_hyper("momentum"),
                                   dtype=momentum_complex.dtype)
                momentum_complex = momentum * momentum_complex +\
                    (1 - momentum) * rgrad

                # Transport and retruction
                new_var, momentum_complex =\
                    self.manifold.retraction_transport(complex_var,
                                                       momentum_complex,
                                                       -lr * momentum_complex)

                momentum_var.assign(m.complex_to_real(momentum_complex))
        else:

            # New value of var
            new_var = self.manifold.retraction(complex_var, -lr * rgrad)

        # Update of var
        var.assign(m.complex_to_real(new_var))