Example #1
0
    def test_remote_tensor_multi_var_methods(self):
        hook = TorchHook(verbose=False)
        local = hook.local_worker
        remote = VirtualWorker(hook, 1)
        local.add_worker(remote)

        x = torch.FloatTensor([[1, 2], [4, 3], [5, 6]])
        x.send(remote)
        y, z = torch.max(x, 1)
        assert torch.equal(y.get(), torch.FloatTensor([2, 4, 6]))
        assert torch.equal(z.get(), torch.LongTensor([1, 0, 1]))

        x = torch.FloatTensor([[0, 0], [1, 0]]).send(remote)
        y, z = torch.qr(x)
        assert (y.get() == torch.FloatTensor([[0, -1], [-1, 0]])).all()
        assert (z.get() == torch.FloatTensor([[-1, 0], [0, 0]])).all()

        x = torch.arange(1, 6).send(remote)
        y, z = torch.kthvalue(x, 4)
        assert (y.get() == torch.FloatTensor([4])).all()
        assert (z.get() == torch.LongTensor([3])).all()

        x = torch.FloatTensor([[0, 0], [1, 1]]).send(remote)
        y, z = torch.eig(x, True)
        assert (y.get() == torch.FloatTensor([[1, 0], [0, 0]])).all()
        assert ((z.get() == torch.FloatTensor([[0, 0], [1, 0]])) == torch.ByteTensor([[1, 0], [1, 0]])).all()

        x = torch.zeros(3, 3).send(remote)
        w, y, z = torch.svd(x)
        assert (w.get() == torch.FloatTensor([[1, 0, 0], [0, 1, 0], [0, 0, 1]])).all()
        assert (y.get() == torch.FloatTensor([0, 0, 0])).all()
        assert (z.get() == torch.FloatTensor([[1, 0, 0], [0, 1, 0], [0, 0, 1]])).all()
Example #2
0
    def test_torch_function_with_multiple_output_on_local_var(self):
        x = Var(torch.FloatTensor([[1, 2], [2, 3], [5, 6]]))
        t, s = torch.max(x, 1)
        assert (t == Var(torch.FloatTensor([2, 3, 6]))).all()
        assert (s == Var(torch.LongTensor([1, 1, 1]))).all()

        x = Var(torch.FloatTensor([[0, 0], [0, 0]]))
        y, z = torch.eig(x, True)
        assert (y == Var(torch.FloatTensor([[0, 0], [0, 0]]))).all()
        assert (z == Var(torch.FloatTensor([[1, 0.], [0, 1]]))).all()


        x = Var(torch.FloatTensor([[0, 0], [1, 0]]))
        y, z = torch.qr(x)
        assert (y == Var(torch.FloatTensor([[0, -1], [-1, 0]]))).all()
        assert (z == Var(torch.FloatTensor([[-1, 0], [0, 0]]))).all()

        x = Var(torch.arange(1, 6))
        y, z = torch.kthvalue(x, 4)
        assert (y == Var(torch.FloatTensor([4]))).all()
        assert (z == Var(torch.LongTensor([3]))).all()

        x = Var(torch.zeros(3, 3))
        w, y, z = torch.svd(x)
        assert (w == Var(torch.FloatTensor([[1, 0, 0], [0, 1, 0], [0, 0, 1]]))).all()
        assert (y == Var(torch.FloatTensor([0, 0, 0]))).all()
        assert (z == Var(torch.FloatTensor([[1, 0, 0], [0, 1, 0], [0, 0, 1]]))).all()
Example #3
0
    def test_local_tensor_multi_var_methods(self):
        x = torch.FloatTensor([[1, 2], [2, 3], [5, 6]])
        t, s = torch.max(x, 1)
        assert (t == torch.FloatTensor([2, 3, 6])).float().sum() == 3
        assert (s == torch.LongTensor([1, 1, 1])).float().sum() == 3

        x = torch.FloatTensor([[0, 0], [1, 1]])
        y, z = torch.eig(x, True)
        assert (y == torch.FloatTensor([[1, 0], [0, 0]])).all()
        assert (torch.equal(z == torch.FloatTensor([[0, 0], [1, 0]]), torch.ByteTensor([[1, 0], [1, 0]])))

        x = torch.FloatTensor([[0, 0], [1, 0]])
        y, z = torch.qr(x)
        assert (y == torch.FloatTensor([[0, -1], [-1, 0]])).all()
        assert (z == torch.FloatTensor([[-1, 0], [0, 0]])).all()

        x = torch.arange(1, 6)
        y, z = torch.kthvalue(x, 4)
        assert (y == torch.FloatTensor([4])).all()
        assert (z == torch.LongTensor([3])).all()

        x = torch.zeros(3, 3)
        w, y, z = torch.svd(x)
        assert (w == torch.FloatTensor([[1, 0, 0], [0, 1, 0], [0, 0, 1]])).all()
        assert (y == torch.FloatTensor([0, 0, 0])).all()
        assert (z == torch.FloatTensor([[1, 0, 0], [0, 1, 0], [0, 0, 1]])).all()
Example #4
0
    def test_torch_function_with_multiple_output_on_remote_var(self):
        hook = TorchHook(verbose=False)
        me = hook.local_worker
        remote = VirtualWorker(id=2, hook=hook)
        me.add_worker(remote)

        x = Var(torch.FloatTensor([[1, 2], [4, 3], [5, 6]]))
        x.send(remote)
        y, z = torch.max(x, 1)
        y.get()
        assert torch.equal(y, Var(torch.FloatTensor([2, 4, 6])))

        x = Var(torch.FloatTensor([[0, 0], [1, 0]])).send(remote)
        y, z = torch.qr(x)
        assert (y.get() == Var(torch.FloatTensor([[0, -1], [-1, 0]]))).all()
        assert (z.get() == Var(torch.FloatTensor([[-1, 0], [0, 0]]))).all()

        x = Var(torch.arange(1, 6)).send(remote)
        y, z = torch.kthvalue(x, 4)
        assert (y.get() == Var(torch.FloatTensor([4]))).all()
        assert (z.get() == Var(torch.LongTensor([3]))).all()

        x = Var(torch.FloatTensor([[0, 0], [0, 0]]))
        x.send(remote)
        y, z = torch.eig(x, True)
        assert (y.get() == Var(torch.FloatTensor([[0, 0], [0, 0]]))).all()
        assert (z.get() == Var(torch.FloatTensor([[1, 0.], [0, 1]]))).all()


        x = Var(torch.zeros(3, 3)).send(remote)
        w, y, z = torch.svd(x)
        assert (w.get() == Var(torch.FloatTensor([[1, 0, 0], [0, 1, 0], [0, 0, 1]]))).all()
        assert (y.get() == Var(torch.FloatTensor([0, 0, 0]))).all()
        assert (z.get() == Var(torch.FloatTensor([[1, 0, 0], [0, 1, 0], [0, 0, 1]]))).all()
Example #5
0
 def __wct_core(self, cont_feat, styl_feat):
     cFSize = cont_feat.size()
     c_mean = torch.mean(cont_feat, 1)  # c x (h x w)
     c_mean = c_mean.unsqueeze(1).expand_as(cont_feat)
     cont_feat = cont_feat - c_mean
     
     iden = torch.eye(cFSize[0])  # .double()
     if self.is_cuda:
         iden = iden.cuda()
     
     contentConv = torch.mm(cont_feat, cont_feat.t()).div(cFSize[1] - 1) + iden
     # del iden
     c_u, c_e, c_v = torch.svd(contentConv, some=False)
     # c_e2, c_v = torch.eig(contentConv, True)
     # c_e = c_e2[:,0]
     
     k_c = cFSize[0]
     for i in range(cFSize[0] - 1, -1, -1):
         if c_e[i] >= 0.00001:
             k_c = i + 1
             break
     
     sFSize = styl_feat.size()
     s_mean = torch.mean(styl_feat, 1)
     styl_feat = styl_feat - s_mean.unsqueeze(1).expand_as(styl_feat)
     styleConv = torch.mm(styl_feat, styl_feat.t()).div(sFSize[1] - 1)
     s_u, s_e, s_v = torch.svd(styleConv, some=False)
     
     k_s = sFSize[0]
     for i in range(sFSize[0] - 1, -1, -1):
         if s_e[i] >= 0.00001:
             k_s = i + 1
             break
     
     c_d = (c_e[0:k_c]).pow(-0.5)
     step1 = torch.mm(c_v[:, 0:k_c], torch.diag(c_d))
     step2 = torch.mm(step1, (c_v[:, 0:k_c].t()))
     whiten_cF = torch.mm(step2, cont_feat)
     
     s_d = (s_e[0:k_s]).pow(0.5)
     targetFeature = torch.mm(torch.mm(torch.mm(s_v[:, 0:k_s], torch.diag(s_d)), (s_v[:, 0:k_s].t())), whiten_cF)
     targetFeature = targetFeature + s_mean.unsqueeze(1).expand_as(targetFeature)
     return targetFeature
    def train(self, x):
        self.model.train()
        
        o = self.model(x)
        loss = torch.mean(torch.pow(torch.mm(o, self.B.t()) - x, 2))

        self.optimizer.zero_grad()
        loss.backward()
        self.optimizer.step()

        U, _, V = torch.svd(torch.mm(x.t().data, o.data))
        self.B = torch.autograd.Variable(torch.mm(U, V.t()))
        
        return loss.data.cpu().numpy()
Example #7
0
 def func():
   torch.svd(torch.rand((N, N)).cuda())
   torch.cuda.synchronize()
Example #8
0
def find_homography_dlt(
        points1: torch.Tensor,
        points2: torch.Tensor,
        weights: Optional[torch.Tensor] = None) -> torch.Tensor:
    r"""Compute the homography matrix using the DLT formulation.

    The linear system is solved by using the Weighted Least Squares Solution for the 4 Points algorithm.

    Args:
        points1: A set of points in the first image with a tensor shape :math:`(B, N, 2)`.
        points2: A set of points in the second image with a tensor shape :math:`(B, N, 2)`.
        weights: Tensor containing the weights per point correspondence with a shape of :math:`(B, N)`.

    Returns:
        the computed homography matrix with shape :math:`(B, 3, 3)`.
    """
    if points1.shape != points2.shape:
        raise AssertionError(points1.shape)
    if not (len(points1.shape) >= 1 and points1.shape[-1] == 2):
        raise AssertionError(points1.shape)
    if points1.shape[1] < 4:
        raise AssertionError(points1.shape)

    device, dtype = _extract_device_dtype([points1, points2])

    eps: float = 1e-8
    points1_norm, transform1 = normalize_points(points1)
    points2_norm, transform2 = normalize_points(points2)

    x1, y1 = torch.chunk(points1_norm, dim=-1, chunks=2)  # BxNx1
    x2, y2 = torch.chunk(points2_norm, dim=-1, chunks=2)  # BxNx1
    ones, zeros = torch.ones_like(x1), torch.zeros_like(x1)

    # DIAPO 11: https://www.uio.no/studier/emner/matnat/its/nedlagte-emner/UNIK4690/v16/forelesninger/lecture_4_3-estimating-homographies-from-feature-correspondences.pdf  # noqa: E501
    ax = torch.cat(
        [zeros, zeros, zeros, -x1, -y1, -ones, y2 * x1, y2 * y1, y2], dim=-1)
    ay = torch.cat(
        [x1, y1, ones, zeros, zeros, zeros, -x2 * x1, -x2 * y1, -x2], dim=-1)
    A = torch.cat((ax, ay), dim=-1).reshape(ax.shape[0], -1, ax.shape[-1])

    if weights is None:
        # All points are equally important
        A = A.transpose(-2, -1) @ A
    else:
        # We should use provided weights
        if not (len(weights.shape) == 2
                and weights.shape == points1.shape[:2]):
            raise AssertionError(weights.shape)
        w_diag = torch.diag_embed(
            weights.unsqueeze(dim=-1).repeat(1, 1,
                                             2).reshape(weights.shape[0], -1))
        A = A.transpose(-2, -1) @ w_diag @ A

    try:
        _, _, V = torch.svd(A)
    except RuntimeError:
        warnings.warn('SVD did not converge', RuntimeWarning)
        return torch.empty((points1_norm.size(0), 3, 3),
                           device=device,
                           dtype=dtype)

    H = V[..., -1].view(-1, 3, 3)
    H = transform2.inverse() @ (H @ transform1)
    H_norm = H / (H[..., -1:, -1:] + eps)
    return H_norm
Example #9
0
    def get_loss_components(self, data_dict):
        loss_components = dict()

        N_data = data_dict['data'].shape[0]

        if ('siam_reflection_data' in data_dict) and ('siam_same_levelvec_data'
                                                      in data_dict):
            is_computing_signed_siamese_pairs = True
        else:
            is_computing_signed_siamese_pairs = False

        data_torch = utils.convert_into_at_least_2d_pytorch_tensor(
            data_dict['data']).requires_grad_().to(self.device)
        norm_level_data_torch = utils.convert_into_at_least_2d_pytorch_tensor(
            data_dict['norm_level_data']).requires_grad_().to(self.device)
        norm_level_weight_torch = utils.convert_into_at_least_2d_pytorch_tensor(
            data_dict['norm_level_weight']).requires_grad_().to(self.device)

        [y_torch, J_torch] = self.y_torch_and_J_torch(data_torch)

        # (level set) prediction error
        norm_level_wnmse_per_dim = utils.compute_wnmse_per_dim(
            prediction=torch.norm(y_torch, dim=1).unsqueeze(1),
            ground_truth=norm_level_data_torch,
            weight=norm_level_weight_torch)

        if is_computing_signed_siamese_pairs:
            siam_reflection_data_torch = utils.convert_into_at_least_2d_pytorch_tensor(
                data_dict['siam_reflection_data']).requires_grad_().to(
                    self.device)
            siam_reflection_weight_torch = utils.convert_into_at_least_2d_pytorch_tensor(
                data_dict['siam_reflection_weight']).requires_grad_().to(
                    self.device)
            siam_same_levelvec_data_torch = utils.convert_into_at_least_2d_pytorch_tensor(
                data_dict['siam_same_levelvec_data']).requires_grad_().to(
                    self.device)
            siam_same_levelvec_weight_torch = utils.convert_into_at_least_2d_pytorch_tensor(
                data_dict['siam_same_levelvec_weight']).requires_grad_().to(
                    self.device)
            augmenting_vector_torch = utils.convert_into_at_least_2d_pytorch_tensor(
                data_dict['augmenting_vector']).requires_grad_().to(
                    self.device)
            siam_frac_aug_weight_torch = utils.convert_into_at_least_2d_pytorch_tensor(
                data_dict['siam_frac_aug_weight']).requires_grad_().to(
                    self.device)

            siam_reflection_y_torch = self.y_torch(siam_reflection_data_torch)
            siam_reflection_wnmse_torch = utils.compute_wnmse_per_dim(
                prediction=(-siam_reflection_y_torch),
                ground_truth=y_torch,
                weight=siam_reflection_weight_torch)

            N_siam_same_levelvec = siam_same_levelvec_data_torch.shape[1]
            siam_same_levelvec_y_torch_list = [
                self.y_torch(
                    siam_same_levelvec_data_torch[:, n_siam_same_levelvec, :])
                for n_siam_same_levelvec in range(N_siam_same_levelvec)
            ]
            siam_same_levelvec_wnmse_torch = torch.stack([
                utils.compute_wnmse_per_dim(
                    prediction=siam_same_levelvec_y_torch_list[
                        n_siam_same_levelvec],
                    ground_truth=y_torch,
                    weight=siam_same_levelvec_weight_torch[:,
                                                           n_siam_same_levelvec]
                ).squeeze()
                for n_siam_same_levelvec in range(N_siam_same_levelvec)
            ],
                                                         dim=0).mean(axis=0)

            N_siam_frac_augs = 4
            normalized_y_torch = utils.normalize(y_torch, data_axis=1)
            siam_frac_aug_normalized_y_torch_list = [
                utils.normalize(self.y_torch(data_torch - (
                    ((1.0 * n_siam_frac_augs) / N_siam_frac_augs) *
                    augmenting_vector_torch)),
                                data_axis=1)
                for n_siam_frac_augs in range(1, N_siam_frac_augs)
            ]
            siam_frac_aug_wnmse_torch = torch.stack([
                utils.compute_wnmse_per_dim(
                    prediction=siam_frac_aug_normalized_y_torch_list[
                        n_siam_frac_augs],
                    ground_truth=normalized_y_torch,
                    weight=siam_frac_aug_weight_torch).squeeze()
                for n_siam_frac_augs in range(N_siam_frac_augs - 1)
            ],
                                                    dim=0).mean(axis=0)

        # Local PCA's Rowspace and Nullspace Eigenvectors extraction
        # (originally from the V Matrix of the Local PCA's Covariance Matrix's SVD (cov_svd_V)):
        cov_torch_rowspace = utils.convert_into_at_least_2d_pytorch_tensor(
            data_dict['cov_rowspace']).to(self.device)
        assert (cov_torch_rowspace.shape[2] == (self.dim_ambient -
                                                self.N_constraints))
        cov_torch_nullspace = utils.convert_into_at_least_2d_pytorch_tensor(
            data_dict['cov_nullspace']).to(self.device)
        assert (cov_torch_nullspace.shape[2] == self.N_constraints)

        cov_torch_rowspace_projector = (
            cov_torch_rowspace @ cov_torch_rowspace.transpose(-2, -1))
        cov_torch_nullspace_projector = (
            cov_torch_nullspace @ cov_torch_nullspace.transpose(-2, -1))

        # Constraint Manifold Neural Network's Jacobian
        # Rowspace and Nullspace eigenvectors extraction:
        [_, _, J_torch_svd_V] = torch.svd(J_torch, some=False)
        J_torch_rowspace = J_torch_svd_V[:, :, :self.N_constraints]
        J_torch_nullspace = J_torch_svd_V[:, :, self.N_constraints:]
        J_torch_rowspace_projector = (
            J_torch_rowspace @ J_torch_rowspace.transpose(-2, -1))
        J_torch_nullspace_projector = (
            J_torch_nullspace @ J_torch_nullspace.transpose(-2, -1))

        # we want to align so that J_torch_nullspace == cov_torch_rowspace,
        # so here is the projection loss (I - A^{+}A)b_i whose norm is to be minimized during training:
        J_nspace_proj_error_per_dim = cov_torch_nullspace_projector @ J_torch_nullspace

        # we want to align so that cov_torch_nullspace == J_torch_rowspace,
        # so here is the projection loss (I - B^{+}B)a_j whose norm is to be minimized during training:
        cov_nspace_proj_error_per_dim = J_torch_nullspace_projector @ cov_torch_nullspace

        # similarly we want to align so that J_torch_rowspace == cov_torch_nullspace:
        J_rspace_proj_error_per_dim = cov_torch_rowspace_projector @ J_torch_rowspace

        # similarly we want to align so that cov_torch_rowspace == J_torch_nullspace:
        cov_rspace_proj_error_per_dim = J_torch_rowspace_projector @ cov_torch_rowspace

        # Local Tangent Space Alignment (LTSA) and Local PCA (eigenvectors) alignment errors:
        J_nspace_proj_loss_per_dim = (J_nspace_proj_error_per_dim**2).mean(
            axis=0)
        cov_nspace_proj_loss_per_dim = (cov_nspace_proj_error_per_dim**2).mean(
            axis=0)
        J_rspace_proj_loss_per_dim = (J_rspace_proj_error_per_dim**2).mean(
            axis=0)
        cov_rspace_proj_loss_per_dim = (cov_rspace_proj_error_per_dim**2).mean(
            axis=0)

        loss_components['norm_level_wnmse_per_dim'] = norm_level_wnmse_per_dim
        if is_computing_signed_siamese_pairs:
            loss_components[
                'siam_reflection_wnmse_torch'] = siam_reflection_wnmse_torch
            loss_components[
                'siam_same_levelvec_wnmse_torch'] = siam_same_levelvec_wnmse_torch
            loss_components[
                'siam_frac_aug_wnmse_torch'] = siam_frac_aug_wnmse_torch
        loss_components[
            'J_nspace_proj_loss_per_dim'] = J_nspace_proj_loss_per_dim
        loss_components[
            'cov_nspace_proj_loss_per_dim'] = cov_nspace_proj_loss_per_dim
        loss_components[
            'J_rspace_proj_loss_per_dim'] = J_rspace_proj_loss_per_dim
        loss_components[
            'cov_rspace_proj_loss_per_dim'] = cov_rspace_proj_loss_per_dim

        return loss_components
Example #10
0
#    plt.imshow(ims, interpolation=None)
#
#plt.savefig('mouse_results/clusterings.png', format='png')
#plt.savefig(shared_path + 'clusterings.eps', format='eps')

#mean_hhat = all_hhats_cat.mean(0, keepdim=True)
#all_hhats_cat_c = all_hhats_cat - mean_hhat
#
#U, S, V = torch.svd(all_hhats_cat_c.t())

folder = 'registered_results'
if 1:
    mean_x = all_xs_cat.mean(0, keepdim=True)
    all_xs_cat_c = (all_xs_cat - mean_x).view(all_xs_cat.size(0), -1)

    Ureal, Sreal, _ = torch.svd(all_xs_cat_c.t())

    mdl.train(mode=False)
    mdl.eval()

    W = Ureal[:, :100]
    pca_coefs = torch.matmul(W.t(), all_xs_cat_c.t()).t()

    recons = torch.matmul(W, pca_coefs.t()).t().contiguous().view(
        -1, 456, 320) + mean_x

    all_mmds = []
    all_stats = []
    num_samples = 5
    for J in range(1, 60, 5):
        print(J)
Example #11
0
def randomized_svd_gpu(M, n_components, n_oversamples=10, n_iter='auto',
                       transpose='auto', random_state=0, lib='cupy'):
    """Computes a truncated randomized SVD on GPU. Adapted from Sklearn.

    Parameters
    ----------
    M : ndarray or sparse matrix
        Matrix to decompose
    n_components : int
        Number of singular values and vectors to extract.
    n_oversamples : int (default is 10)
        Additional number of random vectors to sample the range of M so as
        to ensure proper conditioning. The total number of random vectors
        used to find the range of M is n_components + n_oversamples. Smaller
        number can improve speed but can negatively impact the quality of
        approximation of singular vectors and singular values.
    n_iter : int or 'auto' (default is 'auto')
        Number of power iterations. It can be used to deal with very noisy
        problems. When 'auto', it is set to 4, unless `n_components` is small
        (< .1 * min(X.shape)) `n_iter` in which case is set to 7.
        This improves precision with few components.
    transpose : True, False or 'auto' (default)
        Whether the algorithm should be applied to M.T instead of M. The
        result should approximately be the same. The 'auto' mode will
        trigger the transposition if M.shape[1] > M.shape[0] since this
        implementation of randomized SVD tend to be a little faster in that
        case.
    random_state : int, RandomState instance or None, optional (default=None)
        The seed of the pseudo random number generator to use when shuffling
        the data.  If int, random_state is the seed used by the random number
        generator; If RandomState instance, random_state is the random number
        generator; If None, the random number generator is the RandomState
        instance used by `np.random`.
    lib : {'cupy', 'pytorch'}, str optional
        Chooses the GPU library to be used.

    Notes
    -----
    This algorithm finds a (usually very good) approximate truncated
    singular value decomposition using randomization to speed up the
    computations. It is particularly fast on large matrices on which
    you wish to extract only a small number of components. In order to
    obtain further speed up, `n_iter` can be set <=2 (at the cost of
    loss of precision).

    References
    ----------
    * Finding structure with randomness: Stochastic algorithms for constructing
      approximate matrix decompositions
      Halko, et al., 2009 http://arxiv.org/abs/arXiv:0909.4061
    * A randomized algorithm for the decomposition of matrices
      Per-Gunnar Martinsson, Vladimir Rokhlin and Mark Tygert
    * An implementation of a randomized algorithm for principal component
      analysis
      A. Szlam et al. 2014
    """
    random_state = check_random_state(random_state)
    n_random = n_components + n_oversamples
    n_samples, n_features = M.shape

    if n_iter == 'auto':
        # Checks if the number of iterations is explicitly specified
        n_iter = 7 if n_components < .1 * min(M.shape) else 4

    if transpose == 'auto':
        transpose = n_samples < n_features
    if transpose:
        M = M.T # this implementation is a bit faster with smaller shape[1]

    if lib == 'cupy':
        M = cupy.array(M)
        M = cupy.asarray(M)

        # Generating normal random vectors with shape: (M.shape[1], n_random)
        Q = random_state.normal(size=(M.shape[1], n_random))
        Q = cupy.array(Q)
        Q = cupy.asarray(Q)

        # Perform power iterations with Q to further 'imprint' the top
        # singular vectors of M in Q
        for i in range(n_iter):
            Q = cupy.dot(M, Q)
            Q = cupy.dot(M.T, Q)

        # Sample the range of M by linear projection of Q.
        # Extract an orthonormal basis
        Q, _ = cupy.linalg.qr(cupy.dot(M, Q), mode='reduced')

        # project M to the (k + p) dimensional space using the basis vectors
        B = cupy.dot(Q.T, M)

        B = cupy.array(B)
        Q = cupy.array(Q)
        # compute the SVD on the thin matrix: (k + p) wide
        Uhat, s, V = cupy.linalg.svd(B, full_matrices=False, compute_uv=True)
        del B
        U = cupy.dot(Q, Uhat)

        if transpose:
            # transpose back the results according to the input convention
            return (V[:n_components, :].T, s[:n_components],
                    U[:,:n_components].T)
        else:
            return U[:, :n_components], s[:n_components], V[:n_components, :]

    elif lib == 'pytorch':
        M_gpu = torch.Tensor.cuda(torch.from_numpy(M.astype('float32')))

        # Generating normal random vectors with shape: (M.shape[1], n_random)
        Q = torch.cuda.FloatTensor(M_gpu.shape[1], n_random).normal_()

        # Perform power iterations with Q to further 'imprint' the top
        # singular vectors of M in Q
        for i in range(n_iter):
            Q = torch.mm(M_gpu, Q)
            Q = torch.mm(torch.transpose(M_gpu, 0, 1), Q)

        # Sample the range of M by linear projection of Q.
        # Extract an orthonormal basis
        Q, _ = torch.qr(torch.mm(M_gpu, Q))

        # project M to the (k + p) dimensional space using the basis vectors
        B = torch.mm(torch.transpose(Q, 0, 1), M_gpu)

        # compute the SVD on the thin matrix: (k + p) wide
        Uhat, s, V = torch.svd(B)
        del B
        U = torch.mm(Q, Uhat)

        if transpose:
            # transpose back the results according to the input convention
            return (torch.transpose(V[:n_components, :], 0, 1),
                    s[:n_components],
                    torch.transpose(U[:, :n_components], 0, 1))
        else:
            return U[:, :n_components], s[:n_components], V[:n_components, :]
Example #12
0
    def read_matdataset(self):

        path = self.datadir + 'feature_map_ResNet_101_{}.hdf5'.format(
            self.dataset)
        print('_____')
        print(path)
        tic = time.clock()
        hf = h5py.File(path, 'r')
        features = np.array(hf.get('feature_map'))
        #        shape = features.shape
        #        features = features.reshape(shape[0],shape[1],shape[2]*shape[3])
        labels = np.array(hf.get('labels'))
        trainval_loc = np.array(hf.get('trainval_loc'))
        #        train_loc = np.array(hf.get('train_loc')) #--> train_feature = TRAIN SEEN
        #        val_unseen_loc = np.array(hf.get('val_unseen_loc')) #--> test_unseen_feature = TEST UNSEEN
        test_seen_loc = np.array(hf.get('test_seen_loc'))
        test_unseen_loc = np.array(hf.get('test_unseen_loc'))

        if self.is_unsupervised_attr:
            print('Unsupervised Attr')
            class_path = './w2v/{}_class.pkl'.format(self.dataset)
            with open(class_path, 'rb') as f:
                w2v_class = pickle.load(f)
            assert w2v_class.shape == (50, 300)
            w2v_class = torch.tensor(w2v_class).float()

            U, s, V = torch.svd(w2v_class)
            reconstruct = torch.mm(torch.mm(U, torch.diag(s)),
                                   torch.transpose(V, 1, 0))
            print('sanity check: {}'.format(
                torch.norm(reconstruct - w2v_class).item()))

            print('shape U:{} V:{}'.format(U.size(), V.size()))
            print('s: {}'.format(s))

            self.w2v_att = torch.transpose(V, 1, 0).to(self.device)
            self.att = torch.mm(U, torch.diag(s)).to(self.device)
            self.normalize_att = torch.mm(U, torch.diag(s)).to(self.device)

        else:
            print('Expert Attr')
            att = np.array(hf.get('att'))

            print("threshold at zero attribute with negative value")
            att[att < 0] = 0

            self.att = torch.from_numpy(att).float().to(self.device)

            original_att = np.array(hf.get('original_att'))
            self.original_att = torch.from_numpy(original_att).float().to(
                self.device)

            w2v_att = np.array(hf.get('w2v_att'))
            self.w2v_att = torch.from_numpy(w2v_att).float().to(self.device)

            self.normalize_att = self.original_att / 100

        print('Finish loading data in ', time.clock() - tic)

        train_feature = features[trainval_loc]
        test_seen_feature = features[test_seen_loc]
        test_unseen_feature = features[test_unseen_loc]
        if self.is_scale:
            scaler = preprocessing.MinMaxScaler()

            train_feature = scaler.fit_transform(train_feature)
            test_seen_feature = scaler.fit_transform(test_seen_feature)
            test_unseen_feature = scaler.fit_transform(test_unseen_feature)

        train_feature = torch.from_numpy(
            train_feature).float()  #.to(self.device)
        test_seen_feature = torch.from_numpy(
            test_seen_feature)  #.float().to(self.device)
        test_unseen_feature = torch.from_numpy(
            test_unseen_feature)  #.float().to(self.device)

        train_label = torch.from_numpy(
            labels[trainval_loc]).long()  #.to(self.device)
        test_unseen_label = torch.from_numpy(
            labels[test_unseen_loc])  #.long().to(self.device)
        test_seen_label = torch.from_numpy(
            labels[test_seen_loc])  #.long().to(self.device)

        self.seenclasses = torch.from_numpy(
            np.unique(train_label.cpu().numpy())).to(self.device)

        self.unseenclasses = torch.from_numpy(
            np.unique(test_unseen_label.cpu().numpy())).to(self.device)
        self.ntrain = train_feature.size()[0]
        self.ntrain_class = self.seenclasses.size(0)
        self.ntest_class = self.unseenclasses.size(0)
        self.train_class = self.seenclasses.clone()
        self.allclasses = torch.arange(0, self.ntrain_class +
                                       self.ntest_class).long()

        #        self.train_mapped_label = map_label(train_label, self.seenclasses)

        self.data = {}
        self.data['train_seen'] = {}
        self.data['train_seen']['resnet_features'] = train_feature
        self.data['train_seen']['labels'] = train_label

        self.data['train_unseen'] = {}
        self.data['train_unseen']['resnet_features'] = None
        self.data['train_unseen']['labels'] = None

        self.data['test_seen'] = {}
        self.data['test_seen']['resnet_features'] = test_seen_feature
        self.data['test_seen']['labels'] = test_seen_label

        self.data['test_unseen'] = {}
        self.data['test_unseen']['resnet_features'] = test_unseen_feature
        self.data['test_unseen']['labels'] = test_unseen_label
Example #13
0
    def get_clean_dataloader(self):
        """
        Get the feature representation of samples from each class individually.
        Compute centered  representation.
        Singular value decomposition.
        Compute the vector of the outlier scores.
        Remove the examples with the top epsilon scores from the samples of each class and form the clean dataset.

        Returns:
            torch.utils.data.DataLoader: after removing the suspicious samples with bigger singular value, return the clean dataloader.
        """
        final_set = None  # TODO
        for k in range(self.dataset.num_classes):
            # self.class_dataset = self.dataset.get_class_set(self.mix_dataset,classes = [k])
            idx = []
            for i, data in enumerate(self.mix_dataset):
                _input, _label = self.model.get_data(data)
                _input = _input.view(1, _input.shape[0], _input.shape[1],
                                     _input.shape[2])
                if _label.item() == k:
                    idx.append(k)
            self.class_dataset = torch.utils.data.Subset(self.mix_dataset, idx)

            layer_output_all = torch.empty([])  # TODO
            for i, data in enumerate(self.class_dataset):
                _input, _label = self.model.get_data(data)
                layer_output = self.model.get_layer(
                    _input, layer_output=self.preprocess_layer)
                layer_output = layer_output.view(1, -1)
                if i == 0:
                    layer_output_all = layer_output
                else:
                    layer_output_all = torch.cat(
                        (layer_output_all, layer_output))

            layer_output_mean = torch.mean(layer_output_all, dim=0)

            for i in range(len(self.class_dataset)):
                layer_output_all[i] = layer_output_all[i] - layer_output_mean

            u, s, v = torch.svd(layer_output_all)
            v_transpose = torch.transpose(v, 1, 0)
            outlier_scores = torch.rand([layer_output_all.shape[0]],
                                        device=env['device'])
            for i in range(len(self.class_dataset)):
                outlier_scores[i] = (layer_output_all[i].view(1, -1)
                                     @ v_transpose[i].view(-1, 1))**2
            outlier_scores_sorted, indices = torch.sort(outlier_scores,
                                                        descending=True)

            clean_indices = indices[self.epsilon:]
            self.class_dataset = torch.utils.data.Subset(
                self.class_dataset, clean_indices)
            if k == 0:
                final_set = self.class_dataset
            else:
                final_set = torch.utils.data.ConcatDataset(
                    [final_set, self.class_dataset])

        final_dataloader = self.dataset.get_dataloader(mode=None,
                                                       dataset=final_set,
                                                       num_workers=0,
                                                       pin_memory=False)
        return final_dataloader
Example #14
0
def RealDataAlg(MaxIters,
                X,
                Y,
                R,
                sXs,
                conDenfs,
                Cb=10,
                CT=1,
                log=0,
                bThetainit=None,
                betainit=None,
                tols=None,
                ErrOpts=0,
                etab=0.05,
                etaT=0.05):
    """
    MaxIters: max iteration number.
    X: the covariate matrix, n x m x p
    Y: the response matrix, n x m
    R: the Missing matrix, n x m
    sXs: sample of X for MCMC, p x N
    conDenfs: a list to contain the likelihood function of Y|X, and its fisrt derivative and second derivative w.r.t second argument.
             [f, f2, f22]. In fact, f22 is not used.
    Cb: the constant of Lambda_beta
    CT: the constant of Lambda_bTheta
    log: Whether output detail training log. 0 not output, 1 output simple training log, 2 output detailed training log.
    bThetainit: initial value of bTheta
    tol: terminate tolerace.
    ErrOpts: whether output errors of beta and bTheta. 0 no, 1 yes
    etabinit: The initial learning rate of beta
    etaTinit: The initial learning rate of btheta
    """
    n, m, p = X.shape
    f, f2, f22 = conDenfs
    tol, tolb, tolT = tols
    Lcon = -10
    # To contain the training errors of bTheta and beta, respectively.
    Likelis = []
    bThetahats = []
    betahats = []

    # Initial the value of beta, bTheta and R_b
    bThetaOld = torch.rand(n, m) if bThetainit is None else bThetainit
    betaOld = torch.rand(p) if betainit is None else betainit
    # the relative change of Loss, i.e. |L_k - L_k+1|/max(|L_k|, |L_k+1|, 1), here the L_k and L_k+1 are with penalty items.
    reCh = 1

    # Under Cb and CT, compute the Lambda_beta and Lambda_bTheta
    LamT = LamTfn(CT, n, m, p)
    Lamb = Lambfn(Cb, n, m)

    # The log output, nothing to do with algorithm.
    if log >= 0:
        tb1 = PrettyTable(["Basic Value", "Lamb", "LamT"])
        tb1.add_row(["", f"{Lamb.item():>5.3g}", f"{LamT.item():>5.3g}"])
        print(tb1)
    # The loss, i.e. L +  Lamdab_bTheta * ||bTheta||
    Losses = []

    # Starting optimizing.
    for t in tqdm(range(MaxIters), desc="MNAR"):
        #--------------------------------------------------------------------------------
        # To get the number of nonzeros entry in betaOld
        NumN0Old = p - (betaOld.abs() == 0).sum().to(dtorchdtype)
        #--------------------------------------------------------------------------------
        # compute the loss function (with penalty items) under betaOld and bThetaOld

        # Compute L (without penalty items)
        LvNow = missdepL(bThetaOld, betaOld, f, X, Y, R, sXs)
        # Add L with penalty items.
        LossNow = missdepLR(LvNow, bThetaOld, betaOld, LamT, Lamb)
        QOld = (LossNow - Lcon) / Lamb
        Losses.append(LossNow.item())

        #--------------------------------------------------------------------------------
        # This block is to update beta.
        LpbvOld = missdepLpb(bThetaOld, betaOld, conDenfs, X, Y, R, sXs)
        # compute the learning rate of beta
        etabOld = etab  # 0.05 for linear setting
        betaNewRaw = betaOld - etabOld * LpbvOld
        # Using rho function to soften updated beta
        betaNew = SoftTO(betaNewRaw, etabOld * Lamb)

        #--------------------------------------------------------------------------------
        # To get the number of nonzeros entry in betaNew
        NumN0New = p - (betaNew.abs() == 0).sum().to(dtorchdtype)

        #--------------------------------------------------------------------------------
        # Update bTheta
        LpTvOld = missdepLpT(bThetaOld, betaNew, conDenfs, X, Y, R, sXs)
        LvNew = missdepL(bThetaOld, betaNew, f, X, Y, R, sXs)
        LossNew = missdepLR(LvNew, bThetaOld, betaNew, LamT, Lamb)
        ROld = (LossNew - Lcon) / LamT
        etaTOld = etaT  # 0.05 for linear setting
        #tmpmatrix = bThetaOld-LpTvOld*etaTOld
        #tmpmatarr = tmpmatrix.cpu().numpy()
        #U, S, VT = np.linalg.svd(tmpmatarr)
        #U, S, VT = torch.tensor(U), torch.tensor(S), torch.tensor(VT)
        #V = VT.t()
        svdres = torch.svd(bThetaOld - LpTvOld * etaTOld)
        U, S, V = svdres.U, svdres.S, svdres.V
        softS = (S - LamT * etaTOld).clamp_min(0)
        bThetaNew = U.matmul(torch.diag(softS)).matmul(V.t())

        #--------------------------------------------------------------------------------
        # compute the relative change of Loss
        if t >= 1:
            Lk1 = Losses[-1]
            Lk = Losses[-2]
            reCh = np.abs(Lk1 - Lk) / np.max(np.abs((Lk, Lk1, 1)))

        #--------------------------------------------------------------------------------
        # This block is for log output and Error save, nothing to do with the algorithm
        if ErrOpts:
            Likelis.append(LvNow.item())
            bThetahats.append(bThetaOld.norm().item())
            betahats.append(betaOld.norm().item())
        if log == 1:
            tb2 = PrettyTable(["Iteration", "etaT", "Loss"])
            tb2.add_row([
                f"{t+1:>6}/{MaxIters}", f"{etaTOld:>8.3g}",
                f"{Losses[-1]:>8.3f}"
            ])
            print(tb2)
        if log == 2:
            tb2 = PrettyTable([
                "Iter", "etaT", "etab", "Loss", "-lkd", "reCh", "betat Norm",
                "Thetat Norm", "beta diff Norm", "btheta diff Norm",
                "betat L0 norm"
            ])
            tb2.add_row([
                f"{t+1:>4}/{MaxIters}", f"{etaTOld:>3.3g}", f"{etabOld:>3.3g}",
                f"{Losses[-1]:>6.3f}", f"{LvNow.item():>2.1g}",
                f"{reCh:>6.4g}", f"{betaNew.norm().item():>2.1f}",
                f"{bThetaNew.norm().item():>2.1f}",
                f"{(betaOld-betaNew).norm().item():>6.3g}",
                f"{(bThetaOld-bThetaNew).norm().item():>6.3g}",
                f"{NumN0New.item()}"
            ])
            print(tb2)
        #--------------------------------------------------------------------------------
        # if reCh is smaller than tolerance, stop the loop
        if t >= 1:
            if (reCh < tol):
                break
        # if the difference of 2 consecutive bThetahat is smaller than tolerance, stop the loop
        if ((bThetaOld - bThetaNew).norm() < tolT) and (
            (betaOld - betaNew).norm() < tolb):
            break
        #--------------------------------------------------------------------------------
        # Change New to Old for starting next iteration
        #print(betaOld)
        #print(softS)
        betaOld, bThetaOld = betaNew, bThetaNew

#--------------------------------------------------------------------------------
    if ErrOpts:
        return betaOld, bThetaOld, t + 1, betahats, bThetahats, Likelis
    else:
        return betaOld, bThetaOld, t + 1
Example #15
0
 def set_weight(self, A, bias):
     U, S, V = torch.svd(A)
     self.B = torch.mm(U, torch.diag(S))
     self.V = V.t().contiguous()
     self.bias = bias.view(-1, 1)
    def train(self,
              dataloader,
              num_train_updates,
              val_dataloader=None,
              verbose=False):
        """
        Trains the dynamics model on data.
        Inputs: dataloader: torch DataLoader that returns batches of samples that can 
                            be indexed by 'x', 'u', and 'xp'
                num_train_updates: int specifying the number of gradient steps to take
                
                val_dataloader: torch DataLoader, a dataloader used for validation (optional)
                verbose: bool, whether to print training progress.
                
        Progress is logged to a tensorboard summary writer.
        
        Outputs: None. self.model is modified.
        """
        self.reset()
        config = self.model.config

        validation_freq = 100
        val_iters = 5

        print_freq = validation_freq if verbose else num_train_updates + 1

        eval_method = self.evaluate_sample_singlestep
        if config['multistep_training']:
            eval_method = self.evaluate_sample_multistep

        data_iter = iter(dataloader)

        with trange(num_train_updates,
                    disable=(not verbose or not config['tqdm'])) as pbar:
            for idx in pbar:
                try:
                    sample = next(data_iter)
                except StopIteration:
                    # reset data iter
                    data_iter = iter(dataloader)
                    sample = next(data_iter)

                self.total_train_itrs += 1

                self.optimizer.zero_grad()
                self.model.train()
                total_loss = eval_method(sample)

                # compute validation loss
                if idx % validation_freq == 0 and val_dataloader is not None:
                    total_loss_val = []

                    self.model.eval()
                    for k, val_sample in enumerate(val_dataloader):
                        total_loss_val.append(eval_method(val_sample))

                        if k == val_iters - 1:
                            total_nll_val = torch.stack(
                                total_loss_val).mean().detach().numpy()
                            self.writer.add_scalar('NLL/Val', total_nll_val,
                                                   self.train_step)
                            break

                # grad update on logp
                total_nll = total_loss
                total_nll.backward()

                nn.utils.clip_grad_norm_(self.model.parameters(),
                                         config['grad_clip_value'])
                self.optimizer.step()
                if config['learning_rate_decay']:
                    self.scheduler.step()

                self.model.sigma_scale = max(
                    1., self.model.sigma_scale * config['sigma_eps_annealing'])

                # ---- logging / summaries ------
                self.train_step += 1
                step = self.train_step

                # tensorboard logging
                self.writer.add_scalar('NLL/Train', total_nll.item(), step)

                if self.model.config['multistep_curriculum']:
                    curr_step = self.model.config['curriculum_step']
                    horizon = min(
                        self.model.config['data_horizon'],
                        int(np.floor(self.total_train_itrs / curr_step)) + 1)

                    self.writer.add_scalar('Evaluation_horizon', horizon, step)

                Q, Linv = self.model.prior_params()
                K = (Linv @ Q.unsqueeze(-1)).squeeze(-1)
                _, Linv_sig, _ = torch.svd(Linv)
                _, Q_sig, _ = torch.svd(Q)
                _, K_sig, _ = torch.svd(K)

                for dim in range(config['x_dim']):
                    self.writer.add_histogram('log_Linv' + str(dim) + '_sig',
                                              torch.log(Linv_sig[dim, :]),
                                              step)
                self.writer.add_histogram('Q_sig', Q_sig, step)
                self.writer.add_histogram('K_sig', K_sig, step)
                self.writer.add_histogram('sigma_eps_val',
                                          self.model.logSigEps, step)
                if config['learning_rate_decay']:
                    self.writer.add_scalar('learning_rate',
                                           self.scheduler.get_lr()[0], step)
                self.writer.add_scalar('sigma_eps_scale',
                                       self.model.sigma_scale, step)
                self.writer.add_scalar('kernel_bandwidth',
                                       self.model.length_scale, step)

                # tqdm logging
                logdict = {}
                logdict["tr_loss"] = total_nll.cpu().detach().numpy()
                if val_dataloader is not None:
                    logdict["val_loss"] = total_nll_val
                if config['learnable_bandwidth']:
                    logdict["bandwidth"] = self.model.length_scale.item()

                pbar.set_postfix(logdict)

                self.reset()
Example #17
0
def _nullspace(A):
    '''Compute the null space of A.
    Return the smallest singular value and the corresponding vector.
    '''
    u, s, vh = torch.svd(A)
    return s[..., -1], vh[..., -1]
Example #18
0
def pca(x: Tensor, k=2):
    "Compute PCA of `x` with `k` dimensions."
    x = x - torch.mean(x, 0)
    U, S, V = torch.svd(x.t())
    return torch.mm(x, U[:, :k])
Example #19
0
print(chw_img_data)

m = torch.randn(100, 10)
v = torch.randn(10)

# 内積
d = torch.dot(v, v)
print(d, "内積")
# 100×10の行列と長さ10のベクトルとの内積,結果は長さ100のベクトル
v2 = torch.mv(m, v)
print(v2)
# 行列積
m2 = torch.mm(m.t(), m)
print(m2)
# 特異値分解
u, s, v = torch.svd(m)  # u,vは直交行列,sは対角成分のみの正方行列.最小二乗法を解く,行列の近似,圧縮
print(u, s, v)

x = torch.randn(100, 3)
# 微分の変数として扱う場合はrequires_gradフラグをTrueにする
a = torch.tensor([1, 2, 3.], requires_grad=True)
print(a, "requires_gradフラグをTrue")
# 計算をすることで自動的に計算フラグが構築されていく
y = torch.mv(x, a)
print(y)  # 100個
o = y.sum()
print(o)
# 微分を実行する
print(o.backward())
# 解析解と比較
print(a.grad != x.sum(0))
Example #20
0
def cluster_loss(H, kloss, lmbda, batch_size):
    gram_matrix = (H.T @ H) / batch_size
    _, sv_2, _ = torch.svd(gram_matrix)
    sv = torch.sqrt(sv_2[:kloss])
    loss = torch.sum(sv)
    return lmbda * loss
Example #21
0
import torch
import time

m = torch.randn(100, 10)
v = torch.randn(10)
print(m.size())
print(v.size())

print('internal product')
d = torch.dot(v, v)
print(d)

print('product')
v2 = torch.mv(m, v)
print(v2.size())

print('matrix product')
m2 = torch.mm(m.t(), m)
print(m2.size())

start = time.time()
print('singular value decomposition')
u, s, v = torch.svd(m)
end = time.time()
print('elapsed_time:{0}'.format(end - start) + '[sec]')
print('with cpu: 0.00026488304138183594[sec]')
Example #22
0
def svd_wrapper(matrix, mode, ncomp, debug, verbose, usv=False,
                random_state=None, to_numpy=True):
    """ Wrapper for different SVD libraries (CPU and GPU). 
      
    Parameters
    ----------
    matrix : array_like, 2d
        2d input matrix.
    mode : {'lapack', 'arpack', 'eigen', 'randsvd', 'cupy', 'eigencupy',
            'randcupy', 'pytorch', 'eigenpytorch', 'randpytorch'}, str optional
        Switch for the SVD method/library to be used. ``lapack`` uses the LAPACK 
        linear algebra library through Numpy and it is the most conventional way 
        of computing the SVD (deterministic result computed on CPU). ``arpack`` 
        uses the ARPACK Fortran libraries accessible through Scipy (computation
        on CPU). ``eigen`` computes the singular vectors through the 
        eigendecomposition of the covariance M.M' (computation on CPU).
        ``randsvd`` uses the randomized_svd algorithm implemented in Sklearn 
        (computation on CPU). ``cupy`` uses the Cupy library for GPU computation
        of the SVD as in the LAPACK version. ``eigencupy`` offers the same 
        method as with the ``eigen`` option but on GPU (through Cupy). 
        ``randcupy`` is an adaptation f the randomized_svd algorithm, where all
        the computations are done on a GPU (through Cupy). ``pytorch`` uses the
        Pytorch library for GPU computation of the SVD. ``eigenpytorch`` offers
        the same method as with the ``eigen`` option but on GPU (through
        Pytorch). ``randpytorch`` is an adaptation of the randomized_svd
        algorithm, where all the linear algebra computations are done on a GPU
        (through Pytorch).
    ncomp : int
        Number of singular vectors to be obtained. In the cases when the full
        SVD is computed (LAPACK, ARPACK, EIGEN, CUPY), the matrix of singular 
        vectors is truncated. 
    debug : bool
        If True the explained variance ratio is computed and displayed.
    verbose: bool
        If True intermediate information is printed out.
    usv : bool optional
        If True the 3 terms of the SVD factorization are returned.
    random_state : int, RandomState instance or None, optional
        If int, random_state is the seed used by the random number generator.
        If RandomState instance, random_state is the random number generator.
        If None, the random number generator is the RandomState instance used
        by np.random. Used for ``randsvd`` mode.
    to_numpy : bool, optional
        If True (by default) the arrays computed in GPU are transferred from
        VRAM and converted to numpy ndarrays.

    Returns
    -------
    V : array_like
        The right singular vectors of the input matrix. If ``usv`` is True it
        returns the left and right singular vectors and the singular values of
        the input matrix.
    
    References
    ----------
    * For ``lapack`` SVD mode see:
        https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.linalg.svd.html
        http://www.netlib.org/lapack/
    * For ``eigen`` mode see:
        https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.linalg.eigh.html
    * For ``arpack`` SVD mode see:
        https://docs.scipy.org/doc/scipy-0.19.1/reference/generated/scipy.sparse.linalg.svds.html
        http://www.caam.rice.edu/software/ARPACK/
    * For ``randsvd`` SVD mode see:
        https://github.com/scikit-learn/scikit-learn/blob/master/sklearn/utils/extmath.py
        Finding structure with randomness: Stochastic algorithms for constructing
        approximate matrix decompositions
        Halko, et al., 2009 http://arxiv.org/abs/arXiv:0909.4061
    * For ``cupy`` SVD mode see:
        https://docs-cupy.chainer.org/en/stable/reference/generated/cupy.linalg.svd.html
    * For ``eigencupy`` mode see:
        https://docs-cupy.chainer.org/en/master/reference/generated/cupy.linalg.eigh.html
    * For ``pytorch`` SVD mode see:
        http://pytorch.org/docs/master/torch.html#torch.svd
    * For ``eigenpytorch`` mode see:
        http://pytorch.org/docs/master/torch.html#torch.eig

    """

    def reconstruction(ncomp, U, S, V, var=1):
        if mode == 'lapack':
            rec_matrix = np.dot(U[:, :ncomp],
                                np.dot(np.diag(S[:ncomp]), V[:ncomp]))
            rec_matrix = rec_matrix.T
            print('  Matrix reconstruction with {} PCs:'.format(ncomp))
            print('  Mean Absolute Error =', MAE(matrix, rec_matrix))
            print('  Mean Squared Error =', MSE(matrix, rec_matrix))

            # see https://github.com/scikit-learn/scikit-learn/blob/c3980bcbabd9d2527548820581725df2904e4a0d/sklearn/decomposition/pca.py
            exp_var = (S ** 2) / (S.shape[0] - 1)
            full_var = np.sum(exp_var)
            explained_variance_ratio = exp_var / full_var   # % of variance explained by each PC
            ratio_cumsum = np.cumsum(explained_variance_ratio)
        elif mode == 'eigen':
            exp_var = (S ** 2) / (S.shape[0] - 1)
            full_var = np.sum(exp_var)
            explained_variance_ratio = exp_var / full_var   # % of variance explained by each PC
            ratio_cumsum = np.cumsum(explained_variance_ratio)
        else:
            rec_matrix = np.dot(U, np.dot(np.diag(S), V))
            print('  Matrix reconstruction MAE =', MAE(matrix, rec_matrix))
            exp_var = (S ** 2) / (S.shape[0] - 1)
            full_var = np.var(matrix, axis=0).sum()
            explained_variance_ratio = exp_var / full_var   # % of variance explained by each PC
            if var == 1:
                pass
            else:
                explained_variance_ratio = explained_variance_ratio[::-1]
            ratio_cumsum = np.cumsum(explained_variance_ratio)
            msg = '  This info makes sense when the matrix is mean centered '
            msg += '(temp-mean scaling)'
            print(msg)

        lw = 2; alpha = 0.4
        fig = plt.figure(figsize=vip_figsize)
        fig.subplots_adjust(wspace=0.4)
        ax1 = plt.subplot2grid((1, 3), (0, 0), colspan=2)
        ax1.step(range(explained_variance_ratio.shape[0]),
                 explained_variance_ratio, alpha=alpha, where='mid',
                 label='Individual EVR', lw=lw)
        ax1.plot(ratio_cumsum, '.-', alpha=alpha,
                 label='Cumulative EVR', lw=lw)
        ax1.legend(loc='best', frameon=False, fontsize='medium')
        ax1.set_ylabel('Explained variance ratio (EVR)')
        ax1.set_xlabel('Principal components')
        ax1.grid(linestyle='solid', alpha=0.2)
        ax1.set_xlim(-10, explained_variance_ratio.shape[0] + 10)
        ax1.set_ylim(0, 1)

        trunc = 20
        ax2 = plt.subplot2grid((1, 3), (0, 2), colspan=1)
        # plt.setp(ax2.get_yticklabels(), visible=False)
        ax2.step(range(trunc), explained_variance_ratio[:trunc], alpha=alpha,
                 where='mid', lw=lw)
        ax2.plot(ratio_cumsum[:trunc], '.-', alpha=alpha, lw=lw)
        ax2.set_xlabel('Principal components')
        ax2.grid(linestyle='solid', alpha=0.2)
        ax2.set_xlim(-2, trunc + 2)
        ax2.set_ylim(0, 1)

        msg = '  Cumulative explained variance ratio for {} PCs = {:.5f}'
        # plt.savefig('figure.pdf', dpi=300, bbox_inches='tight')
        print(msg.format(ncomp, ratio_cumsum[ncomp - 1]))

    # --------------------------------------------------------------------------

    if matrix.ndim != 2:
        raise TypeError('Input matrix is not a 2d array')

    if usv:
        if mode not in ('lapack', 'arpack', 'randsvd', 'cupy', 'randcupy',
                        'pytorch', 'randpytorch'):
            msg = "Returning USV is supported with modes lapack, arpack, "
            msg += "randsvd, cupy, randcupy, pytorch or randpytorch"
            raise ValueError(msg)

    if ncomp > min(matrix.shape[0], matrix.shape[1]):
        msg = '{} PCs cannot be obtained from a matrix with size [{},{}].'
        msg += ' Increase the size of the patches or request less PCs'
        raise RuntimeError(msg.format(ncomp, matrix.shape[0], matrix.shape[1]))

    if mode == 'eigen':
        # building C as np.dot(matrix.T,matrix) is slower and takes more memory
        C = np.dot(matrix, matrix.T)        # covariance matrix
        e, EV = linalg.eigh(C)              # EVals and EVs
        pc = np.dot(EV.T, matrix)           # PCs using a compact trick when cov is MM'
        V = pc[::-1]                        # reverse since we need the last EVs
        S = np.sqrt(np.abs(e))              # SVals = sqrt(EVals)
        S = S[::-1]                         # reverse since EVals go in increasing order
        if debug:
            reconstruction(ncomp, None, S, None)
        for i in range(V.shape[1]):
            V[:, i] /= S                    # scaling EVs by the square root of EVals
        V = V[:ncomp]
        if verbose:
            print('Done PCA with numpy linalg eigh functions')

    elif mode == 'lapack':
        # n_frames is usually smaller than n_pixels. In this setting taking the SVD of M'
        # and keeping the left (transposed) SVs is faster than taking the SVD of M (right SVs)
        U, S, V = linalg.svd(matrix.T, full_matrices=False)
        if debug:
            reconstruction(ncomp, U, S, V)
        V = V[:ncomp]                       # we cut projection matrix according to the # of PCs
        U = U[:, :ncomp]
        S = S[:ncomp]
        if verbose:
            print('Done SVD/PCA with numpy SVD (LAPACK)')

    elif mode == 'arpack':
        U, S, V = svds(matrix, k=ncomp)
        if debug:
            reconstruction(ncomp, U, S, V, -1)
        if verbose:
            print('Done SVD/PCA with scipy sparse SVD (ARPACK)')

    elif mode == 'randsvd':
        U, S, V = randomized_svd(matrix, n_components=ncomp, n_iter=2,
                                 transpose='auto', random_state=random_state)
        if debug:
            reconstruction(ncomp, U, S, V)
        if verbose:
            print('Done SVD/PCA with randomized SVD')

    elif mode == 'cupy':
        if no_cupy:
            raise RuntimeError('Cupy is not installed')
        a_gpu = cupy.array(matrix)
        a_gpu = cupy.asarray(a_gpu)  # move the data to the current device
        u_gpu, s_gpu, vh_gpu = cupy.linalg.svd(a_gpu, full_matrices=True,
                                               compute_uv=True)
        V = vh_gpu[:ncomp]
        if to_numpy:
            V = cupy.asnumpy(V)
        if usv:
            S = s_gpu[:ncomp]
            if to_numpy:
                S = cupy.asnumpy(S)
            U = u_gpu[:, :ncomp]
            if to_numpy:
                U = cupy.asnumpy(U)
        if verbose:
            print('Done SVD/PCA with cupy (GPU)')

    elif mode == 'randcupy':
        if no_cupy:
            raise RuntimeError('Cupy is not installed')
        U, S, V = randomized_svd_gpu(matrix, ncomp, n_iter=2, lib='cupy')
        if to_numpy:
            V = cupy.asnumpy(V)
            S = cupy.asnumpy(S)
            U = cupy.asnumpy(U)
        if debug:
            reconstruction(ncomp, U, S, V)
        if verbose:
            print('Done randomized SVD/PCA with cupy (GPU)')

    elif mode == 'eigencupy':
        if no_cupy:
            raise RuntimeError('Cupy is not installed')
        a_gpu = cupy.array(matrix)
        a_gpu = cupy.asarray(a_gpu)         # move the data to the current device
        C = cupy.dot(a_gpu, a_gpu.T)        # covariance matrix
        e, EV = cupy.linalg.eigh(C)         # eigenvalues and eigenvectors
        pc = cupy.dot(EV.T, a_gpu)          # PCs using a compact trick when cov is MM'
        V = pc[::-1]                        # reverse since last eigenvectors are the ones we want
        S = cupy.sqrt(e)[::-1]              # reverse since eigenvalues are in increasing order
        if debug:
            reconstruction(ncomp, None, S, None)
        for i in range(V.shape[1]):
            V[:, i] /= S                    # scaling by the square root of eigenvalues
        V = V[:ncomp]
        if to_numpy:
            V = cupy.asnumpy(V)
        if verbose:
            print('Done PCA with cupy eigh function (GPU)')

    elif mode == 'pytorch':
        if no_torch:
            raise RuntimeError('Pytorch is not installed')
        a_gpu = torch.Tensor.cuda(torch.from_numpy(matrix.astype('float32').T))
        u_gpu, s_gpu, vh_gpu = torch.svd(a_gpu)
        V = vh_gpu[:ncomp]
        S = s_gpu[:ncomp]
        U = torch.transpose(u_gpu, 0, 1)[:ncomp]
        if to_numpy:
            V = np.array(V)
            S = np.array(S)
            U = np.array(U)
        if verbose:
            print('Done SVD/PCA with pytorch (GPU)')

    elif mode == 'eigenpytorch':
        if no_torch:
            raise RuntimeError('Pytorch is not installed')
        a_gpu = torch.Tensor.cuda(torch.from_numpy(matrix.astype('float32')))
        C = torch.mm(a_gpu, torch.transpose(a_gpu, 0, 1))
        e, EV = torch.eig(C, eigenvectors=True)
        V = torch.mm(torch.transpose(EV, 0, 1), a_gpu)
        S = torch.sqrt(e[:, 0])
        if debug:
            reconstruction(ncomp, None, S, None)
        for i in range(V.shape[1]):
            V[:, i] /= S
        V = V[:ncomp]
        if to_numpy:
            V = np.array(V)
        if verbose:
            print('Done PCA with pytorch eig function')

    elif mode == 'randpytorch':
        if no_torch:
            raise RuntimeError('Pytorch is not installed')
        U, S, V = randomized_svd_gpu(matrix, ncomp, n_iter=2, lib='pytorch')
        if to_numpy:
            V = np.array(V)
            S = np.array(S)
            U = np.array(U)
        if debug:
            reconstruction(ncomp, U, S, V)
        if verbose:
            print('Done randomized SVD/PCA with randomized pytorch (GPU)')

    else:
        raise ValueError('The SVD mode is not available')

    if usv:
        if mode == 'lapack':
            return V.T, S, U.T
        elif mode == 'pytorch':
            if to_numpy:
                return V.T, S, U.T
            else:
                return torch.transpose(V, 0, 1), S, torch.transpose(U, 0, 1)
        else:
            return U, S, V
    else:
        if mode == 'lapack':
            return U.T
        elif mode == 'pytorch':
            return U
        else:
            return V
Example #23
0
    def forward(self, features):
        # start_time = time.time()

        # features: NCWH
        k = features.size(0) * features.size(2) * features.size(3)
        x_mean = (features.sum(dim=2).sum(dim=2).sum(dim=0) /
                  k).unsqueeze(0).unsqueeze(2).unsqueeze(2)

        # print("1--- %s seconds ---" % (time.time() - start_time))
        # d = time.time()
        features = features - x_mean
        # print("2--- %s seconds ---" % (time.time() - d))
        # d = time.time()
        reshaped_features = features.view(features.size(0), features.size(1), -1)\
            .permute(1, 0, 2).contiguous().view(features.size(1), -1)

        cov = torch.matmul(reshaped_features, reshaped_features.t()) / k
        # print("3--- %s seconds ---" % (time.time() - d))
        # d = time.time()
        # print('cov',cov.shape)
        # eigval, eigvec = torch.eig(cov, eigenvectors=True)
        # print("4--- %s seconds ---" % (time.time() - d))
        d = time.time()
        _, _, eigvec = torch.svd(cov)
        # print("4s--- %s seconds ---" % (time.time() - d))
        # d = time.time()
        first_compo = eigvec[:, 0]

        first_projected_map = torch.matmul(first_compo.unsqueeze(0), reshaped_features).view(1, features.size(0), -1)\
            .view(features.size(0), features.size(2), features.size(3))
        # print("5--- %s seconds ---" % (time.time() - d))
        # d = time.time()

        first_maxv = first_projected_map.max()
        first_minv = first_projected_map.min()

        first_projected_map *= (
            first_maxv + first_minv) / torch.abs(first_maxv + first_minv)
        # print("6--- %s seconds ---" % (time.time() - d))
        # d = time.time()
        second_compo = eigvec[:, 1]

        second_projected_map = torch.matmul(second_compo.unsqueeze(0), reshaped_features).view(1, features.size(0), -1)\
            .view(features.size(0), features.size(2), features.size(3))

        second_maxv = second_projected_map.max()
        second_minv = second_projected_map.min()

        second_projected_map *= (
            second_maxv + second_minv) / torch.abs(second_maxv + second_minv)

        third_compo = eigvec[:, 2]

        third_projected_map = torch.matmul(third_compo.unsqueeze(0), reshaped_features).view(1, features.size(0), -1)\
        .view(features.size(0), features.size(2), features.size(3))

        third_maxv = third_projected_map.max()
        third_minv = third_projected_map.min()

        third_projected_map *= (
            third_maxv + third_minv) / torch.abs(third_maxv + third_minv)
        # print("7--- %s seconds ---" % (time.time() - d))
        # d = time.time()
        return [first_projected_map, second_projected_map, third_projected_map]
Example #24
0
def svd_wrapper(matrix, mode, ncomp, verbose, full_output=False,
                random_state=None, to_numpy=True):
    """ Wrapper for different SVD libraries (CPU and GPU). 
      
    Parameters
    ----------
    matrix : numpy ndarray, 2d
        2d input matrix.
    mode : {'lapack', 'arpack', 'eigen', 'randsvd', 'cupy', 'eigencupy',
        'randcupy', 'pytorch', 'eigenpytorch', 'randpytorch'}, str optional
        Switch for the SVD method/library to be used.

        ``lapack``: uses the LAPACK linear algebra library through Numpy
        and it is the most conventional way of computing the SVD
        (deterministic result computed on CPU).

        ``arpack``: uses the ARPACK Fortran libraries accessible through
        Scipy (computation on CPU).

        ``eigen``: computes the singular vectors through the
        eigendecomposition of the covariance M.M' (computation on CPU).

        ``randsvd``: uses the randomized_svd algorithm implemented in
        Sklearn (computation on CPU).

        ``cupy``: uses the Cupy library for GPU computation of the SVD as in
        the LAPACK version. `

        `eigencupy``: offers the same method as with the ``eigen`` option
        but on GPU (through Cupy).

        ``randcupy``: is an adaptation of the randomized_svd algorithm,
        where all the computations are done on a GPU (through Cupy). `

        `pytorch``: uses the Pytorch library for GPU computation of the SVD.

        ``eigenpytorch``: offers the same method as with the ``eigen``
        option but on GPU (through Pytorch).

        ``randpytorch``: is an adaptation of the randomized_svd algorithm,
        where all the linear algebra computations are done on a GPU
        (through Pytorch).

    ncomp : int
        Number of singular vectors to be obtained. In the cases when the full
        SVD is computed (LAPACK, ARPACK, EIGEN, CUPY), the matrix of singular 
        vectors is truncated.
    verbose: bool
        If True intermediate information is printed out.
    full_output : bool optional
        If True the 3 terms of the SVD factorization are returned. If ``mode``
        is eigen then only S and V are returned.
    random_state : int, RandomState instance or None, optional
        If int, random_state is the seed used by the random number generator.
        If RandomState instance, random_state is the random number generator.
        If None, the random number generator is the RandomState instance used
        by np.random. Used for ``randsvd`` mode.
    to_numpy : bool, optional
        If True (by default) the arrays computed in GPU are transferred from
        VRAM and converted to numpy ndarrays.

    Returns
    -------
    V : numpy ndarray
        The right singular vectors of the input matrix. If ``full_output`` is
        True it returns the left and right singular vectors and the singular
        values of the input matrix. If ``mode`` is set to eigen then only S and
        V are returned.
    
    References
    ----------
    * For ``lapack`` SVD mode see:
        https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.linalg.svd.html
        http://www.netlib.org/lapack/
    * For ``eigen`` mode see:
        https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.linalg.eigh.html
    * For ``arpack`` SVD mode see:
        https://docs.scipy.org/doc/scipy-0.19.1/reference/generated/scipy.sparse.linalg.svds.html
        http://www.caam.rice.edu/software/ARPACK/
    * For ``randsvd`` SVD mode see:
        https://github.com/scikit-learn/scikit-learn/blob/master/sklearn/utils/extmath.py
        Finding structure with randomness: Stochastic algorithms for constructing
        approximate matrix decompositions
        Halko, et al., 2009 http://arxiv.org/abs/arXiv:0909.4061
    * For ``cupy`` SVD mode see:
        https://docs-cupy.chainer.org/en/stable/reference/generated/cupy.linalg.svd.html
    * For ``eigencupy`` mode see:
        https://docs-cupy.chainer.org/en/master/reference/generated/cupy.linalg.eigh.html
    * For ``pytorch`` SVD mode see:
        http://pytorch.org/docs/master/torch.html#torch.svd
    * For ``eigenpytorch`` mode see:
        http://pytorch.org/docs/master/torch.html#torch.eig

    """
    if matrix.ndim != 2:
        raise TypeError('Input matrix is not a 2d array')

    if ncomp > min(matrix.shape[0], matrix.shape[1]):
        msg = '{} PCs cannot be obtained from a matrix with size [{},{}].'
        msg += ' Increase the size of the patches or request less PCs'
        raise RuntimeError(msg.format(ncomp, matrix.shape[0], matrix.shape[1]))

    if mode == 'eigen':
        # building C as np.dot(matrix.T,matrix) is slower and takes more memory
        C = np.dot(matrix, matrix.T)    # covariance matrix
        e, EV = linalg.eigh(C)          # EVals and EVs
        pc = np.dot(EV.T, matrix)       # PCs using a compact trick when cov is MM'
        V = pc[::-1]                    # reverse since we need the last EVs
        S = np.sqrt(np.abs(e))          # SVals = sqrt(EVals)
        S = S[::-1]                     # reverse since EVals go in increasing order
        for i in range(V.shape[1]):
            V[:, i] /= S    # scaling EVs by the square root of EVals
        V = V[:ncomp]
        if verbose:
            print('Done PCA with numpy linalg eigh functions')

    elif mode == 'lapack':
        # n_frames is usually smaller than n_pixels. In this setting taking
        # the SVD of M' and keeping the left (transposed) SVs is faster than
        # taking the SVD of M (right SVs)
        U, S, V = linalg.svd(matrix.T, full_matrices=False)
        V = V[:ncomp]       # we cut projection matrix according to the # of PCs
        U = U[:, :ncomp]
        S = S[:ncomp]
        if verbose:
            print('Done SVD/PCA with numpy SVD (LAPACK)')

    elif mode == 'arpack':
        U, S, V = svds(matrix, k=ncomp)
        if verbose:
            print('Done SVD/PCA with scipy sparse SVD (ARPACK)')

    elif mode == 'randsvd':
        U, S, V = randomized_svd(matrix, n_components=ncomp, n_iter=2,
                                 transpose='auto', random_state=random_state)
        if verbose:
            print('Done SVD/PCA with randomized SVD')

    elif mode == 'cupy':
        if no_cupy:
            raise RuntimeError('Cupy is not installed')
        a_gpu = cupy.array(matrix)
        a_gpu = cupy.asarray(a_gpu)  # move the data to the current device
        u_gpu, s_gpu, vh_gpu = cupy.linalg.svd(a_gpu, full_matrices=True,
                                               compute_uv=True)
        V = vh_gpu[:ncomp]
        if to_numpy:
            V = cupy.asnumpy(V)
        if full_output:
            S = s_gpu[:ncomp]
            if to_numpy:
                S = cupy.asnumpy(S)
            U = u_gpu[:, :ncomp]
            if to_numpy:
                U = cupy.asnumpy(U)
        if verbose:
            print('Done SVD/PCA with cupy (GPU)')

    elif mode == 'randcupy':
        if no_cupy:
            raise RuntimeError('Cupy is not installed')
        U, S, V = randomized_svd_gpu(matrix, ncomp, n_iter=2, lib='cupy')
        if to_numpy:
            V = cupy.asnumpy(V)
            S = cupy.asnumpy(S)
            U = cupy.asnumpy(U)
        if verbose:
            print('Done randomized SVD/PCA with cupy (GPU)')

    elif mode == 'eigencupy':
        if no_cupy:
            raise RuntimeError('Cupy is not installed')
        a_gpu = cupy.array(matrix)
        a_gpu = cupy.asarray(a_gpu)     # move the data to the current device
        C = cupy.dot(a_gpu, a_gpu.T)    # covariance matrix
        e, EV = cupy.linalg.eigh(C)     # eigenvalues and eigenvectors
        pc = cupy.dot(EV.T, a_gpu)      # using a compact trick when cov is MM'
        V = pc[::-1]                    # reverse to get last eigenvectors
        S = cupy.sqrt(e)[::-1]          # reverse since EVals go in increasing order
        for i in range(V.shape[1]):
            V[:, i] /= S                # scaling by the square root of eigvals
        V = V[:ncomp]
        if to_numpy:
            V = cupy.asnumpy(V)
        if verbose:
            print('Done PCA with cupy eigh function (GPU)')

    elif mode == 'pytorch':
        if no_torch:
            raise RuntimeError('Pytorch is not installed')
        a_gpu = torch.Tensor.cuda(torch.from_numpy(matrix.astype('float32').T))
        u_gpu, s_gpu, vh_gpu = torch.svd(a_gpu)
        V = vh_gpu[:ncomp]
        S = s_gpu[:ncomp]
        U = torch.transpose(u_gpu, 0, 1)[:ncomp]
        if to_numpy:
            V = np.array(V)
            S = np.array(S)
            U = np.array(U)
        if verbose:
            print('Done SVD/PCA with pytorch (GPU)')

    elif mode == 'eigenpytorch':
        if no_torch:
            raise RuntimeError('Pytorch is not installed')
        a_gpu = torch.Tensor.cuda(torch.from_numpy(matrix.astype('float32')))
        C = torch.mm(a_gpu, torch.transpose(a_gpu, 0, 1))
        e, EV = torch.eig(C, eigenvectors=True)
        V = torch.mm(torch.transpose(EV, 0, 1), a_gpu)
        S = torch.sqrt(e[:, 0])
        for i in range(V.shape[1]):
            V[:, i] /= S
        V = V[:ncomp]
        if to_numpy:
            V = np.array(V)
        if verbose:
            print('Done PCA with pytorch eig function')

    elif mode == 'randpytorch':
        if no_torch:
            raise RuntimeError('Pytorch is not installed')
        U, S, V = randomized_svd_gpu(matrix, ncomp, n_iter=2, lib='pytorch')
        if to_numpy:
            V = np.array(V)
            S = np.array(S)
            U = np.array(U)
        if verbose:
            print('Done randomized SVD/PCA with randomized pytorch (GPU)')

    else:
        raise ValueError('The SVD `mode` is not recognized')

    if full_output:
        if mode == 'lapack':
            return V.T, S, U.T
        elif mode == 'pytorch':
            if to_numpy:
                return V.T, S, U.T
            else:
                return torch.transpose(V, 0, 1), S, torch.transpose(U, 0, 1)
        elif mode in ('eigen', 'eigencupy', 'eigenpytorch'):
            return S, V
        else:
            return U, S, V
    else:
        if mode == 'lapack':
            return U.T
        elif mode == 'pytorch':
            return U
        else:
            return V
def EVBMF(Y, sigma2=None, H=None):
    """Implementation of the analytical solution to Empirical Variational Bayes Matrix Factorization.

    This function can be used to calculate the analytical solution to empirical VBMF.
    This is based on the paper and MatLab code by Nakajima et al.:
    "Global analytic solution of fully-observed variational Bayesian matrix factorization."

    Notes
    -----
        If sigma2 is unspecified, it is estimated by minimizing the free energy.
        If H is unspecified, it is set to the smallest of the sides of the input Y.

    Attributes
    ----------
    Y : numpy-array
        Input matrix that is to be factorized. Y has shape (L,M), where L<=M.

    sigma2 : int or None (default=None)
        Variance of the noise on Y.

    H : int or None (default = None)
        Maximum rank of the factorized matrices.

    Returns
    -------
    U : numpy-array
        Left-singular vectors.

    S : numpy-array
        Diagonal matrix of singular values.

    V : numpy-array
        Right-singular vectors.

    post : dictionary
        Dictionary containing the computed posterior values.


    References
    ----------
    .. [1] Nakajima, Shinichi, et al. "Global analytic solution of fully-observed variational Bayesian matrix factorization." Journal of Machine Learning Research 14.Jan (2013): 1-37.

    .. [2] Nakajima, Shinichi, et al. "Perfect dimensionality recovery by variational Bayesian PCA." Advances in Neural Information Processing Systems. 2012.
    """
    L, M = Y.shape  # has to be L<=M

    if H is None:
        H = L

    alpha = L / M
    tauubar = 2.5129 * np.sqrt(alpha)

    # SVD of the input matrix, max rank of H
    U, s, V = torch.svd(Y)
    U = U[:, :H]
    s = s[:H]
    V[:H].t_()

    # Calculate residual
    residual = 0.
    if H < L:
        residual = torch.sum(torch.sum(Y**2) - torch.sum(s**2))

    # Estimation of the variance when sigma2 is unspecified
    if sigma2 is None:
        xubar = (1 + tauubar) * (1 + alpha / tauubar)
        eH_ub = int(np.min([np.ceil(L / (1 + alpha)) - 1, H])) - 1
        upper_bound = (torch.sum(s**2) + residual) / (L * M)
        upper_bound = upper_bound.item()
        lower_bound = np.max(
            [s[eH_ub + 1]**2 / (M * xubar),
             torch.mean(s[eH_ub + 1:]**2) / M])
        scale = 1.  # /lower_bound
        s = s * np.sqrt(scale)
        residual = residual * scale
        lower_bound = lower_bound * scale
        upper_bound = upper_bound * scale
        sigma2_opt = minimize_scalar(EVBsigma2,
                                     args=(L, M, s, residual, xubar),
                                     bounds=[lower_bound, upper_bound],
                                     method='Bounded')
        sigma2 = sigma2_opt.x

    # Threshold gamma term
    threshold = np.sqrt(M * sigma2 * (1 + tauubar) * (1 + alpha / tauubar))

    pos = torch.sum(s > threshold)
    if pos == 0:
        return np.array([])

    # Formula (15) from [2]
    d = torch.mul(
        s[:pos] / 2, 1 - (L + M) * sigma2 / s[:pos]**2 +
        torch.sqrt((1 - ((L + M) * sigma2) / s[:pos]**2)**2 -
                   (4 * L * M * sigma2**2) / s[:pos]**4))

    return torch.diag(d)
Example #26
0
def main():
    cfg.configure(args)
    cfg.print_config()
    torch.set_num_threads(args.omp_cores)
    torch.manual_seed(args.seed)

    if args.c4v_type == "TI":
        model = jq.JQ_C4V(j1=args.j1, q=args.q)
    elif args.c4v_type == "BIPARTITE":
        model = jq.JQ_C4V_BIPARTITE(j1=args.j1, q=args.q)
    elif args.c4v_type == "PLAQUETTE":
        q_inter = args.q if args.q_inter is None else args.q_inter
        model = jq.JQ_C4V_PLAQUETTE(j1=args.j1, q=args.q, q_inter=q_inter)
    else:
        raise ValueError("Unsupported C4v ansatz: -c4v_type= "\
            +str(args.ipeps_init_type)+" is not supported")

    # initialize an ipeps
    # 1) define lattice-tiling function, that maps arbitrary vertex of square lattice
    # coord into one of coordinates within unit-cell of iPEPS ansatz

    if args.instate != None:
        state = read_ipeps_c4v(args.instate)
        if args.bond_dim > max(state.get_aux_bond_dims()):
            # extend the auxiliary dimensions
            state = extend_bond_dim(state, args.bond_dim)
        state.add_noise(args.instate_noise)
        state.sites[(0, 0)] = state.sites[(0, 0)] / torch.max(
            torch.abs(state.sites[(0, 0)]))
    elif args.ipeps_init_type == 'RANDOM':
        bond_dim = args.bond_dim
        A= torch.rand((model.phys_dim, bond_dim, bond_dim, bond_dim, bond_dim),\
            dtype=cfg.global_args.dtype,device=cfg.global_args.device)
        A = make_c4v_symm(A)
        A = A / torch.max(torch.abs(A))
        state = IPEPS_C4V(A)
    else:
        raise ValueError("Missing trial state: -instate=None and -ipeps_init_type= "\
            +str(args.ipeps_init_type)+" is not supported")

    print(state)

    def ctmrg_conv_energy(state, env, history, ctm_args=cfg.ctm_args):
        with torch.no_grad():
            if not history:
                history = []
            e_curr = model.energy_1x1(state, env)
            obs_values, obs_labels = model.eval_obs(state, env)
            history.append([e_curr.item()] + obs_values)
            print(", ".join([f"{len(history)}", f"{e_curr}"] +
                            [f"{v}" for v in obs_values]))

            if len(history) > 1 and abs(
                    history[-1][0] - history[-2][0]) < ctm_args.ctm_conv_tol:
                return True, history
        return False, history

    ctm_env_init = ENV_C4V(args.chi, state)
    init_env(state, ctm_env_init)
    print(ctm_env_init)

    e_curr0 = model.energy_1x1(state, ctm_env_init)
    obs_values0, obs_labels = model.eval_obs(state, ctm_env_init)

    print(", ".join(["epoch", "energy"] + obs_labels))
    print(", ".join([f"{-1}", f"{e_curr0}"] + [f"{v}" for v in obs_values0]))

    ctm_env_init, *ctm_log = ctmrg_c4v.run(state,
                                           ctm_env_init,
                                           conv_check=ctmrg_conv_energy)

    corrSS = model.eval_corrf_SS(state, ctm_env_init, args.corrf_r)
    print("\n\nSS r " + " ".join([label for label in corrSS.keys()]))
    for i in range(args.corrf_r):
        print(f"{i} " +
              " ".join([f"{corrSS[label][i]}" for label in corrSS.keys()]))

    corrDD = model.eval_corrf_DD_H(state, ctm_env_init, args.corrf_r)
    print("\n\nDD r " + " ".join([label for label in corrDD.keys()]))
    for i in range(args.corrf_r):
        print(f"{i} " +
              " ".join([f"{corrDD[label][i]}" for label in corrDD.keys()]))

    corrDD_V = model.eval_corrf_DD_V(state, ctm_env_init, args.corrf_r)
    print("\n\nDD_V r " + " ".join([label for label in corrDD_V.keys()]))
    for i in range(args.corrf_r):
        print(f"{i} " +
              " ".join([f"{corrDD_V[label][i]}" for label in corrDD_V.keys()]))

    # environment diagnostics
    print("\n\nspectrum(C)")
    u, s, v = torch.svd(ctm_env_init.C[ctm_env_init.keyC], compute_uv=False)
    for i in range(args.chi):
        print(f"{i} {s[i]}")

    # transfer operator spectrum
    print("\n\nspectrum(T)")
    l = transferops_c4v.get_Top_spec_c4v(args.top_n, state, ctm_env_init)
    for i in range(l.size()[0]):
        print(f"{i} {l[i,0]} {l[i,1]}")
Example #27
0
def show_low_rank(model,
                  look_up_table=[],
                  input_size=None,
                  criterion=None,
                  type='NC'):

    redundancy = OrderedDict()
    comp_rate = OrderedDict()

    if input_size is not None:
        if isinstance(input_size, int):
            input_size = [input_size, input_size]
        elif isinstance(input_size, list):
            pass
        else:
            raise Exception

    if criterion is None:
        raise Exception('criterion must be set for sigma selection')

    if input_size is None:
        raise Exception('invalid input size')

    origin_FLOPs = 0.
    decouple_FLOPs = 0.

    channels_ = []

    for name, m in model.named_modules():

        if not isinstance(m, nn.Conv2d):
            continue

        p = m.weight.data
        dim = p.size()
        FLOPs = dim[0] * dim[1] * dim[2] * dim[3]

        if name in look_up_table:
            if args.stride_1_only:
                print('Skipping those not with stride 1')
                if not m.stride == (1, 1):
                    continue

            if type == 'NC':
                NC = p.view(dim[0], -1)
                N, sigma, C = torch.svd(NC, some=True)
                item_num = criterion(sigma)
                print(item_num)
                channels_.append(item_num)
                new_FLOPs = dim[1] * dim[2] * dim[
                    3] * item_num + item_num * dim[0]
            elif type == 'VH':
                VH = p.permute(1, 2, 0,
                               3).contiguous().view(dim[1] * dim[2], -1)
                V, sigma, H = torch.svd(VH, some=True)
                item_num = criterion(sigma)
                new_FLOPs = dim[1] * item_num * dim[2] + dim[
                    0] * item_num * dim[3]
            else:
                valid_idx = []
                for i in range(dim[0]):
                    W = p[i, :, :, :].view(dim[1], -1)
                    U, sigma, V = torch.svd(W, some=True)
                    valid_idx.append(criterion(sigma))
                item_num = min(max(valid_idx), min(dim[1], dim[2] * dim[3]))
                new_FLOPs = (dim[0] * dim[1] +
                             dim[0] * dim[2] * dim[3]) * item_num

            rate = float(new_FLOPs) / FLOPs

            comp_rate[name] = ('%.3f' % (rate))
        else:
            new_FLOPs = FLOPs

        if 'downsample' not in name:
            # a special case for resnet
            output_h = input_size[0] / m.stride[0]
            output_w = input_size[1] / m.stride[1]
        else:
            output_h = input_size[0]
            output_w = input_size[1]

        origin_FLOPs += FLOPs * output_h * output_w
        decouple_FLOPs += new_FLOPs * output_h * output_w
        input_size = [output_h, output_w]

    r = origin_FLOPs / decouple_FLOPs
    if DEBUG:
        print(comp_rate)
        print('\n')
        print('comp rate:')
        print(r)

    return r, channels_
Example #28
0
        x_torch = utils.convert_into_at_least_2d_pytorch_tensor(
            x).requires_grad_().to(self.device)
        J_torch = self.J_torch(x_torch)
        return J_torch.cpu().detach().numpy()


if __name__ == "__main__":
    rand_seed = 47
    np.random.seed(rand_seed)
    torch.random.manual_seed(rand_seed)

    dfeat = DummyDifferentiableFeature()
    x = np.random.rand(2, 5)
    print("x = ")
    print(x)
    J = dfeat.J(x)
    print("J = ")
    print(J)
    J_torch = utils.convert_into_at_least_2d_pytorch_tensor(
        J).requires_grad_().to('cpu')
    [J_svd_U_torch, J_svd_s_torch, J_svd_V_torch] = torch.svd(J_torch,
                                                              some=True)
    print("J_svd_U_torch = ", J_svd_U_torch)
    print("J_svd_s_torch = ", J_svd_s_torch)
    print("J_svd_V_torch = ", J_svd_V_torch)
    # print("J_svd_U_torch @ J_svd_U_torch.transpose() = ", J_svd_U_torch @ J_svd_U_torch.transpose(-2, -1))
    # print("J_svd_U_torch.transpose() @ J_svd_U_torch = ", J_svd_U_torch.transpose(-2, -1) @ J_svd_U_torch)
    # print("J_svd_V_torch @ J_svd_V_torch.transpose() = ", J_svd_V_torch @ J_svd_V_torch.transpose(-2, -1))
    # print("J_svd_V_torch.transpose() @ J_svd_V_torch = ", J_svd_V_torch.transpose(-2, -1) @ J_svd_V_torch)
    # print("det(J_svd_U_torch) = ", torch.det(J_svd_U_torch))
Example #29
0
def low_rank_approx(model, look_up_table, criterion, use_trp, type='NC'):
    dict2 = model.state_dict()
    sub = dict()
    #can set m here
    for name in dict2:
        param = dict2[name]
        dim = param.size()

        model_name = name[:-7] if len(dim) == 4 else ''

        if len(dim) == 4 and model_name in look_up_table:
            if type == 'VH':
                VH = param.permute(1, 2, 0,
                                   3).contiguous().view(dim[1] * dim[2], -1)
                try:
                    V, sigma, H = torch.svd(VH, some=True)
                    # print(sigma.size())
                    H = H.t()
                    # remain large singular value
                    valid_idx = criterion(sigma)
                    V = V[:, :valid_idx].contiguous()
                    sigma = sigma[:valid_idx]
                    dia = torch.diag(sigma)
                    H = H[:valid_idx, :]
                    if use_trp:
                        new_VH = (V.mm(dia)).mm(H)
                        new_VH = new_VH.contiguous().view(
                            dim[1], dim[2], dim[0],
                            dim[3]).permute(2, 0, 1, 3)
                        dict2[name].copy_(new_VH)
                    subgradient = torch.mm(V, H)
                    subgradient = subgradient.contiguous().view(
                        dim[1], dim[2], dim[0], dim[3]).permute(2, 0, 1, 3)
                    sub[model_name] = subgradient
                except:
                    sub[model_name] = 0.0
                    dict2[name].copy_(param)
            elif type == 'NC':
                NC = param.contiguous().view(dim[0], -1)
                try:
                    N, sigma, C = torch.svd(NC, some=True)
                    # print(sigma.size())
                    C = C.t()
                    # remain large singular value
                    valid_idx = criterion(sigma)
                    N = N[:, :valid_idx].contiguous()
                    sigma = sigma[:valid_idx]
                    dia = torch.diag(sigma)
                    C = C[:valid_idx, :]
                    if use_trp:
                        new_NC = (N.mm(dia)).mm(C)
                        new_NC = new_NC.contiguous().view(
                            dim[0], dim[1], dim[2], dim[3])
                        dict2[name].copy_(new_NC)
                    # this the gradient step
                    subgradient = torch.mm(N, C)
                    subgradient = subgradient.contiguous().view(
                        dim[0], dim[1], dim[2], dim[3])
                    sub[model_name] = subgradient
                except:
                    sub[model_name] = 0.0
                    dict2[name].copy_(param)
            else:
                # network decouple approximation
                tmp = param.clone()
                tmp_sub = param.clone()
                valid_idx = 0

                for i in range(dim[0]):
                    W = param[i, :, :, :].view(dim[1], -1)
                    try:
                        U, sigma, V = torch.svd(W, some=True)
                        V = V.t()
                        valid_idx = criterion(sigma)
                        U = U[:, :valid_idx].contiguous()
                        V = V[:valid_idx, :].contiguous()
                        sigma = sigma[:valid_idx]
                        dia = torch.diag(sigma)
                        if use_trp:
                            new_W = (U.mm(dia)).mm(V)
                            new_W = new_W.contiguous().view(
                                dim[1], dim[2], dim[3])
                            tmp[i, :, :, :] = new_W[...]
                        subgradient = torch.mm(U, V)
                        subgradient = subgradient.contiguous().view(
                            dim[1], dim[2], dim[3])
                        tmp_sub[i, :, :, :] = subgradient[...]
                    except Exception as e:
                        print(e)
                        tmp_sub[i, :, :, :] = 0.0
                        tmp[i, :, :, :] = param[i, :, :, :]

                dict2[name].copy_(tmp)
                sub[model_name] = tmp_sub
        else:
            dict2[name].copy_(param)
    model.load_state_dict(dict2)

    return model, sub
    torch.manual_seed(0)
    with torch.no_grad():
        print('Generating teacher outputs')
        for i, (images, _) in enumerate(trainLoader):
            images = Variable(images)
            images = images.cuda()

            _, student_activation = model.forward(images, True)
            curr_output, curr_activations = teacherModel.forward(images, True)
            student_activations.append(student_activation)
            teacher_outputs.append(curr_output)
            teacher_activations.append(curr_activations)
        student_activations = torch.cat(student_activations)
        teacher_outputs = torch.cat(teacher_outputs)
        teacher_activations = torch.cat(teacher_activations)
        train_svd = torch.svd(teacher_activations)
        teacher_Us = train_svd.U
        # we use eos_scale to scale the EOS loss during training, so that the same
        # learning rates that were good for MSE loss are also good for EOS loss.
        eos_scale = torch.norm(teacher_activations) / torch.norm(teacher_Us)
        print('Done!')

    # train!
    torch.manual_seed(0)
    bestAcc = 0.0
    for epoch in range(1, args.epochs):
        train(epoch)
        acc = eval_training(epoch)

        if epoch > args.warm:
            train_scheduler.step()
Example #31
0
def spectral_normalize(tensor: Tensor) -> Tensor:
    u, s, v = torch.svd(tensor, compute_uv=False)
    norm = torch.max(s)
    return tensor / norm
Example #32
0
 def func():
   torch.svd(torch.rand((N, N)))
Example #33
0
def procrustes(X_source, X_target):
    """min |X_source Q - X_target|_F s.t. Q^TQ = I"""
    U, _, V = torch.svd(X_target.T @ X_source)
    return V @ U.T
Example #34
0
 def reset_parameters(self):
     torch.nn.init.xavier_uniform_(self.A)
     u, s, v = torch.svd(self.A)
     self.A.data = u.matmul(v.t())
def SubspaceNetHead(query,
                    support,
                    support_labels,
                    n_way,
                    n_shot,
                    normalize=True):
    """
       Constructs the subspace representation of each class(=mean of support vectors of each class) and
       returns the classification score (=L2 distance to each class prototype) on the query set.

        Our algorithm using subspaces here

       Parameters:
         query:  a (tasks_per_batch, n_query, d) Tensor.
         support:  a (tasks_per_batch, n_support, d) Tensor.
         support_labels: a (tasks_per_batch, n_support) Tensor.
         n_way: a scalar. Represents the number of classes in a few-shot classification task.
         n_shot: a scalar. Represents the number of support examples given per class.
         normalize: a boolean. Represents whether if we want to normalize the distances by the embedding dimension.
       Returns: a (tasks_per_batch, n_query, n_way) Tensor.
       """

    tasks_per_batch = query.size(0)
    n_support = support.size(1)
    n_query = query.size(1)
    d = query.size(2)

    assert (query.dim() == 3)
    assert (support.dim() == 3)
    assert (query.size(0) == support.size(0)
            and query.size(2) == support.size(2))
    assert (n_support == n_way * n_shot
            )  # n_support must equal to n_way * n_shot

    support_labels_one_hot = one_hot(
        support_labels.view(tasks_per_batch * n_support), n_way)
    #support_labels_one_hot = support_labels_one_hot.view(tasks_per_batch, n_support, n_way)

    support_reshape = support.view(tasks_per_batch * n_support, -1)

    support_labels_reshaped = support_labels.contiguous().view(-1)
    class_representatives = []
    for nn in range(n_way):
        idxss = (support_labels_reshaped == nn).nonzero()
        all_support_perclass = support_reshape[idxss, :]
        class_representatives.append(
            all_support_perclass.view(tasks_per_batch, n_shot, -1))

    class_representatives = torch.stack(class_representatives)
    class_representatives = class_representatives.transpose(
        0, 1)  #tasks_per_batch, n_way, n_support, -1
    class_representatives = class_representatives.transpose(
        2, 3).contiguous().view(tasks_per_batch * n_way, -1, n_shot)

    dist = []
    for cc in range(tasks_per_batch * n_way):
        batch_idx = cc // n_way
        qq = query[batch_idx]
        uu, _, _ = torch.svd(class_representatives[cc].double())
        uu = uu.float()
        subspace = uu[:, :n_shot - 1].transpose(0, 1)
        projection = subspace.transpose(0, 1).mm(
            subspace.mm(qq.transpose(0, 1))).transpose(0, 1)
        dist_perclass = torch.sum((qq - projection)**2, dim=-1)
        dist.append(dist_perclass)

    dist = torch.stack(dist).view(tasks_per_batch, n_way, -1).transpose(1, 2)
    logits = -dist

    if normalize:
        logits = logits / d

    return logits
Example #36
0
File: svd.py Project: regran/VIP
def svd_wrapper(matrix,
                mode,
                ncomp,
                debug,
                verbose,
                usv=False,
                random_state=None,
                to_numpy=True):
    """ Wrapper for different SVD libraries (CPU and GPU). 
      
    Parameters
    ----------
    matrix : array_like, 2d
        2d input matrix.
    mode : {'lapack', 'arpack', 'eigen', 'randsvd', 'cupy', 'eigencupy',
            'randcupy', 'pytorch', 'eigenpytorch', 'randpytorch'}, str optional
        Switch for the SVD method/library to be used. ``lapack`` uses the LAPACK 
        linear algebra library through Numpy and it is the most conventional way 
        of computing the SVD (deterministic result computed on CPU). ``arpack`` 
        uses the ARPACK Fortran libraries accessible through Scipy (computation
        on CPU). ``eigen`` computes the singular vectors through the 
        eigendecomposition of the covariance M.M' (computation on CPU).
        ``randsvd`` uses the randomized_svd algorithm implemented in Sklearn 
        (computation on CPU). ``cupy`` uses the Cupy library for GPU computation
        of the SVD as in the LAPACK version. ``eigencupy`` offers the same 
        method as with the ``eigen`` option but on GPU (through Cupy). 
        ``randcupy`` is an adaptation f the randomized_svd algorithm, where all
        the computations are done on a GPU (through Cupy). ``pytorch`` uses the
        Pytorch library for GPU computation of the SVD. ``eigenpytorch`` offers
        the same method as with the ``eigen`` option but on GPU (through
        Pytorch). ``randpytorch`` is an adaptation of the randomized_svd
        algorithm, where all the linear algebra computations are done on a GPU
        (through Pytorch).
    ncomp : int
        Number of singular vectors to be obtained. In the cases when the full
        SVD is computed (LAPACK, ARPACK, EIGEN, CUPY), the matrix of singular 
        vectors is truncated. 
    debug : bool
        If True the explained variance ratio is computed and displayed.
    verbose: bool
        If True intermediate information is printed out.
    usv : bool optional
        If True the 3 terms of the SVD factorization are returned.
    random_state : int, RandomState instance or None, optional
        If int, random_state is the seed used by the random number generator.
        If RandomState instance, random_state is the random number generator.
        If None, the random number generator is the RandomState instance used
        by np.random. Used for ``randsvd`` mode.
    to_numpy : bool, optional
        If True (by default) the arrays computed in GPU are transferred from
        VRAM and converted to numpy ndarrays.

    Returns
    -------
    V : array_like
        The right singular vectors of the input matrix. If ``usv`` is True it
        returns the left and right singular vectors and the singular values of
        the input matrix.
    
    References
    ----------
    * For ``lapack`` SVD mode see:
        https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.linalg.svd.html
        http://www.netlib.org/lapack/
    * For ``eigen`` mode see:
        https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.linalg.eigh.html
    * For ``arpack`` SVD mode see:
        https://docs.scipy.org/doc/scipy-0.19.1/reference/generated/scipy.sparse.linalg.svds.html
        http://www.caam.rice.edu/software/ARPACK/
    * For ``randsvd`` SVD mode see:
        https://github.com/scikit-learn/scikit-learn/blob/master/sklearn/utils/extmath.py
        Finding structure with randomness: Stochastic algorithms for constructing
        approximate matrix decompositions
        Halko, et al., 2009 http://arxiv.org/abs/arXiv:0909.4061
    * For ``cupy`` SVD mode see:
        https://docs-cupy.chainer.org/en/stable/reference/generated/cupy.linalg.svd.html
    * For ``eigencupy`` mode see:
        https://docs-cupy.chainer.org/en/master/reference/generated/cupy.linalg.eigh.html
    * For ``pytorch`` SVD mode see:
        http://pytorch.org/docs/master/torch.html#torch.svd
    * For ``eigenpytorch`` mode see:
        http://pytorch.org/docs/master/torch.html#torch.eig

    """
    def reconstruction(ncomp, U, S, V, var=1):
        if mode == 'lapack':
            rec_matrix = np.dot(U[:, :ncomp],
                                np.dot(np.diag(S[:ncomp]), V[:ncomp]))
            rec_matrix = rec_matrix.T
            print('  Matrix reconstruction with {} PCs:'.format(ncomp))
            print('  Mean Absolute Error =', MAE(matrix, rec_matrix))
            print('  Mean Squared Error =', MSE(matrix, rec_matrix))

            # see https://github.com/scikit-learn/scikit-learn/blob/c3980bcbabd9d2527548820581725df2904e4a0d/sklearn/decomposition/pca.py
            exp_var = (S**2) / (S.shape[0] - 1)
            full_var = np.sum(exp_var)
            explained_variance_ratio = exp_var / full_var  # % of variance explained by each PC
            ratio_cumsum = np.cumsum(explained_variance_ratio)
        elif mode == 'eigen':
            exp_var = (S**2) / (S.shape[0] - 1)
            full_var = np.sum(exp_var)
            explained_variance_ratio = exp_var / full_var  # % of variance explained by each PC
            ratio_cumsum = np.cumsum(explained_variance_ratio)
        else:
            rec_matrix = np.dot(U, np.dot(np.diag(S), V))
            print('  Matrix reconstruction MAE =', MAE(matrix, rec_matrix))
            exp_var = (S**2) / (S.shape[0] - 1)
            full_var = np.var(matrix, axis=0).sum()
            explained_variance_ratio = exp_var / full_var  # % of variance explained by each PC
            if var == 1:
                pass
            else:
                explained_variance_ratio = explained_variance_ratio[::-1]
            ratio_cumsum = np.cumsum(explained_variance_ratio)
            msg = '  This info makes sense when the matrix is mean centered '
            msg += '(temp-mean scaling)'
            print(msg)

        lw = 2
        alpha = 0.4
        fig = plt.figure(figsize=vip_figsize)
        fig.subplots_adjust(wspace=0.4)
        ax1 = plt.subplot2grid((1, 3), (0, 0), colspan=2)
        ax1.step(range(explained_variance_ratio.shape[0]),
                 explained_variance_ratio,
                 alpha=alpha,
                 where='mid',
                 label='Individual EVR',
                 lw=lw)
        ax1.plot(ratio_cumsum,
                 '.-',
                 alpha=alpha,
                 label='Cumulative EVR',
                 lw=lw)
        ax1.legend(loc='best', frameon=False, fontsize='medium')
        ax1.set_ylabel('Explained variance ratio (EVR)')
        ax1.set_xlabel('Principal components')
        ax1.grid(linestyle='solid', alpha=0.2)
        ax1.set_xlim(-10, explained_variance_ratio.shape[0] + 10)
        ax1.set_ylim(0, 1)

        trunc = 20
        ax2 = plt.subplot2grid((1, 3), (0, 2), colspan=1)
        # plt.setp(ax2.get_yticklabels(), visible=False)
        ax2.step(range(trunc),
                 explained_variance_ratio[:trunc],
                 alpha=alpha,
                 where='mid',
                 lw=lw)
        ax2.plot(ratio_cumsum[:trunc], '.-', alpha=alpha, lw=lw)
        ax2.set_xlabel('Principal components')
        ax2.grid(linestyle='solid', alpha=0.2)
        ax2.set_xlim(-2, trunc + 2)
        ax2.set_ylim(0, 1)

        msg = '  Cumulative explained variance ratio for {} PCs = {:.5f}'
        # plt.savefig('figure.pdf', dpi=300, bbox_inches='tight')
        print(msg.format(ncomp, ratio_cumsum[ncomp - 1]))

    # --------------------------------------------------------------------------

    if matrix.ndim != 2:
        raise TypeError('Input matrix is not a 2d array')

    if usv:
        if mode not in ('lapack', 'arpack', 'randsvd', 'cupy', 'randcupy',
                        'pytorch', 'randpytorch'):
            msg = "Returning USV is supported with modes lapack, arpack, "
            msg += "randsvd, cupy, randcupy, pytorch or randpytorch"
            raise ValueError(msg)

    if ncomp > min(matrix.shape[0], matrix.shape[1]):
        msg = '{} PCs cannot be obtained from a matrix with size [{},{}].'
        msg += ' Increase the size of the patches or request less PCs'
        raise RuntimeError(msg.format(ncomp, matrix.shape[0], matrix.shape[1]))

    if mode == 'eigen':
        # building the covariance as np.dot(matrix.T,matrix) is slower and takes more memory
        C = np.dot(matrix, matrix.T)  # covariance matrix
        e, EV = linalg.eigh(C)  # eigenvalues and eigenvectors
        pc = np.dot(EV.T, matrix)  # PCs using a compact trick when cov is MM'
        V = pc[::-1]  # reverse since last eigenvectors are the ones we want
        S = np.sqrt(e)[::
                       -1]  # reverse since eigenvalues are in increasing order
        if debug:
            reconstruction(ncomp, None, S, None)
        for i in range(V.shape[1]):
            V[:, i] /= S  # scaling by the square root of eigenvalues
        V = V[:ncomp]
        if verbose:
            print('Done PCA with numpy linalg eigh functions')

    elif mode == 'lapack':
        # n_frames is usually smaller than n_pixels. In this setting taking the SVD of M'
        # and keeping the left (transposed) SVs is faster than taking the SVD of M (right SVs)
        U, S, V = linalg.svd(matrix.T, full_matrices=False)
        if debug:
            reconstruction(ncomp, U, S, V)
        V = V[:ncomp]  # we cut projection matrix according to the # of PCs
        U = U[:, :ncomp]
        S = S[:ncomp]
        if verbose:
            print('Done SVD/PCA with numpy SVD (LAPACK)')

    elif mode == 'arpack':
        U, S, V = svds(matrix, k=ncomp)
        if debug:
            reconstruction(ncomp, U, S, V, -1)
        if verbose:
            print('Done SVD/PCA with scipy sparse SVD (ARPACK)')

    elif mode == 'randsvd':
        U, S, V = randomized_svd(matrix,
                                 n_components=ncomp,
                                 n_iter=2,
                                 transpose='auto',
                                 random_state=random_state)
        if debug:
            reconstruction(ncomp, U, S, V)
        if verbose:
            print('Done SVD/PCA with randomized SVD')

    elif mode == 'cupy':
        if no_cupy:
            raise RuntimeError('Cupy is not installed')
        a_gpu = cupy.array(matrix)
        a_gpu = cupy.asarray(a_gpu)  # move the data to the current device
        u_gpu, s_gpu, vh_gpu = cupy.linalg.svd(a_gpu,
                                               full_matrices=True,
                                               compute_uv=True)
        V = vh_gpu[:ncomp]
        if to_numpy:
            V = cupy.asnumpy(V)
        if usv:
            S = s_gpu[:ncomp]
            if to_numpy:
                S = cupy.asnumpy(S)
            U = u_gpu[:, :ncomp]
            if to_numpy:
                U = cupy.asnumpy(U)
        if verbose:
            print('Done SVD/PCA with cupy (GPU)')

    elif mode == 'randcupy':
        if no_cupy:
            raise RuntimeError('Cupy is not installed')
        U, S, V = randomized_svd_gpu(matrix, ncomp, n_iter=2, lib='cupy')
        if to_numpy:
            V = cupy.asnumpy(V)
            S = cupy.asnumpy(S)
            U = cupy.asnumpy(U)
        if debug:
            reconstruction(ncomp, U, S, V)
        if verbose:
            print('Done randomized SVD/PCA with cupy (GPU)')

    elif mode == 'eigencupy':
        if no_cupy:
            raise RuntimeError('Cupy is not installed')
        a_gpu = cupy.array(matrix)
        a_gpu = cupy.asarray(a_gpu)  # move the data to the current device
        C = cupy.dot(a_gpu, a_gpu.T)  # covariance matrix
        e, EV = cupy.linalg.eigh(C)  # eigenvalues and eigenvectors
        pc = cupy.dot(EV.T, a_gpu)  # PCs using a compact trick when cov is MM'
        V = pc[::-1]  # reverse since last eigenvectors are the ones we want
        S = cupy.sqrt(
            e)[::-1]  # reverse since eigenvalues are in increasing order
        if debug:
            reconstruction(ncomp, None, S, None)
        for i in range(V.shape[1]):
            V[:, i] /= S  # scaling by the square root of eigenvalues
        V = V[:ncomp]
        if to_numpy:
            V = cupy.asnumpy(V)
        if verbose:
            print('Done PCA with cupy eigh function (GPU)')

    elif mode == 'pytorch':
        if no_torch:
            raise RuntimeError('Pytorch is not installed')
        a_gpu = torch.Tensor.cuda(torch.from_numpy(matrix.astype('float32').T))
        u_gpu, s_gpu, vh_gpu = torch.svd(a_gpu)
        V = vh_gpu[:ncomp]
        S = s_gpu[:ncomp]
        U = torch.transpose(u_gpu, 0, 1)[:ncomp]
        if to_numpy:
            V = np.array(V)
            S = np.array(S)
            U = np.array(U)
        if verbose:
            print('Done SVD/PCA with pytorch (GPU)')

    elif mode == 'eigenpytorch':
        if no_torch:
            raise RuntimeError('Pytorch is not installed')
        a_gpu = torch.Tensor.cuda(torch.from_numpy(matrix.astype('float32')))
        C = torch.mm(a_gpu, torch.transpose(a_gpu, 0, 1))
        e, EV = torch.eig(C, eigenvectors=True)
        V = torch.mm(torch.transpose(EV, 0, 1), a_gpu)
        S = torch.sqrt(e[:, 0])
        if debug:
            reconstruction(ncomp, None, S, None)
        for i in range(V.shape[1]):
            V[:, i] /= S
        V = V[:ncomp]
        if to_numpy:
            V = np.array(V)
        if verbose:
            print('Done PCA with pytorch eig function')

    elif mode == 'randpytorch':
        if no_torch:
            raise RuntimeError('Pytorch is not installed')
        U, S, V = randomized_svd_gpu(matrix, ncomp, n_iter=2, lib='pytorch')
        if to_numpy:
            V = np.array(V)
            S = np.array(S)
            U = np.array(U)
        if debug:
            reconstruction(ncomp, U, S, V)
        if verbose:
            print('Done randomized SVD/PCA with randomized pytorch (GPU)')

    else:
        raise ValueError('The SVD mode is not available')

    if usv:
        if mode == 'lapack':
            return V.T, S, U.T
        elif mode == 'pytorch':
            if to_numpy:
                return V.T, S, U.T
            else:
                return torch.transpose(V, 0, 1), S, torch.transpose(U, 0, 1)
        else:
            return U, S, V
    else:
        if mode == 'lapack':
            return U.T
        elif mode == 'pytorch':
            return U
        else:
            return V
Example #37
0
def BNM(logits, lw=1):
    A = torch.softmax(logits, dim=1)
    _, s_tgt, _ = torch.svd(A)
    loss_bnm = -torch.mean(s_tgt)
    return loss_bnm * lw
Example #38
0
File: svd.py Project: carlgogo/VIP
def svd_wrapper(matrix, mode, ncomp, verbose, full_output=False,
                random_state=None, to_numpy=True):
    """ Wrapper for different SVD libraries (CPU and GPU). 
      
    Parameters
    ----------
    matrix : numpy ndarray, 2d
        2d input matrix.
    mode : {'lapack', 'arpack', 'eigen', 'randsvd', 'cupy', 'eigencupy',
        'randcupy', 'pytorch', 'eigenpytorch', 'randpytorch'}, str optional
        Switch for the SVD method/library to be used.

        ``lapack``: uses the LAPACK linear algebra library through Numpy
        and it is the most conventional way of computing the SVD
        (deterministic result computed on CPU).

        ``arpack``: uses the ARPACK Fortran libraries accessible through
        Scipy (computation on CPU).

        ``eigen``: computes the singular vectors through the
        eigendecomposition of the covariance M.M' (computation on CPU).

        ``randsvd``: uses the randomized_svd algorithm implemented in
        Sklearn (computation on CPU).

        ``cupy``: uses the Cupy library for GPU computation of the SVD as in
        the LAPACK version. `

        `eigencupy``: offers the same method as with the ``eigen`` option
        but on GPU (through Cupy).

        ``randcupy``: is an adaptation of the randomized_svd algorithm,
        where all the computations are done on a GPU (through Cupy). `

        `pytorch``: uses the Pytorch library for GPU computation of the SVD.

        ``eigenpytorch``: offers the same method as with the ``eigen``
        option but on GPU (through Pytorch).

        ``randpytorch``: is an adaptation of the randomized_svd algorithm,
        where all the linear algebra computations are done on a GPU
        (through Pytorch).

    ncomp : int
        Number of singular vectors to be obtained. In the cases when the full
        SVD is computed (LAPACK, ARPACK, EIGEN, CUPY), the matrix of singular 
        vectors is truncated.
    verbose: bool
        If True intermediate information is printed out.
    full_output : bool optional
        If True the 3 terms of the SVD factorization are returned. If ``mode``
        is eigen then only S and V are returned.
    random_state : int, RandomState instance or None, optional
        If int, random_state is the seed used by the random number generator.
        If RandomState instance, random_state is the random number generator.
        If None, the random number generator is the RandomState instance used
        by np.random. Used for ``randsvd`` mode.
    to_numpy : bool, optional
        If True (by default) the arrays computed in GPU are transferred from
        VRAM and converted to numpy ndarrays.

    Returns
    -------
    V : numpy ndarray
        The right singular vectors of the input matrix. If ``full_output`` is
        True it returns the left and right singular vectors and the singular
        values of the input matrix. If ``mode`` is set to eigen then only S and
        V are returned.
    
    References
    ----------
    * For ``lapack`` SVD mode see:
        https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.linalg.svd.html
        http://www.netlib.org/lapack/
    * For ``eigen`` mode see:
        https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.linalg.eigh.html
    * For ``arpack`` SVD mode see:
        https://docs.scipy.org/doc/scipy-0.19.1/reference/generated/scipy.sparse.linalg.svds.html
        http://www.caam.rice.edu/software/ARPACK/
    * For ``randsvd`` SVD mode see:
        https://github.com/scikit-learn/scikit-learn/blob/master/sklearn/utils/extmath.py
        Finding structure with randomness: Stochastic algorithms for constructing
        approximate matrix decompositions
        Halko, et al., 2009 http://arxiv.org/abs/arXiv:0909.4061
    * For ``cupy`` SVD mode see:
        https://docs-cupy.chainer.org/en/stable/reference/generated/cupy.linalg.svd.html
    * For ``eigencupy`` mode see:
        https://docs-cupy.chainer.org/en/master/reference/generated/cupy.linalg.eigh.html
    * For ``pytorch`` SVD mode see:
        http://pytorch.org/docs/master/torch.html#torch.svd
    * For ``eigenpytorch`` mode see:
        http://pytorch.org/docs/master/torch.html#torch.eig

    """
    if matrix.ndim != 2:
        raise TypeError('Input matrix is not a 2d array')

    if ncomp > min(matrix.shape[0], matrix.shape[1]):
        msg = '{} PCs cannot be obtained from a matrix with size [{},{}].'
        msg += ' Increase the size of the patches or request less PCs'
        raise RuntimeError(msg.format(ncomp, matrix.shape[0], matrix.shape[1]))

    if mode == 'eigen':
        # building C as np.dot(matrix.T,matrix) is slower and takes more memory
        C = np.dot(matrix, matrix.T)    # covariance matrix
        e, EV = linalg.eigh(C)          # EVals and EVs
        pc = np.dot(EV.T, matrix)       # PCs using a compact trick when cov is MM'
        V = pc[::-1]                    # reverse since we need the last EVs
        S = np.sqrt(np.abs(e))          # SVals = sqrt(EVals)
        S = S[::-1]                     # reverse since EVals go in increasing order
        for i in range(V.shape[1]):
            V[:, i] /= S    # scaling EVs by the square root of EVals
        V = V[:ncomp]
        if verbose:
            print('Done PCA with numpy linalg eigh functions')

    elif mode == 'lapack':
        # n_frames is usually smaller than n_pixels. In this setting taking
        # the SVD of M' and keeping the left (transposed) SVs is faster than
        # taking the SVD of M (right SVs)
        U, S, V = linalg.svd(matrix.T, full_matrices=False)
        V = V[:ncomp]       # we cut projection matrix according to the # of PCs
        U = U[:, :ncomp]
        S = S[:ncomp]
        if verbose:
            print('Done SVD/PCA with numpy SVD (LAPACK)')

    elif mode == 'arpack':
        U, S, V = svds(matrix, k=ncomp)
        if verbose:
            print('Done SVD/PCA with scipy sparse SVD (ARPACK)')

    elif mode == 'randsvd':
        U, S, V = randomized_svd(matrix, n_components=ncomp, n_iter=2,
                                 transpose='auto', random_state=random_state)
        if verbose:
            print('Done SVD/PCA with randomized SVD')

    elif mode == 'cupy':
        if no_cupy:
            raise RuntimeError('Cupy is not installed')
        a_gpu = cupy.array(matrix)
        a_gpu = cupy.asarray(a_gpu)  # move the data to the current device
        u_gpu, s_gpu, vh_gpu = cupy.linalg.svd(a_gpu, full_matrices=True,
                                               compute_uv=True)
        V = vh_gpu[:ncomp]
        if to_numpy:
            V = cupy.asnumpy(V)
        if full_output:
            S = s_gpu[:ncomp]
            if to_numpy:
                S = cupy.asnumpy(S)
            U = u_gpu[:, :ncomp]
            if to_numpy:
                U = cupy.asnumpy(U)
        if verbose:
            print('Done SVD/PCA with cupy (GPU)')

    elif mode == 'randcupy':
        if no_cupy:
            raise RuntimeError('Cupy is not installed')
        U, S, V = randomized_svd_gpu(matrix, ncomp, n_iter=2, lib='cupy')
        if to_numpy:
            V = cupy.asnumpy(V)
            S = cupy.asnumpy(S)
            U = cupy.asnumpy(U)
        if verbose:
            print('Done randomized SVD/PCA with cupy (GPU)')

    elif mode == 'eigencupy':
        if no_cupy:
            raise RuntimeError('Cupy is not installed')
        a_gpu = cupy.array(matrix)
        a_gpu = cupy.asarray(a_gpu)     # move the data to the current device
        C = cupy.dot(a_gpu, a_gpu.T)    # covariance matrix
        e, EV = cupy.linalg.eigh(C)     # eigenvalues and eigenvectors
        pc = cupy.dot(EV.T, a_gpu)      # using a compact trick when cov is MM'
        V = pc[::-1]                    # reverse to get last eigenvectors
        S = cupy.sqrt(e)[::-1]          # reverse since EVals go in increasing order
        for i in range(V.shape[1]):
            V[:, i] /= S                # scaling by the square root of eigvals
        V = V[:ncomp]
        if to_numpy:
            V = cupy.asnumpy(V)
        if verbose:
            print('Done PCA with cupy eigh function (GPU)')

    elif mode == 'pytorch':
        if no_torch:
            raise RuntimeError('Pytorch is not installed')
        a_gpu = torch.Tensor.cuda(torch.from_numpy(matrix.astype('float32').T))
        u_gpu, s_gpu, vh_gpu = torch.svd(a_gpu)
        V = vh_gpu[:ncomp]
        S = s_gpu[:ncomp]
        U = torch.transpose(u_gpu, 0, 1)[:ncomp]
        if to_numpy:
            V = np.array(V)
            S = np.array(S)
            U = np.array(U)
        if verbose:
            print('Done SVD/PCA with pytorch (GPU)')

    elif mode == 'eigenpytorch':
        if no_torch:
            raise RuntimeError('Pytorch is not installed')
        a_gpu = torch.Tensor.cuda(torch.from_numpy(matrix.astype('float32')))
        C = torch.mm(a_gpu, torch.transpose(a_gpu, 0, 1))
        e, EV = torch.eig(C, eigenvectors=True)
        V = torch.mm(torch.transpose(EV, 0, 1), a_gpu)
        S = torch.sqrt(e[:, 0])
        for i in range(V.shape[1]):
            V[:, i] /= S
        V = V[:ncomp]
        if to_numpy:
            V = np.array(V)
        if verbose:
            print('Done PCA with pytorch eig function')

    elif mode == 'randpytorch':
        if no_torch:
            raise RuntimeError('Pytorch is not installed')
        U, S, V = randomized_svd_gpu(matrix, ncomp, n_iter=2, lib='pytorch')
        if to_numpy:
            V = np.array(V)
            S = np.array(S)
            U = np.array(U)
        if verbose:
            print('Done randomized SVD/PCA with randomized pytorch (GPU)')

    else:
        raise ValueError('The SVD `mode` is not recognized')

    if full_output:
        if mode == 'lapack':
            return V.T, S, U.T
        elif mode == 'pytorch':
            if to_numpy:
                return V.T, S, U.T
            else:
                return torch.transpose(V, 0, 1), S, torch.transpose(U, 0, 1)
        elif mode in ('eigen', 'eigencupy', 'eigenpytorch'):
            return S, V
        else:
            return U, S, V
    else:
        if mode == 'lapack':
            return U.T
        elif mode == 'pytorch':
            return U
        else:
            return V
Example #39
0
path='model/'+str(nn_mass) +'_'+str((100 * float(correct) / total))+'.pt'
torch.save(model_raw, path)



frac=np.linspace(start=0.9, stop=1.1, num = 101)


loss_log=np.zeros([101,101])
#print(model_new.features[0].weight)
for i in range(101):
    for j in range(101):
        model_new = torch.load(path)
        for x in model_new.features:
            u,sig,v=torch.svd(x.weight)
            sig[0]=sig[0]*frac[i]
            sig[1]=sig[1]*frac[j]
            tmp=torch.matmul(u,torch.diag(sig))
            tmp_v=torch.transpose(v,0,1)
            tmp=torch.matmul(tmp,tmp_v)
            x.weight.data=tmp
        #print(model_new.features[0].weight)
        correct = 0
        total = 0
        predicted_label=torch.zeros(test_num)


        image = Variable(test_data)
        label = Variable(test_label)
        outputs = model_new(image)
Example #40
0
def randomized_svd_gpu(M, n_components, n_oversamples=10, n_iter='auto',
                       transpose='auto', random_state=0, lib='cupy'):
    """Computes a truncated randomized SVD on GPU. Adapted from Sklearn.

    Parameters
    ----------
    M : ndarray or sparse matrix
        Matrix to decompose
    n_components : int
        Number of singular values and vectors to extract.
    n_oversamples : int (default is 10)
        Additional number of random vectors to sample the range of M so as
        to ensure proper conditioning. The total number of random vectors
        used to find the range of M is n_components + n_oversamples. Smaller
        number can improve speed but can negatively impact the quality of
        approximation of singular vectors and singular values.
    n_iter : int or 'auto' (default is 'auto')
        Number of power iterations. It can be used to deal with very noisy
        problems. When 'auto', it is set to 4, unless `n_components` is small
        (< .1 * min(X.shape)) `n_iter` in which case is set to 7.
        This improves precision with few components.
    transpose : True, False or 'auto' (default)
        Whether the algorithm should be applied to M.T instead of M. The
        result should approximately be the same. The 'auto' mode will
        trigger the transposition if M.shape[1] > M.shape[0] since this
        implementation of randomized SVD tend to be a little faster in that
        case.
    random_state : int, RandomState instance or None, optional (default=None)
        The seed of the pseudo random number generator to use when shuffling
        the data.  If int, random_state is the seed used by the random number
        generator; If RandomState instance, random_state is the random number
        generator; If None, the random number generator is the RandomState
        instance used by `np.random`.
    lib : {'cupy', 'pytorch'}, str optional
        Chooses the GPU library to be used.

    Notes
    -----
    This algorithm finds a (usually very good) approximate truncated
    singular value decomposition using randomization to speed up the
    computations. It is particularly fast on large matrices on which
    you wish to extract only a small number of components. In order to
    obtain further speed up, `n_iter` can be set <=2 (at the cost of
    loss of precision).

    References
    ----------
    * Finding structure with randomness: Stochastic algorithms for constructing
      approximate matrix decompositions
      Halko, et al., 2009 http://arxiv.org/abs/arXiv:0909.4061
    * A randomized algorithm for the decomposition of matrices
      Per-Gunnar Martinsson, Vladimir Rokhlin and Mark Tygert
    * An implementation of a randomized algorithm for principal component
      analysis
      A. Szlam et al. 2014
    """
    random_state = check_random_state(random_state)
    n_random = n_components + n_oversamples
    n_samples, n_features = M.shape

    if n_iter == 'auto':
        # Checks if the number of iterations is explicitly specified
        n_iter = 7 if n_components < .1 * min(M.shape) else 4

    if transpose == 'auto':
        transpose = n_samples < n_features
    if transpose:
        M = M.T # this implementation is a bit faster with smaller shape[1]

    if lib == 'cupy':
        M = cupy.array(M)
        M = cupy.asarray(M)

        # Generating normal random vectors with shape: (M.shape[1], n_random)
        Q = random_state.normal(size=(M.shape[1], n_random))
        Q = cupy.array(Q)
        Q = cupy.asarray(Q)

        # Perform power iterations with Q to further 'imprint' the top
        # singular vectors of M in Q
        for i in range(n_iter):
            Q = cupy.dot(M, Q)
            Q = cupy.dot(M.T, Q)

        # Sample the range of M using by linear projection of Q. Extract an orthonormal basis
        Q, _ = cupy.linalg.qr(cupy.dot(M, Q), mode='reduced')

        # project M to the (k + p) dimensional space using the basis vectors
        B = cupy.dot(Q.T, M)

        B = cupy.array(B)
        Q = cupy.array(Q)
        # compute the SVD on the thin matrix: (k + p) wide
        Uhat, s, V = cupy.linalg.svd(B, full_matrices=False, compute_uv=True)
        del B
        U = cupy.dot(Q, Uhat)

        if transpose:
            # transpose back the results according to the input convention
            return V[:n_components, :].T, s[:n_components], U[:,
                                                            :n_components].T
        else:
            return U[:, :n_components], s[:n_components], V[:n_components, :]

    elif lib == 'pytorch':
        M_gpu = torch.Tensor.cuda(torch.from_numpy(M.astype('float32')))

        # Generating normal random vectors with shape: (M.shape[1], n_random)
        Q = torch.cuda.FloatTensor(M_gpu.shape[1], n_random).normal_()

        # Perform power iterations with Q to further 'imprint' the top
        # singular vectors of M in Q
        for i in range(n_iter):
            Q = torch.mm(M_gpu, Q)
            Q = torch.mm(torch.transpose(M_gpu, 0, 1), Q)

        # Sample the range of M using by linear projection of Q. Extract an orthonormal basis
        Q, _ = torch.qr(torch.mm(M_gpu, Q))

        # project M to the (k + p) dimensional space using the basis vectors
        B = torch.mm(torch.transpose(Q, 0, 1), M_gpu)

        # compute the SVD on the thin matrix: (k + p) wide
        Uhat, s, V = torch.svd(B)
        del B
        U = torch.mm(Q, Uhat)

        if transpose:
            # transpose back the results according to the input convention
            return (torch.transpose(V[:n_components, :], 0, 1),
                    s[:n_components],
                    torch.transpose(U[:, :n_components], 0, 1))
        else:
            return U[:, :n_components], s[:n_components], V[:n_components, :]
Example #41
0
def main():
    cfg.configure(args)
    cfg.print_config()
    torch.set_num_threads(args.omp_cores)
    torch.manual_seed(args.seed)

    model= j1j2.J1J2_C4V_BIPARTITE(j1=args.j1, j2=args.j2, j3=args.j3, \
        hz_stag=args.hz_stag, delta_zz=args.delta_zz)
    energy_f = model.energy_1x1_lowmem
    # energy_f= model.energy_1x1_tiled
    # energy_f= model.energy_1x1

    # initialize an ipeps
    if args.instate != None:
        state = read_ipeps_u1(args.instate, vertexToSite=None)
        assert len(state.coeffs) == 1, "Not a 1-site ipeps"
        state.add_noise(args.instate_noise)
    elif args.opt_resume is not None:
        if args.bond_dim in [2, 3, 4, 5, 6, 7, 8]:
            u1sym_t= tenU1.import_sym_tensors(2,args.bond_dim,"A_1",\
                infile=f"u1sym/D{args.bond_dim}_U1_{args.u1_class}.txt",\
                dtype=cfg.global_args.torch_dtype, device=cfg.global_args.device)
        else:
            raise ValueError("Unsupported --bond_dim= " + str(args.bond_dim))
        A = torch.zeros(len(u1sym_t),
                        dtype=cfg.global_args.torch_dtype,
                        device=cfg.global_args.device)
        coeffs = {(0, 0): A}
        state = IPEPS_U1SYM(u1sym_t, coeffs)
        state.load_checkpoint(args.opt_resume)
    elif args.ipeps_init_type == 'RANDOM':
        if args.bond_dim in [2, 3, 4, 5, 6, 7, 8]:
            u1sym_t= tenU1.import_sym_tensors(2, args.bond_dim, "A_1", \
                infile=f"u1sym/D{args.bond_dim}_U1_{args.u1_class}.txt", \
                dtype=cfg.global_args.torch_dtype, device=cfg.global_args.device)
        else:
            raise ValueError("Unsupported --bond_dim= " + str(args.bond_dim))
        A = torch.rand(len(u1sym_t),
                       dtype=cfg.global_args.torch_dtype,
                       device=cfg.global_args.device)
        A = A / torch.max(torch.abs(A))
        coeffs = {(0, 0): A}
        state = IPEPS_U1SYM(u1sym_t, coeffs)
    else:
        raise ValueError("Missing trial state: -instate=None and -ipeps_init_type= "\
            +str(args.ipeps_init_type)+" is not supported")

    print(state)

    @torch.no_grad()
    def ctmrg_conv_rdm2x1(state, env, history, ctm_args=cfg.ctm_args):
        if not history:
            history = dict({"log": []})
        rdm2x1 = rdm2x1_sl(state, env, force_cpu=ctm_args.conv_check_cpu)
        dist = float('inf')
        if len(history["log"]) > 1:
            dist = torch.dist(rdm2x1, history["rdm"], p=2).item()
        # log dist and observables
        if args.obs_freq>0 and \
            (len(history["log"])%args.obs_freq==0 or
            (len(history["log"])-1)%args.obs_freq==0):
            e_curr = energy_f(state, env, force_cpu=ctm_args.conv_check_cpu)
            obs_values, obs_labels = model.eval_obs(state, env, force_cpu=True)
            print(
                ", ".join([f"{len(history['log'])}", f"{dist}", f"{e_curr}"] +
                          [f"{v}" for v in obs_values]))
        else:
            print(f"{len(history['log'])}, {dist}")
        # update history
        history["rdm"] = rdm2x1
        history["log"].append(dist)

        converged = dist < ctm_args.ctm_conv_tol
        if converged or len(history['log']) >= ctm_args.ctm_max_iter:
            log.info({
                "history_length": len(history['log']),
                "history": history['log'],
                "final_multiplets": compute_multiplets(env)
            })
            return converged, history
        return False, history

    ctm_env_init = ENV_C4V(args.chi, state)
    init_env(state, ctm_env_init)

    e_curr0 = energy_f(state, ctm_env_init, force_cpu=True)
    obs_values0, obs_labels = model.eval_obs(state,
                                             ctm_env_init,
                                             force_cpu=True)
    print(", ".join(["epoch", "energy"] + obs_labels))
    print(", ".join([f"{-1}", f"{e_curr0}"] + [f"{v}" for v in obs_values0]))

    ctm_env_init, *ctm_log = ctmrg_c4v.run(state, ctm_env_init, \
        conv_check=ctmrg_conv_rdm2x1)

    e_curr0 = energy_f(state, ctm_env_init, force_cpu=True)
    obs_values0, obs_labels = model.eval_obs(state,
                                             ctm_env_init,
                                             force_cpu=True)
    history, t_ctm, t_obs = ctm_log
    print("\n")
    print(", ".join(["epoch", "energy"] + obs_labels))
    print("FINAL " + ", ".join([f"{e_curr0}"] + [f"{v}" for v in obs_values0]))
    print(f"TIMINGS ctm: {t_ctm} conv_check: {t_obs}")

    # ----- additional observables ---------------------------------------------
    corrSS = model.eval_corrf_SS(state,
                                 ctm_env_init,
                                 args.corrf_r,
                                 canonical=args.corrf_canonical)
    print("\n\nSS r " + " ".join([label for label in corrSS.keys()]) +
          f" canonical {args.corrf_canonical}")
    for i in range(args.corrf_r):
        print(f"{i} " +
              " ".join([f"{corrSS[label][i]}" for label in corrSS.keys()]))

    corrDD = model.eval_corrf_DD_H(state, ctm_env_init, args.corrf_r)
    print("\n\nDD r " + " ".join([label for label in corrDD.keys()]))
    for i in range(args.corrf_r):
        print(f"{i} " +
              " ".join([f"{corrDD[label][i]}" for label in corrDD.keys()]))

    if args.corrf_dd_v:
        corrDD_V = model.eval_corrf_DD_V(state, ctm_env_init, args.corrf_r)
        print("\n\nDD_v r " + " ".join([label for label in corrDD_V.keys()]))
        for i in range(args.corrf_r):
            print(f"{i} " + " ".join(
                [f"{corrDD_V[label][i]}" for label in corrDD_V.keys()]))

    # environment diagnostics
    print("\n\nspectrum(C)")
    u, s, v = torch.svd(ctm_env_init.C[ctm_env_init.keyC], compute_uv=False)
    for i in range(args.chi):
        print(f"{i} {s[i]}")

    # transfer operator spectrum 1-site-width channel
    print("\n\nspectrum(T)")
    l = transferops_c4v.get_Top_spec_c4v(args.top_n, state, ctm_env_init)
    for i in range(l.size()[0]):
        print(f"{i} {l[i,0]} {l[i,1]}")

    # transfer operator spectrum 2-site-width channel
    if args.top2:
        print("\n\nspectrum(T2)")
        l = transferops_c4v.get_Top2_spec_c4v(args.top_n, state, ctm_env_init)
        for i in range(l.size()[0]):
            print(f"{i} {l[i,0]} {l[i,1]}")