矩阵分解(一):奇异值分解

    由于涉及到大量数学公式,用Latex生成pdf文件,这里贴出pdf转换出来的png图片。附件里面有完整的pdf和代码文件。
奇异值分解1.png


奇异值分解2.png


奇异值分解3.png


奇异值分解4.png

  pdf里面并没有贴出代码,这里贴出源文件的代码,代码很简单,只是简单地对svd进行了测试。下面是代码文件和输出结果:
  svd.py文件:
import numpy as np
import time
# 利用numpy包自带的svd实现,第二个参数表示是否打印出矩阵
def np_svd(matrix,printInfo=True):
    print('np_svd:')
    start = time.clock()
    u,sigma,v = np.linalg.svd(matrix)
    end = time.clock()
    print('shape:',matrix.shape,'=',u.shape,'*',sigma.shape,'*',v.shape)
    print('time:',end-start)
    if(printInfo):
        print(matrix)
        print(u)
        print(sigma)
        print(v)
if __name__ == "__main__":
    # 测试矩阵秩为行满秩或列满秩的情况
    a = np.array([[-1,3,4],
                  [2,-5,8],
                  [-3,-7,-2],
                  [2,4,-3]])
    np_svd(a)
    
    # 测试秩小于行数和列数的矩阵
    b = np.array([[-1,3,4],
                  [2,-5,8],
                  [-2,6,8],
                  [0,1,16]])
    np_svd(b)
    
    # 测试矩阵分解的时间
    for ex in range(1,4):
        m = 3 * 10 ** ex         # 3乘以10的ex次方
        n = 4 * 10 ** ex         # 4乘以10的ex次方
        matrix = np.random.normal(size=(m,n))  # 正态分布
        np_svd(matrix,False)
    测试结果:       
'''
# 满秩情况下的测试:输入矩阵为4*3
np_svd:
shape: (4, 3) = (4, 4) * (3,) * (3, 3)
time: 0.001563813577831752
[[-1  3  4]
 [ 2 -5  8]
 [-3 -7 -2]
 [ 2  4 -3]]
[[ 0.03492724  0.50564699 -0.74831887  0.42792532]
 [ 0.80692855  0.38784734  0.40536499  0.18471597]
 [ 0.37135366 -0.7637849  -0.22588836  0.47718292]
 [-0.45797693  0.10260697  0.47399636  0.74502107]]
[ 11.06047807   8.73915881   3.36049521]
[[-0.0407835  -0.75595687  0.65334977]
 [ 0.31657696  0.61042791  0.72605564]
 [ 0.94768968 -0.23644657 -0.21442314]]
# 不满秩的分解,可以看出sigma矩阵[  2.00999029e+01   8.71744817e+00   2.11044410e-16](由于是对角矩阵,采用向量存储),可以看出第三个奇异值已经趋于零了,可以说就是零
np_svd:
shape: (4, 3) = (4, 4) * (3,) * (3, 3)
time: 0.0001338945396582858
[[-1  3  4]
 [ 2 -5  8]
 [-2  6  8]
 [ 0  1 16]]
[[ 0.21486784  0.31094848  0.90774033 -0.18207238]
 [ 0.3668635  -0.71292939  0.03774797 -0.59642095]
 [ 0.42973567  0.62189696 -0.41612219 -0.50538476]
 [ 0.79659917 -0.09103243 -0.03774797  0.59642095]]
[  2.00999029e+01   8.71744817e+00   2.11044410e-16]
[[-0.01694596  0.10872188  0.99392776]
 [-0.34191212  0.93351191 -0.10794265]
 [-0.93957913 -0.34166514  0.02135407]]
# 测试30*40 300*400 3000*4000 30000*40000矩阵的分解时间(s),分别为0.0011336715375591666、 0.03374235704779949、37.49550263636945。可见3000*4000已经用了半分钟,当测试30000*40000时,计算机全卡了,结果等了大概五分钟没有出结果,所以直接强制关机。可见矩阵分解操作计算了特别大。
np_svd:
shape: (30, 40) = (30, 30) * (30,) * (40, 40)
time: 0.0011336715375591666
np_svd:
shape: (300, 400) = (300, 300) * (300,) * (400, 400)
time: 0.03374235704779949
np_svd:
shape: (3000, 4000) = (3000, 3000) * (3000,) * (4000, 4000)
time: 37.49550263636945
'''

 

2 个评论

补充一个我觉得比较形象的介绍:http://blog.csdn.net/xiahouzuoxin/article/details/41118351
是的,这个博客写得太棒了!

要回复文章请先登录注册