principal angel 主角,特征角,以及不变子空间的扰动和相似性问题,以及python代码

参考链接:https://wenku.baidu.com/view/821687e90975f46527d3e18c.html

principal angel 定义:

中文版定义:

解释:有两个子空间A和B,这两个子空间的维数可能不同。在每个子空间里,向量是单位正交基。所要求的就是,A中的一个向量和B中的一个向量夹角的最小值,即cos最大。

解决方法:可以使用SVD进行求解:

因为对于两个单位向量x和y,|x|=1,|y|=1, |x|*|y| =1,所以 cos(x,y) = x'y。详细过程请看下面论文:Principal Angles Between Subspaces and their tangents

知道了cos,那么改变正交向量可以求得sin.还可以求得tan.只要相除一下,使用矩阵的逆(Moore-Penrose),参考张贤达老师的矩阵分析与应用。

python 程序 求 principal angle:

官方程序:https://github.com/scipy/scipy/blob/master/scipy/linalg/decomp_svd.py

def subspace_angles(A, B):
    r"""
    Compute the subspace angles between two matrices.
    Parameters
    ----------
    A : (M, N) array_like
        The first input array.
    B : (M, K) array_like
        The second input array.
    Returns
    -------
    angles : ndarray, shape (min(N, K),)
        The subspace angles between the column spaces of `A` and `B` in
        descending order.
    See Also
    --------
    orth
    svd
    Notes
    -----
    This computes the subspace angles according to the formula
    provided in [1]_. For equivalence with MATLAB and Octave behavior,
    use ``angles[0]``.
    .. versionadded:: 1.0
    References
    ----------
    .. [1] Knyazev A, Argentati M (2002) Principal Angles between Subspaces
           in an A-Based Scalar Product: Algorithms and Perturbation
           Estimates. SIAM J. Sci. Comput. 23:2008-2040.
    Examples
    --------
    A Hadamard matrix, which has orthogonal columns, so we expect that
    the suspace angle to be :math:`\frac{\pi}{2}`:
    >>> from scipy.linalg import hadamard, subspace_angles
    >>> H = hadamard(4)
    >>> print(H)
    [[ 1  1  1  1]
     [ 1 -1  1 -1]
     [ 1  1 -1 -1]
     [ 1 -1 -1  1]]
    >>> np.rad2deg(subspace_angles(H[:, :2], H[:, 2:]))
    array([ 90.,  90.])
    And the subspace angle of a matrix to itself should be zero:
    >>> subspace_angles(H[:, :2], H[:, :2]) <= 2 * np.finfo(float).eps
    array([ True,  True], dtype=bool)
    The angles between non-orthogonal subspaces are in between these extremes:
    >>> x = np.random.RandomState(0).randn(4, 3)
    >>> np.rad2deg(subspace_angles(x[:, :2], x[:, [2]]))
    array([ 55.832])
    """
    # Steps here omit the U and V calculation steps from the paper

    # 1. Compute orthonormal bases of column-spaces
    A = _asarray_validated(A, check_finite=True)
    if len(A.shape) != 2:
        raise ValueError('expected 2D array, got shape %s' % (A.shape,))
    QA = orth(A)
    del A

    B = _asarray_validated(B, check_finite=True)
    if len(B.shape) != 2:
        raise ValueError('expected 2D array, got shape %s' % (B.shape,))
    if len(B) != len(QA):
        raise ValueError('A and B must have the same number of rows, got '
                         '%s and %s' % (QA.shape[0], B.shape[0]))
    QB = orth(B)
    del B

    # 2. Compute SVD for cosine
    QA_T_QB = dot(QA.T, QB)
    sigma = svdvals(QA_T_QB)

    # 3. Compute matrix B
    if QA.shape[1] >= QB.shape[1]:
        B = QB - dot(QA, QA_T_QB)
    else:
        B = QA - dot(QB, QA_T_QB.T)
    del QA, QB, QA_T_QB

    # 4. Compute SVD for sine
    mask = sigma ** 2 >= 0.5
    if mask.any():
        mu_arcsin = arcsin(clip(svdvals(B, overwrite_a=True), -1., 1.))
    else:
        mu_arcsin = 0.

    # 5. Compute the principal angles
    # with reverse ordering of sigma because smallest sigma belongs to largest angle theta
    theta = where(mask, mu_arcsin, arccos(clip(sigma[::-1], -1., 1.)))
    return theta

猜你喜欢

转载自blog.csdn.net/qq_26004387/article/details/88085662