SVD理论以及Python实现

论坛 期权论坛 期权     
肥宅Sean   2019-7-7 23:20   1168   0
[h1]SVD[/h1]将一个矩阵分解为U,V(U,V均为列正交矩阵,即列向量直接内积为0)
中间的矩阵为对角阵,元素为奇异值。


[h2]SVD计算方式[/h2]

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


因此,U为
特征向量构成的矩阵,然后
的对角元为特征值。
      同理,可知
对应于V的计算。

[h1]Python实现[/h1]
  • 导入包
  1. import numpy as np
复制代码
  • 创建数据
  1. A = np.linspace(0, 14, 15).reshape((3, -1))A
复制代码
  1. array([[ 0.,  1.,  2.,  3.,  4.],       [ 5.,  6.,  7.,  8.,  9.],       [10., 11., 12., 13., 14.]])
复制代码
  • 实现
  1. 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)
复制代码
  • 调用
  1. A_ = SVD(A, 2)A_
复制代码
  1. 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]])
复制代码
非常近了,然后量化判断下,用二范数来测量下:
  1. np.linalg.norm(A_ - A)
复制代码
  • 总共的误差:
    1. 1.8697717541841314e-14
    复制代码
  • 非常的小了。


ps:笔者最近上线了自己的GitHub账号,大家有感兴趣的项目可以一起参与其中哦!点击阅读原文可跳转至我的github网站。

排版|Shane

作者|Sean
审稿|Vinson




长按识别二维码


喜欢的可以点
右下角的好看哦

[h1][/h1]
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:
帖子:
精华:
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP