示例#1
0
def transpose_square_root(sigma2, method='Riccati', d=None):
    """For details, see here.

    Parameters
    ----------
        sigma2 : array, shape (n_,n_)
        method : string, optional
        d : array, shape (k_,n_), optional

    Returns
    -------
        s : array, shape (n_,n_)

    """
    if np.ndim(sigma2) < 2:
        return np.squeeze(np.sqrt(sigma2))

    n_ = sigma2.shape[0]

    if method == 'CPCA' and d is None:
        method = 'PCA'

    # Step 1: Riccati root
    if method == 'Riccati':
        s = solve_riccati(sigma2)

    # Step 2: Conditional principal components
    elif method == 'CPCA':
        e_d, lambda2_d = cpca_cov(sigma2, d)
        s = e_d * np.sqrt(lambda2_d)

    # Step 3: Principal components
    elif method == 'PCA':
        e, lambda2 = pca_cov(sigma2)
        s = e * np.sqrt(lambda2)

    # Step 4: Gram-Schmidt
    elif method == 'Gram-Schmidt':
        g = gram_schmidt(sigma2)
        s = np.linalg.inv(g).T

    # Step 5: Cholesky
    elif method == 'Cholesky':
        s = np.linalg.cholesky(sigma2)

    return s
示例#2
0
def fit_lfm_pcfp(x, p, sig2, k_):
    """For details, see here.

    Parameters
    ----------
        x : array, shape (t_, n_)
        p : array, shape (t_,)
        sig2 : array, shape (t_, t_)
        k_ : scalar

    Returns
    -------
        alpha_PC : array, shape (n_,)
        beta_PC : array, shape (n_, k_)
        gamma_PC : array, shape(n_, k_)
        s2_PC : array, shape(n_, n_)

    """

    t_, n_ = x.shape

    # Step 1: Compute HFP-expectation and covariance of x
    m_x, s2_x = meancov_sp(x, p)

    # Step 2: Compute the Choleski root of sig2
    sig = np.linalg.cholesky(sig2)

    # Step 3: Perform spectral decomposition
    s2_tmp = np.linalg.solve(sig, (s2_x.dot(np.linalg.pinv(sig))))
    e, lambda2 = pca_cov(s2_tmp)

    # Step 4: Compute optimal loadings for PC LFM
    beta_PC = sig @ e[:, :k_]

    # Step 5: Compute factor extraction matrix for PC LFM
    gamma_PC = (np.linalg.solve(sig, np.eye(n_))) @ e[:, :k_]

    # Step 6: Compute shifting term for PC LFM
    alpha_PC = (np.eye(n_) - beta_PC @ gamma_PC.T) @ m_x

    # Step 7: Compute the covariance of residuals
    s2_PC = sig @ e[:, k_:n_] * lambda2[k_:n_] @ e[:, k_:n_].T @ sig.T
    return alpha_PC, beta_PC, gamma_PC, s2_PC
示例#3
0
文件: cpca_cov.py 项目: s0ap/arpmRes
def cpca_cov(sigma2, d, old=False):
    """For details, see here.

    Parameters
    ----------
        sigma2 : array, shape (n_,n_)
        d : array, shape (k_,n_)

    Returns
    -------
        lambda2_d : array, shape (n_,)
        e_d : array, shape (n_,n_)

    """

    n_ = sigma2.shape[0]
    k_ = d.shape[0]
    i_n = np.eye(n_)
    lambda2_d = np.empty((n_, 1))
    e_d = np.empty((n_, n_))

    # Step 0. initialize constraints
    m_ = n_ - k_
    a_n = np.copy(d)

    for n in range(n_):
        # Step 1. orthogonal projection matrix
        p_n = [email protected](a_n@a_n.T)@a_n

        # Step 2. conditional dispersion matrix
        s2_n = p_n @ sigma2 @ p_n

        # Step 3. conditional principal directions/variances
        e_d[:, [n]], lambda2_d[n] = pca_cov(s2_n, 1)

        # Step 4. Update augmented constraints matrix
        if n+1 <= m_-1:
            a_n = np.concatenate((a_n.T, sigma2 @ e_d[:, [n]]), axis=1).T
        elif m_ <= n+1 <= n_-1:
            a_n = (sigma2 @ e_d[:, :n+1]).T

    return e_d, lambda2_d.squeeze()
示例#4
0
def factor_analysis_paf(sigma2, k_=None, maxiter=100, eps=1e-2):
    """For details, see here.

    Parameters
    ----------
        sigma2 : array, shape (n_, n_)
        k : int, optional
        maxiter : integer, optional
        eps : float, optional

    Returns
    -------
        beta_paf : array, shape (n_, k_) for k_>1 or (n_, ) for k_=1
        delta2_paf : array, shape (n_,)

    """
    n_ = sigma2.shape[0]

    if k_ is None:
        k_ = int(n_ / 2.0)

    # Step 0: Initialize parameters

    v = np.zeros(n_)
    b = np.zeros((n_, k_))

    for i in range(maxiter):

        # Step 1: Compute the first k_ eigenvectors and eigenvalues

        e_k, lambda2_k = pca_cov(sigma2 - np.diagflat(v), k_)

        # Step 2: Compute the factor loadings and adjust if necessary

        # Step 2a
        b_new = e_k @ np.diag(np.sqrt(lambda2_k))
        # Step 2b
        idx = np.diag(b_new @ b_new.T) > np.diag(sigma2)
        if np.any(idx):
            b_new[idx, :] = np.sqrt(sigma2[idx, idx] /
                                    (b_new @ b_new.T)[idx,
                                                      idx]).reshape(-1, 1) *\
                            b_new[idx, :]

        # Step 3: Update residual variances

        v_new = np.diag(sigma2) - np.diag(b_new @ b_new.T)

        # Step 4: Check convergence

        # relative error
        err = max(
            np.max(np.abs(v_new - v)) / max(np.max(np.abs(v)), 1e-20),
            np.max(np.abs(b_new - b)) / max(np.max(np.abs(b)), 1e-20))

        v = v_new
        b = b_new
        if err < eps:
            break

    beta_paf = b_new
    delta2_paf = v

    return np.squeeze(beta_paf), delta2_paf
示例#5
0
def plot_ellipse(m, s2, *, r=1, n_=1000, display_ellipse=True, plot_axes=False,
                 plot_tang_box=False, color='k', line_width=2):
    """For details, see here.

    Parameters
    ----------
        mu : array, shape (2,)
        sigma2 : array, shape (2,2)
        r : scalar, optional
        n_ : scalar, optional
        display_ellipse : boolean, optional
        plot_axes : boolean, optional
        plot_tang_box : boolean, optional
        color : char, optional
        line_width : scalar, optional

    Returns
    -------
        x : array, shape (n_points,2)

    """

    # Step 1: compute the circle with the radius r

    theta = np.arange(0, 2 * np.pi, (2*np.pi)/n_)
    y = [r * np.cos(theta), r * np.sin(theta)]

    # Step 2: spectral decomposition of s2

    e, lambda2 = pca_cov(s2)
    Diag_lambda = np.diagflat(np.sqrt(np.maximum(lambda2, 0)))

    # Step 3: compute the ellipse as affine transformation of the circle

    # stretch
    x = Diag_lambda@y
    # rotate
    x = e@x
    # translate
    x = m.reshape((2, 1)) + x

    if display_ellipse:
        plt.plot(x[0], x[1], lw=line_width, color=color)
        plt.grid(True)

        # Step 4: plot the tangent box
        if plot_tang_box:
            sigvec = np.sqrt(np.diag(s2))

            rect = patches.Rectangle(m-r * sigvec, 2*r * sigvec[0],
                                     2*r*sigvec[1], fill=False,
                                     linewidth=line_width)
            ax = plt.gca()
            ax.add_patch(rect)

        # Step 5: plot the principal axes
        if plot_axes:
            # principal axes
            plt.plot([m[0]-r*np.sqrt(lambda2[0])*e[0, 0],
                      m[0]+r*np.sqrt(lambda2[0])*e[0, 0]],
                     [m[1]-r*np.sqrt(lambda2[0])*e[1, 0],
                      m[1]+r*np.sqrt(lambda2[0])*e[1, 0]], color=color,
                     lw=line_width)

            plt.plot([m[0]-r*np.sqrt(lambda2[1])*e[0, 1],
                      m[0]+r*np.sqrt(lambda2[1])*e[0, 1]],
                     [m[1]-r*np.sqrt(lambda2[1])*e[1, 1],
                      m[1]+r*np.sqrt(lambda2[1])*e[1, 1]], color=color,
                     lw=line_width)
            plt.axis('equal')

    return x.T
示例#6
0
def spectrum_shrink(sigma2_in, t_):
    """For details, see here.

    Parameters
    ----------
         sigma_in : array, shape (i_, i_)
         t_ : scalar

    Returns
    -------
         sigma_out : array, shape (i_, i_)
         lambda2_out : array, shape (i_, )
         k_ : scalar
         err : scalar
         y_mp : array, shape (100, )
         x_mp : array, shape (100, )
         dist : array

    """

    i_ = sigma2_in.shape[0]

    # PCA decomposition

    e, lambda2 = pca_cov(sigma2_in)

    # Determine optimal k_
    ll = 1000

    dist = np.ones(i_ - 1) * np.nan

    for k in range(i_ - 1):

        lambda2_k = lambda2[k + 1:]
        lambda2_noise = np.mean(lambda2_k)

        q = t_ / len(lambda2_k)

        # compute M-P on a very dense grid
        x_tmp, mp_tmp, x_lim = marchenko_pastur(q, ll, lambda2_noise)
        if q > 1:
            x_tmp = np.r_[0, x_lim[0], x_tmp]
            mp_tmp = np.r_[0, mp_tmp[0], mp_tmp]
        l_max = np.max(lambda2_k)
        if l_max > x_tmp[-1]:
            x_tmp = np.r_[x_tmp, x_lim[1], l_max]
            mp_tmp = np.r_[mp_tmp, 0, 0]

        # compute the histogram of eigenvalues
        hgram, x_bin = np.histogram(lambda2_k, len(x_tmp), density=True)

        # interpolation
        interp = interp1d(x_tmp, mp_tmp, fill_value='extrapolate')
        mp = interp(x_bin[:-1])

        dist[k] = np.mean((mp - hgram)**2)

    err_tmp, k_tmp = np.nanmin(dist), np.nanargmin(dist)
    k_ = k_tmp
    err = err_tmp

    # Isotropy
    lambda2_out = lambda2
    lambda2_noise = np.mean(lambda2[k_ + 1:])

    lambda2_out[k_ + 1:] = lambda2_noise  # shrunk spectrum

    # Output

    sigma2_out = e @ np.diagflat(lambda2_out) @ e.T

    # compute M-P on a very dense grid
    x_mp, y_mp, _ = marchenko_pastur(t_ / (i_ - k_ - 1), 100, lambda2_noise)

    return sigma2_out, lambda2_out, k_, err, y_mp, x_mp, dist
示例#7
0
def cointegration_fp(x, p=None, *, b_threshold=0.99):
    """For details, see here.

    Parameters
    ----------
         x : array, shape(t_, d_)
         p : array, shape(t_, d_)
         b_threshold : scalar

    Returns
    -------
        c_hat : array, shape(d_, l_)
        beta_hat : array, shape(l_, )

    """

    t_ = x.shape[0]
    if len(x.shape) == 1:
        x = x.reshape((t_, 1))
        d_ = 1
    else:
        d_ = x.shape[1]

    if p is None:
        p = np.ones(t_) / t_

    if p is None:
        p = np.ones(t_)/t_

    # Step 1: estimate HFP covariance matrix

    _, sigma2_hat = meancov_sp(x, p)

    # Step 2: find eigenvectors

    e_hat, _ = pca_cov(sigma2_hat)

    # Step 3: detect cointegration vectors

    c_hat = []
    b_hat = []
    p = p[:-1]

    for d in np.arange(0, d_):

        # Step 4: Define series

        y_t = e_hat[:, d] @ x.T

        # Step 5: fit AR(1)

        yt = y_t[1:].reshape((-1, 1))
        ytm1 = y_t[:-1].reshape((-1, 1))
        _, b, _, _ = fit_lfm_mlfp(yt, ytm1, p / np.sum(p))
        if np.ndim(b) < 2:
            b = np.array(b).reshape(-1, 1)

        # Step 6: check stationarity

        if abs(b[0, 0]) <= b_threshold:
            c_hat.append(list(e_hat[:, d]))
            b_hat.append(b[0, 0])

    # Output

    c_hat = np.array(c_hat).T
    b_hat = np.array(b_hat)

    # Step 7: Sort according to the AR(1) parameters beta_hat

    c_hat = c_hat[:, np.argsort(b_hat)]
    b_hat = np.sort(b_hat)

    return c_hat, b_hat