zoukankan      html  css  js  c++  java
  • SVD奇异值分解

    Singular Value Decomposition

    矩阵分解,特征值

    • 矩阵的特征值分解的原理
    • 目的是什么
    • 如何去使用。

    为什么要对矩阵进行分解:知乎-马同学

    1.SVD矩阵分解

    任意实矩阵(Ain R^{m * n})都可以进行分解$$A=U Sigma V^{T}$$
    (Uin R^{m*m})是满足 (U^{T}U=I)的m阶酉矩阵 unitary matrix
    (Vin R^{m*m}, V^{T} V=I)的n阶酉矩阵
    (Sigma in R^{m*n})是m x n矩阵,其中(Sigma _{ii}=sigma _{i})
    (sigma_{i})为非负数,满足(sigma_{1} geq sigma_{2}geq ...geq 0)

    知识点扩充:酉矩阵

    n阶复方阵U的n个列向量是U空间的一个标准正交基。酉矩阵是正交矩阵往复数域的推广

    一些性质

    1.(sigma_{i})奇异值按降序排列确保(Sigma)的唯一性
    2.矩阵(A)的秩就是非零奇异值的个数
    3.矩阵(A)的奇异值就是矩阵(A*A^{T})特征值的平方根

    2.SVD的实现

    利用numpy函数包中linalg来实现

    # 先看一个具体的案例
    import numpy as np 
    U,Sigma,VT=np.linalg.svd([[1,1],[7,7]])
    print("the U is:
     {}
     Sigma is:
     {}
     VT is:
     {}".format(U,Sigma,VT));
    

    输出
    the U is:
    [[-0.14142136 -0.98994949]
    [-0.98994949 0.14142136]]
    Sigma is:
    [1.00000000e+01 2.82797782e-16]
    VT is:
    [[-0.70710678 -0.70710678]
    [ 0.70710678 -0.70710678]]

    这里要注意的是在numpy中为了节省储存空间,特征值矩阵Sigma 只输出对角线的元素(输出一列)

    from numpy import *
    from numpy import linalg as la
    # construct the datasets
    def loadExData():
        return[[0, 0, 0, 2, 2],
               [0, 0, 0, 3, 3],
               [0, 0, 0, 1, 1],
               [1, 1, 1, 0, 0],
               [2, 2, 2, 0, 0],
               [5, 5, 5, 0, 0],
               [1, 1, 1, 0, 0]]
    if __name__ == '__main__':
    	data=loadExData()
    	U,Sigma,VT=linalg.svd(data)
    	print("Sigma is:
     {}".format(Sigma))
    

    输出结果:
    Sigma is:
    [9.64365076e+00 5.29150262e+00 6.49628424e-16 1.43063514e-16 2.79192092e-17]

    开始对矩阵进行约简

    采用启发式的策略来保留奇异值的数目:

    • 保留矩阵中90%的能量信息-所有奇异值的平方和为总能量,奇异值平方和累加到90%就可以。
    • 在科学和工程中,我们一般设置在r个奇异值之后,其余的奇异值都为0(非常小)。表示在数据集中只有r个重要特征,其余的特征都是噪声或者冗余特征。r=2000或3000

    [A_{7 imes 5} approx U_{7 imes 2} Sigma_{2 imes 2} V_{2 imes 5}^{T} ]

    def Sigma(data):
    	U,Sigma,VT=linalg.svd(data)
    	return U,Sigma,VT
    def SigmaReduce(U,Sigma,VT):
    	sigmaReduce=mat([[Sigma[0],0],[0,Sigma[1]]])
    	similarMatrix=U[:,:2]*sigmaReduce*VT[:2,:]
    	return similarMatrix
    if __name__ == '__main__':
    	data=loadExData()
    	U,Sigma,VT=Sigma(data)
    	similarMatrix=SigmaReduce(U,Sigma,VT)
    	print("the similarMatrix is :
     {}".format(similarMatrix))
    

    结果是:
    the similarMatrix is :
    [[ 1.76986622e-17 -7.05283417e-16 -7.05283417e-16 2.00000000e+00 2.00000000e+00]
    [ 7.22982080e-16 -3.61491040e-16 -3.61491040e-16 3.00000000e+00 3.00000000e+00]
    [ 2.40994027e-16 -1.20497013e-16 -1.20497013e-16 1.00000000e+00 1.00000000e+00]
    [ 1.00000000e+00 1.00000000e+00 1.00000000e+00 -1.70292592e-16 -1.70292592e-16]
    [ 2.00000000e+00 2.00000000e+00 2.00000000e+00 -2.45454840e-16 -2.45454840e-16]
    [ 5.00000000e+00 5.00000000e+00 5.00000000e+00 -5.55011948e-18 -5.55011948e-18]
    [ 1.00000000e+00 1.00000000e+00 1.00000000e+00 -1.22727420e-16 -1.22727420e-16]]

    与原始数据相比较,几乎没有什么差距
    表示可以使用sigma来进行代替约简矩阵

    3.SVD的实际应用

    基于协同过滤的推荐引擎
    协同过滤-collaborative filtering

    相似度的计算

    • 欧式距离计算相似度

    [L_{P}(x_{i},x_{j})=(sum _{i=1}^{n} mid x_{i}^{l}- x_{j}^{l} mid ^{p})^{frac{1}{p}} ]

    p=2的时候表示为欧式距离
    可以利用 $$simiarity=frac{1}{1+L_{p}distance}$$
    来保证相似度在(0,1)之间,数值越大表示相似度越高。

    • Pearson correlation

    在 numpy计算包中,可以使用 corrcoef()函数来实现计算
    corrcoef()的输出是(-1,1),可以使用函数 0.5+0.5*corrcoef() 来将输出相似度保证在(0,1)之间

    • 余弦相似度-cosine similarity

    [cos heta= frac{A cdot B} { mid mid A mid mid cdot mid mid B mid mid } ]

    (mid mid A mid mid ,mid mid B mid mid) 表示向量的2范数
    夹角为90度,则相似度为0,方向相同则相似度为1。
    范数的计算方法可以使用 numpy.linalg.norm()来计算

    推荐引擎评价指标:最小均方根误差 root mean squared error RSME

    对数字识别的图像进行压缩
    结果是使用两个特征值就可以实现矩阵的近似,实现图像的重构
    大大减小了存储空间

    # import packages
    def printMat(inMat,thresh=0.8):
        for i in range(32):
            for k in range(32):
                if float(inMat[i,k])>thresh:
                    print("{}".format(1))
                else:
                    print("{}".format(0))
            print("
    ")
    def imgCompress(numSV=3,thresh=0.8):
        myl=[]
        for line in open('0_5.txt').readlines():
            newRow=[]
            for i in range (32):
                newRow.append(int(line[i]))
            myl.append(newRow)
        myMat=mat(myl)
    
        # firsr,print the original matrix
        print(" the original matrix") 
        printMat(myMat,thresh)
        U,Sigma,VT=la.svd(myMat)
        sigRecon=mat(zeros((numSV,numSV)))
        # 还是需要把简化的 sigma 变成矩阵的形式
        for k in range(numSV):
            sigRecon[k,k]=Sigma[k]
    
        # 计算推荐矩阵
        ReconMat=U[:,:numSV]*sigRecon*VT[:numSV,:]
    
        # print the recommend matrix 
        print("the recommend matrix ")
        printMat(ReconMat,thresh)
    
    if __name__ == '__main__':
        imgCompress()
    
    不要用狭隘的眼光看待不了解的事物,自己没有涉及到的领域不要急于否定. 每天学习一点,努力过好平凡的生活.
  • 相关阅读:
    c# 获取计算机信息
    中文转换为完整拼音算法原理分析
    C#汉字转拼音(npinyin)将中文转换成拼音全文或首字母
    指定账户访问共享文件
    解决table边框在打印中不显示的问题
    SQL SERVER数据库备份时出现“操作系统错误5(拒绝访问)
    关于sql server 代理(已禁用代理xp)解决办法
    【架构】架构漫谈
    【Javascript】js图形编辑器库介绍
    【Web】前台传送JSON格式数据到后台Shell处理
  • 原文地址:https://www.cnblogs.com/GeekDanny/p/10099004.html
Copyright © 2011-2022 走看看