<commit_before>""" Matrix factorization with Sparse PCA
"""
# Author: <NAME>, <NAME>, <NAME>
# License: BSD

import time
import sys

from math import sqrt

import numpy as np
from numpy.lib.stride_tricks import as_strided
from scipy import linalg

from ..utils import check_random_state
from ..linear_model import Lasso, lars_path, ridge_regression
from ..externals.joblib import Parallel, delayed, cpu_count
from ..base import BaseEstimator, TransformerMixin


##################################
# Utility to spread load on CPUs
# XXX: where should this be?
def _gen_even_slices(n, n_packs):
    """Generator to create n_packs slices going up to n.

    Examples
    ========

    >>> list(_gen_even_slices(10, 1))
    [slice(0, 10, None)]
    >>> list(_gen_even_slices(10, 10)) #doctest: +ELLIPSIS
    [slice(0, 1, None), slice(1, 2, None), ..., slice(9, 10, None)]
    >>> list(_gen_even_slices(10, 5)) #doctest: +ELLIPSIS
    [slice(0, 2, None), slice(2, 4, None), ..., slice(8, 10, None)]
    >>> list(_gen_even_slices(10, 3))
    [slice(0, 4, None), slice(4, 7, None), slice(7, 10, None)]

    """
    start = 0
    for pack_num in range(n_packs):
        this_n = n // n_packs
        if pack_num < n % n_packs:
            this_n += 1
        if this_n > 0:
            end = start + this_n
            yield slice(start, end, None)
            start = end


def _update_code(dictionary, Y, alpha, code=None, Gram=None, method='lars',
                 tol=1e-8):
    """ Update the sparse code factor in sparse_pca loop.
    Each column of the result is the solution to a Lasso problem.

    Parameters
    ----------
    dictionary: array of shape (n_samples, n_components)
        dictionary against which to optimize the sparse code

    Y: array of shape (n_samples, n_features)
        data matrix

    alpha: float
        regularization parameter for the Lasso problem

    code: array of shape (n_components, n_features)
        Value of the sparse codes at the previous iteration

    Gram: array of shape (n_features, n_features)
        precomputed Gram matrix, (Y^T * Y)

    method: 'lars' | 'cd'
        lars: uses the least angle regression method (linear_model.lars_path)
        cd: uses the stochastic coordinate descent method to compute the
            Lasso solution (linear_model.Lasso)

    tol: float
        numerical tolerance for Lasso convergence.
        Ignored if `method='lars'`

    Returns
    -------
    new_code : array of shape (n_components, n_features)
        The sparse codes recomputed using this iteration's dictionary
    """
    n_features = Y.shape[1]
    n_atoms = dictionary.shape[1]
    new_code = np.empty((n_atoms, n_features))
    # XXX: should we always do this?
    if Gram is None:
        Gram = np.dot(dictionary.T, dictionary)
    if method == 'lars':
        err_mgt = np.seterr()
        np.seterr(all='ignore')
        #alpha = alpha * n_samples
        XY = np.dot(dictionary.T, Y)
        try:
            for k in range(n_features):
                # A huge amount of time is spent in this loop. It needs to be
                # tight.
                _, _, coef_path_ = lars_path(dictionary, Y[:, k], Xy=XY[:, k],
                                             Gram=Gram, alpha_min=alpha,
                                             method='lasso')
                new_code[:, k] = coef_path_[:, -1]
        finally:
            np.seterr(**err_mgt)
    elif method == 'cd':
        clf = Lasso(alpha=alpha, fit_intercept=False, precompute=Gram)
        for k in range(n_features):
            # A huge amount of time is spent in this loop. It needs to be
            # tight.
            if code is not None:
                clf.coef_ = code[:, k]  # Init with previous value of Vk
            clf.fit(dictionary, Y[:, k], max_iter=1000, tol=tol)
            new_code[:, k] = clf.coef_
    else:
        raise NotImplemented("Lasso method %s is not implemented." % method)
    return new_code


def _update_code_parallel(dictionary, Y, alpha, code=None, Gram=None,
                          method='lars', n_jobs=1, tol=1e-8):
    """ Update the sparse factor V in sparse_pca loop by efficiently
    spreading the load over the available cores.

    Parameters
    ----------
    dictionary: array of shape (n_samples, n_components)
        dictionary against which to optimize the sparse code

    Y: array of shape (n_samples, n_features)
        data matrix

    alpha: float
        regularization parameter for the Lasso problem

    code: array of shape (n_components, n_features)
        previous iteration of the sparse code

    Gram: array of shape (n_features, n_features)
        precomputed Gram matrix, (Y^T * Y)

    method: 'lars' | 'cd'
        lars: uses the least angle regression method (linear_model.lars_path)
        cd: uses the stochastic gradient descent method to compute the
            lasso solution (linear_model.Lasso)

    n_jobs: int
        number of parallel jobs to run

    tol: float
        numerical tolerance for coordinate descent Lasso convergence.
        Only used if `method='lasso`.<commit_msg>Doc: fix minor error in docstring<commit_after>""" Matrix factorization with Sparse PCA
"""
# Author: <NAME>, <NAME>, <NAME>
# License: BSD

import time
import sys

from math import sqrt

import numpy as np
from numpy.lib.stride_tricks import as_strided
from scipy import linalg

from ..utils import check_random_state
from ..linear_model import Lasso, lars_path, ridge_regression
from ..externals.joblib import Parallel, delayed, cpu_count
from ..base import BaseEstimator, TransformerMixin


##################################
# Utility to spread load on CPUs
# XXX: where should this be?
def _gen_even_slices(n, n_packs):
    """Generator to create n_packs slices going up to n.

    Examples
    ========

    >>> list(_gen_even_slices(10, 1))
    [slice(0, 10, None)]
    >>> list(_gen_even_slices(10, 10)) #doctest: +ELLIPSIS
    [slice(0, 1, None), slice(1, 2, None), ..., slice(9, 10, None)]
    >>> list(_gen_even_slices(10, 5)) #doctest: +ELLIPSIS
    [slice(0, 2, None), slice(2, 4, None), ..., slice(8, 10, None)]
    >>> list(_gen_even_slices(10, 3))
    [slice(0, 4, None), slice(4, 7, None), slice(7, 10, None)]

    """
    start = 0
    for pack_num in range(n_packs):
        this_n = n // n_packs
        if pack_num < n % n_packs:
            this_n += 1
        if this_n > 0:
            end = start + this_n
            yield slice(start, end, None)
            start = end


def _update_code(dictionary, Y, alpha, code=None, Gram=None, method='lars',
                 tol=1e-8):
    """ Update the sparse code factor in sparse_pca loop.
    Each column of the result is the solution to a Lasso problem.

    Parameters
    ----------
    dictionary: array of shape (n_samples, n_components)
        dictionary against which to optimize the sparse code

    Y: array of shape (n_samples, n_features)
        data matrix

    alpha: float
        regularization parameter for the Lasso problem

    code: array of shape (n_components, n_features)
        Value of the sparse codes at the previous iteration

    Gram: array of shape (n_features, n_features)
        precomputed Gram matrix, (Y^T * Y)

    method: 'lars' | 'cd'
        lars: uses the least angle regression method (linear_model.lars_path)
        cd: uses the stochastic coordinate descent method to compute the
            Lasso solution (linear_model.Lasso)

    tol: float
        numerical tolerance for Lasso convergence.
        Ignored if `method='lars'`

    Returns
    -------
    new_code : array of shape (n_components, n_features)
        The sparse codes recomputed using this iteration's dictionary
    """
    n_features = Y.shape[1]
    n_atoms = dictionary.shape[1]
    new_code = np.empty((n_atoms, n_features))
    # XXX: should we always do this?
    if Gram is None:
        Gram = np.dot(dictionary.T, dictionary)
    if method == 'lars':
        err_mgt = np.seterr()
        np.seterr(all='ignore')
        #alpha = alpha * n_samples
        XY = np.dot(dictionary.T, Y)
        try:
            for k in range(n_features):
                # A huge amount of time is spent in this loop. It needs to be
                # tight.
                _, _, coef_path_ = lars_path(dictionary, Y[:, k], Xy=XY[:, k],
                                             Gram=Gram, alpha_min=alpha,
                                             method='lasso')
                new_code[:, k] = coef_path_[:, -1]
        finally:
            np.seterr(**err_mgt)
    elif method == 'cd':
        clf = Lasso(alpha=alpha, fit_intercept=False, precompute=Gram)
        for k in range(n_features):
            # A huge amount of time is spent in this loop. It needs to be
            # tight.
            if code is not None:
                clf.coef_ = code[:, k]  # Init with previous value of Vk
            clf.fit(dictionary, Y[:, k], max_iter=1000, tol=tol)
            new_code[:, k] = clf.coef_
    else:
        raise NotImplemented("Lasso method %s is not implemented." % method)
    return new_code


def _update_code_parallel(dictionary, Y, alpha, code=None, Gram=None,
                          method='lars', n_jobs=1, tol=1e-8):
    """ Update the sparse factor V in sparse_pca loop by efficiently
    spreading the load over the available cores.

    Parameters
    ----------
    dictionary: array of shape (n_samples, n_components)
        dictionary against which to optimize the sparse code

    Y: array of shape (n_samples, n_features)
        data matrix

    alpha: float
        regularization parameter for the Lasso problem

    code: array of shape (n_components, n_features)
        previous iteration of the sparse code

    Gram: array of shape (n_features, n_features)
        precomputed Gram matrix, (Y^T * Y)

    method: 'lars' | 'cd'
        lars: uses the least angle regression method (linear_model.lars_path)
        cd: uses the coordinate descent method to compute the
        lasso solution (linear_model.Lasso). Lars will be faster if
        the components extracted are sparse.

    n_jobs: int
        number of parallel jobs to run

    tol: float
        numerical tolerance for coordinate descent Lasso convergence.
        Only used if `method='lasso`.
{'fraction_non_alphanumeric': 0.10331781140861467, 'fraction_numerical': 0.010089251067132324, 'mean_word_length': 2.345991561181435, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2389033', 'n_tokens_mistral': 3213, 'n_tokens_neox': 3045, 'n_words': 1075}