SVD理论以及Python实现

SVD

将一个矩阵分解为U,V(U,V均为列正交矩阵,即列向量直接内积为0),中间的矩阵为对角阵,元素为奇异值。

A [ m ∗ n ] = U [ m ∗ r ] ∗ ∑ [ r ∗ r ] ∗ ( V [ n ∗ r ] ) T A_{[m*n]} = U_{[m*r]} * \sum_{[r*r]} *(V_{[n*r]})^T A[mn]=U[mr][rr](V[nr])T

SVD计算方式

A = U ∗ ∑ ∗ V T A T = V ∗ ∑ ∗ U T A A T = U ∗ ∑ ∗ V T ∗ V ∗ ∑ ∗ U T A = U * \sum * V^T \\ A^T = V * \sum * U ^T \\ AA^T = U * \sum * V^T * V * \sum * U^T A=UVTAT=VUTAAT=UVTVUT

  • 由于其为列正交向量,所以矩阵在非对角位置都为0, 因此当V的列向量是单位向量时,对角位为1,则为单位阵。

A A T = U ∑ 2 U T A A T U = U ∑ 2 AA^T = U {\sum}^2U^T \\ AA^T U = U {\sum}^2 AAT=U2UTAATU=U2
因此,U为 A A T AA^T AAT特征向量构成的矩阵,然后 ∑ 2 {\sum}^2 2的对角元为特征值。

同理,可知, A T A A^TA ATA对应于V的计算。

Python实现

  • 导入包
import numpy as np
  • 创建数据
A = np.linspace(0, 14, 15).reshape((3, -1))
A
array([[ 0.,  1.,  2.,  3.,  4.],
       [ 5.,  6.,  7.,  8.,  9.],
       [10., 11., 12., 13., 14.]])
  • 实现
def SVD(A, n):
    M = np.dot(A, A.T)
    eigval, eigvec = np.linalg.eig(M)
    indexes = np.argsort(-eigval)[:n]
    U = eigvec[:, indexes]
    sigma_sq = eigval[indexes]
    M = np.dot(A.T, A)
    eigval, eigvec = np.linalg.eig(M)
    indexes = np.argsort(-eigval)[:n]
    V = eigvec[:, indexes]
    sigma = np.diag(np.sqrt(sigma_sq))
#     print(sigma)
    return np.dot(np.dot(U, sigma), V.T)
  • 调用
A_ = SVD(A, 2)
A_
array([[2.01625019e-16, 1.00000000e+00, 2.00000000e+00, 3.00000000e+00,
        4.00000000e+00],
       [5.00000000e+00, 6.00000000e+00, 7.00000000e+00, 8.00000000e+00,
        9.00000000e+00],
       [1.00000000e+01, 1.10000000e+01, 1.20000000e+01, 1.30000000e+01,
        1.40000000e+01]])

非常近了,然后量化判断下,用二范数来测量下:

np.linalg.norm(A_ - A)
  • 总共的误差:1.8697717541841314e-14
  • 非常的小了。

你可能感兴趣的:(Python,机器学习+深度学习+强化学习,机器学习+深度学习+强化学习)