奇异值分解SVD计算原理及JAVA代码
SVD是什么?
SVD是针对⾮⽅阵的特征降维⽅法,对于⽅阵通常⽤PCA来进⾏降维。设A是⼀个m*n矩阵 m>=n。那么对A进⾏奇异值分解的结果就表⽰为(V.T的⼤⼩是r*n):
python转java代码
其中矩阵U中的列向量被称为左奇异向量,V中的⾏向量被成为右奇异向量,Σ是⼀个对⾓矩阵,⾥⾯的对⾓线上的值就是奇异值(特征值)。
那么如何分解呢?
先将A.T乘A,得到⼀个m*m的矩阵,再对这个⽅阵进⾏特征值分解。
这⾥的Vi就是上述的右奇异向量,它是列向量,n⾏1列,在构成V矩阵的时候要注意转置,并且还可以得到:
这⾥就是对应的奇异值,就是对应的左奇异向量,也是⼀个列向量,总共会分解出来r个和,将左奇异向量⼀列⼀列排起来就得到了U,将⼜奇异向量⼀列⼀列排起来再进⾏转置就得到了V.T。
图⽚来⾃,这也是⼀篇很好的⽂章。
如何通过SVD来降维?
分解出奇异值后得到矩阵Σ,每个奇异值都对应⼀个右奇异向量、左奇异向量,奇异值的⼤⼩就代表了特征的重要程度,往往前10%甚⾄前1%个奇异值之和占总的奇异值之和就达到了85%或者更⾼,所以只需要选取这些奇异值代表的奇异向量就可以最⼤程度上降低维度且没有损失太多数据信息。
最后会得到哪些数据?
最后得到的就是Σ U V。Σ是奇异值对⾓矩阵,包含了每个特征的奇异值(可以看成是这个特征的重要程度)。U是左奇异向量构成的矩阵,V是右奇异向量构成的矩阵,这两个矩阵可以互相转化,所以选取新的特征的时候⽤其中的⼀个就可以。并且在SVD的时候对特征进⾏了压缩,原矩阵A 为m*n,但是奇异值只有r个,压缩后的左右奇异向量也各只有r个,然后还需要根据阈值再从r个特征中选出占⽐⾼的。
如何⽤代码实现?
python中scikit-learn库可以实现,JAVA中使⽤包可以实现SVD。对于JAVA先从官⽹上下载jama.jar再导⼊⼯程中,使⽤的⽰例代码如下。
import Jama.Matrix;
import Jama.SingularValueDecomposition;
SimpleDateFormat;
public class TestSVD {
public static void main(String[] args){
// create M-by-N matrix that doesn't have full rank
int M = 8, N = 5;
Matrix B = Matrix.random(5, 3);
Matrix A = Matrix.random(M, N).times(B).anspose());
System.out.print("A = ");
A.print(9, 6);
// compute the singular vallue decomposition
System.out.println("A = U S V^T");
System.out.println();
long start = System.currentTimeMillis();
//进⾏奇异值分解
SingularValueDecomposition s = A.svd();
long end = System.currentTimeMillis();
System.out.println("Singular Value Decomposition elapsed time: "+(end-start));        Matrix U = s.getU();
Matrix S = s.getS();
Matrix V = s.getV();
System.out.print("U = ");
U.print(9, 6);
System.out.print("Sigma = ");
S.print(9, 6);
System.out.print("V = ");
V.print(9, 6);
System.out.println("rank = " + s.rank());
System.out.println("condition number = " + s.cond());
System.out.println("2-norm = " + s.norm2());
// print out singular values
System.out.print("singular values = ");
Matrix svalues = new SingularValues(), 1);
svalues.print(9, 6);
}
}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。