奇异值分解(SVD)

特征值分解

特征值分解是矩阵分解的一种方法,矩阵分解也称为矩阵因子分解,即将原始矩阵表示成新的结构简单或者具有特殊性质的两个或多个矩阵的乘积,类似于代数中的因子分解。

特征值分解的实质是求解给定矩阵的特征值和 特征向盘,提取出矩阵最重要的特征,其中特征值分解公式

A=QΣQ−1 , 其中Q为特征向量矩阵, Σ 是特征值对角阵。

奇异值分解(SVD

特征值分解仅适用于提取方阵特征,但在实际应用中,大部分数据对应的矩阵都 不是方阵;
矩阵可能是有很多0的 稀疏矩阵,存储量大且浪费空间,这时就需要 提取主要特征;
奇异值分解 是将任意较复杂的矩阵用更小、更简单的 3个子矩阵的相乘表示 ,用这3个小矩阵来描述 大矩 阵重要的特性。

应用:在使用线性代数的地方,基本上都要使用 SVD。 SVD 不仅仅应用在 PCA 、图像压缩、数字水印、 推荐系统和文章分类、 LSA (隐性语义分析)、特征压缩(或数据降维)中,在信号分解、信号重构、信号降噪、数据融合、同标识别、目标跟踪、故障检测神经网络等方面也有很好的应用, 是很多机器学习算法的基石。

SVD 定义

矩阵的奇异值分解是酉等价型的分解: A∈Cm×n  ∃ 酉矩阵 U∈Cm×m , V∈Cn×n , 使得 A=UΣVH , ( 其中H表示复共轭转置, UHU=UUH=I )

至于为什么要这样分解?如何降维 ?----看文章后的案例,不懂顺网线打我

奇异值定义

A∈Cm×n ,rank(A)=r,设 AHA 的特征值 λ1≥λ2≥...≥λr>0,λr+1=λr+2=...0 ,则矩阵A的奇异值:

可能对于 复线性空间有点难理解,那么对实数矩阵 Am×n , 我们不能求其特征值,但对于ATA 和 AAT 分别为n阶和m阶对称方阵,他们的秩R( ATA)=R(AAT)=R(A), 且两个 对称矩阵的非零特值相同 ,对称矩阵的特征址矩阵是 正交矩阵,特征值均为正实数,因此可求出 特征值的平方根--奇异值

SVD的实现(以下仅针对实数域)

案例1--数学

SVD代码

# -*- coding: utf-8 -*-
import numpy as np
from numpy import linalg as la
#1. SVD分解
A= [[1,1,3,6,1],[5,1,8,4,2],[7,9,2,1,2]]
A=np.array(A)
U,s,VT = la.svd(A) 
# 为节省空间,svd输出s只有奇异值的向量
print('奇异值:',s)
# 根据奇异值向量s,生成奇异值矩阵
Sigma = np.zeros(np.shape(A))
Sigma[:len(s),:len(s)] = np.diag(s)

print("左奇异值矩阵:\n",U)
print('奇异值矩阵:\n',Sigma)
print('右奇异矩阵的转置:\n',VT)

#2.SVD重构
B = U.dot(Sigma.dot(VT))
print('重构后的矩阵B:\n', B)

print('原矩阵与重构矩阵是否相同?',np.allclose(A,B))

# 3. SVD矩阵压缩(降维)
for k in range(3,0,-1):  # 3,2,1
    # U的k列,VT的k行
    D = U[:,:k].dot(Sigma[:k,:k].dot(VT[:k,:]))
    print('k=',k,"压缩后的矩阵:\n",np.round(D,1))  # round取整数
代码一定要自己跑跑,SVD 得到的特征值的前两项较大,最后一项值较小,通过取不同的k值,分别对应于取 U的前 k列, Σ 变成  k阶方阵, VT取钱k行,对比利用矩阵乘积得到的新矩阵与原始矩阵的情况,从结果可看到,SVD 后特征值主要集中在前两个数上,当 k取2时,得到的新矩阵较接近,虽然有些差异,但大多数信息是完好的,因此,可以选取合适的 值,保留比较大的奇异值及特征向量,实现用较少的数据量达到较好的矩阵近似效果。

奇异值分解的展开形式

对于图像的数字化技术与矩阵的奇异值分解

将图形分解成象素的一个矩形的数阵,其中的信息就可以用一个矩阵A=(a ij)m×n来存储。矩阵A的元素a ij是一个正的数,它相应于象素的灰度水平的度量值。压缩数字化图形存储量的方法主要是应用矩阵的奇异值分解和矩阵范数下的逼近。如果图象的数字矩阵A的奇异值分解为: A=UΣVH , 压缩矩阵A的方法是取一个秩为k (k<r)的矩阵Ak来逼近矩阵A。

  • 存储矩阵Ak只需要存储k个奇异值,k个m维向量ui和n维向量vj的所有分量,共计k(m+n+1)个元素。
  • 如果m=n=1000,存储原矩阵A需要存储1000×1000个元素。取k=100时,图象已经非常清晰了,这时的存储量是100(2000+1)=200100个数。
  • 和矩阵A比较,存储量减少了80%。

案例2--图像压缩

# -*- coding: utf-8 -*-
from itertools import count
from PIL import Image
import numpy as np

def img_compress(img,percent):
    U,s,VT=np.linalg.svd(img)
    Sigma = np.zeros(np.shape(img))
    Sigma[:len(s),:len(s)] = np.diag(s)
    # 根据压缩比 取k值

    # 方法1 # k是奇异值数值总和的百分比个数,(奇异值权重)
    count = (int)(sum(s))*percent
    k = -1
    curSum = 0
    while curSum <= count:
        k+=1
        curSum += s[k]

    # 方法2
    # k = (int)(percent*len(s)) # k是奇异值个数的百分比个数

    # 还原后的数据D
    D = U[:,:k].dot(Sigma[:k,:k].dot(VT[:k,:]))
    D[D<0] = 0
    D[D>255] = 255
    return np.rint(D).astype('uint8')

# 图像重建
def rebuild_img(filename,percent):
    img = Image.open(filename,'r')
    a = np.array(img)
    R0 = a[:,:,0]
    G0 = a[:,:,1]
    B0 = a[:,:,2]
    R = img_compress(R0,percent)
    G = img_compress(G0,percent)
    B = img_compress(B0,percent)
    re_img = np.stack((R,G,B),2)
    # 保存图片
    newfile = filename+str(percent*100)+'.jpg'
    Image.fromarray(re_img).save(newfile)
    img = Image.open(newfile)
    img.show()


rebuild_img('test.jpg',0.6)

代码一定要动手跑,对比结果

上面方法1--奇异值权重

案例3--奇异值与潜在语义索引[1]

这个矩阵里的一行表示一个词在哪些title中出现了几次,一列表示一个title中有哪些词,。比如说T1这个title中就有guide、investing、market、stock四个词,各出现了一次,我们将这个矩阵进行SVD,得到下面的矩阵

注意观测他们的数值左奇异向量表示词的一些特性,右奇异向量表示title的一些特性,中间的奇异值矩阵表示左奇异向量的一行对应右奇异向量的一列的重要程度,数字越大越重要,继续看这个矩阵还可以发现一些有意思的东西,首先,左奇异向量的第一列表示每一个词的出现频繁程度,虽然不是线性的,但是可以认为是一个大概的描述,比如book是0.15对应文档中出现的2次,investing是0.74对应了文档中出现了9次,rich是0.36对应文档中出现了3次,其次,右奇异向量中一的第一行表示每一篇文档中的出现词的个数的近似,比如说,T6是0.49,出现了5个词,T2是0.22,出现了2个词

参考

  1. ^大佬博客-机器学习中的数学 http://leftnoteasy.cnblogs.com
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值