作者:@静哥哥
本文为作者原创,未经博主允许,请勿转载:https://www.cnblogs.com/endlesscoding/p/10058532.html
阅读目录
1、SVD算法实现
2、SVD的Python实现
总结
注:在《SVD(奇异值分解)小结 》中分享了SVD原理,但其中只是利用了numpy.linalg.svd函数应用了它,并没有提到如何自己编写代码实现它,在这里,我再分享一下如何自已写一个SVD函数。但是这里会利用到SVD的原理,如果大家还不明白它的原理,可以去看看《SVD(奇异值分解)小结 》,或者自行百度/google。
1、SVD算法实现
1.1 SVD原理简单回顾
有一个m×n的实数矩阵A,我们可以将它分解成如下的形式
A=UΣVT
其中U和V均为单位正交阵,即有UUT=I和VVT=I,U称为左奇异矩阵,V称为右奇异矩阵,Σ仅在主对角线上有值,我们称它为奇异值,其它元素均为0。上面矩阵的维度分别为U∈Rm×m, Σ∈Rm×n, V∈Rn×n。
正常求上面的U,V,Σ不便于求,我们可以利用如下性质
AAT=UΣVTVΣTUT=UΣΣTUT
ATA=VΣTUTUΣVT=VΣTΣVT
1.2 SVD算法
据1.1小节,对式(1-3)和式(1-4)做特征值分解,即可得到奇异值分解的结果。但是样分开求存在一定的问题,由于做特征值分解的时候,特征向量的正负号并不影响结果,比如,我们利用式(1-3)和(1-4)做特征值分解
AATui=σiuiorAAT(−ui)=σi(−ui)ATAvi=σiviorATA(−vi)=σi(−vi)
如果在计算过程取,取上面的ui组成左奇异矩阵U,取−vi组成右奇异矩阵V,此时A≠UΣVT。因此求vi时,要根据ui来求,这样才能保证A=UΣVT。因此,我们可以得出如下1.1计算SVD的算法。它主要是先做特性值分解,再根据特征值分解得到的左奇异矩阵U间接地求出部分的右奇异矩阵V′∈Rm×n。
算法1.1:SVD
输入:样本数据
输出:左奇异矩阵,奇异值矩阵,右奇异矩阵
计算特征值: 特征值分解AAT,其中A∈Rm×n为原始样本数据
AAT=UΣΣTUT
得到左奇异矩阵U∈Rm×m和奇异值矩阵Σ′∈Rm×m
间接求部分右奇异矩阵: 求V′∈Rm×n
利用A=UΣ′V′可得
V′=(UΣ′)−1A=(Σ′)−1UTA
返回U, Σ′, V′,分别为左奇异矩阵,奇异值矩阵,右奇异矩阵。
注:这里得到的Σ′和V′与式(1-2)所得到的Σ, V有区别,它们的维度不一样。Σ′是只取了前m个奇异值形成的对角方阵,即Σ′∈Rm×m;V′不是一个方阵,它只取了V∈Rm×n的前m行(假设m