我正在使用jama来计算SVD。它工作得很好。如果我通过方阵。例如2x2或3x3等矩阵。但是,当我传递像2x3或4x8这样的东西时,它给出了 错误。我用了他们所有的例子。他们有不同的构造函数来执行这项工作。另外我的第二个问题是,我用3x3矩阵,它给了
double[][] vals = {{1.,1.,0},{1.,0.,1.},{1.,3.,4.},{6.,4.,8.}};
Matrix A = new Matrix(vals);
产生以下错误:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
之后,我可以使用另一个构造函数,如下所示
double[][] vals = {{1.,1.,0,4},{1.,0.,1.,2},{1.,3.,4.,8},{1.,3.,4.,8}};
Matrix A = new Matrix(vals,4,3);
它产生了以下输出:
A =
1.0 1.0 0.0
1.0 0.0 1.0
1.0 3.0 4.0
6.0 4.0 8.0
A = U S V^T
U =
0.078 -0.115 -0.963
0.107 -0.281 0.260
0.402 0.886 -0.018
0.906 -0.351 0.060
Sigma =
11.861881 0.000000 0.000000
0.000000 2.028349 0.000000
0.000000 0.000000 1.087006
V =
0.507705 -0.795196 -0.331510
0.413798 0.562579 -0.715735
0.755650 0.226204 0.614675
rank = 3
condition number = 10.912437186202627
2-norm = 11.86188091889931
singular values =
11.861881 2.028349 1.087006
适用于非方矩阵。但它为svd产生了错误的结果,因为V和S没有相同的行= 4(如果我不能正确分析结果,我很抱歉,因为我是SVD的新手)。任何的想法? 我该怎么办?
答案 0 :(得分:4)
在这里要小心,JAMA主要支持SVD用于全等级矩阵,如果你阅读“自述”,你会注意到行为不一定对于秩不足(m 实质上,导致ArrayIndexOutOfBounds异常的原因是 将此更改为: 将解决问题。终极所发生的事情(至少对于vicatcu的例子)是你注入了一个带有 对于m> = n的m×n矩阵A,奇异值分解为
m×n正交矩阵U,n×n对角矩阵S和
n×n正交矩阵V使得A = U S V'。 但在这种情况下,这并不成立,因为 将创建一个假定行为 简而言之,切换到上面粘贴的线将检测U的尺寸,因此无论等级如何都会返回有效结果。SingularValueDecomposition
中的第486行:return new Matrix(U,m,Math.min(m+1,n));
return new Matrix(U);
m=4
和n=5
的矩阵,但实际输出U
中的注意事项有维度m=4
和n=4
。如果您阅读了SingularValueDecomposition
类的顶部,请说明:
m=4
和n=5
表示m<n
。所以现在因为你传递的是秩不足的矩阵,U的维度与SVD类的 normal 调用情况不同,因此语句如下:new Matrix(U, m, Math.min(m+1,n))
m
的矩阵,此处为4(这是正确的)和假定列n
,此处为Math.min(4+1,5)=5
(这是不正确的)。所以:当你打印矩阵并且打印例程调用getColumnDimension
时,U矩阵返回5
,它大于实际的后备数组维度。
答案 1 :(得分:1)
阅读wiki article on SVD。以下代码代表第2节中的示例。
import Jama.Matrix;
import Jama.SingularValueDecomposition;
public class JAMATest {
static public void printMatrix(Matrix m){
double[][] d = m.getArray();
for(int row = 0; row < d.length; row++){
for(int col = 0; col < d[row].length; col++){
System.out.printf("%6.4f\t", m.get(row, col));
}
System.out.println();
}
System.out.println();
}
public static void main(String[] args) {
double[][] vals = { {1., 0., 0., 0., 2.},
{0., 0., 3., 0., 0.},
{0., 0., 0., 0., 0.},
{0., 4., 0., 0., 0.}
};
Matrix A = new Matrix(vals);
SingularValueDecomposition svd = new SingularValueDecomposition(A);
System.out.println("A = ");
printMatrix(A);
System.out.println("U = ");
printMatrix(svd.getU());
System.out.println("Sigma = ");
printMatrix(svd.getS());
System.out.println("V = ");
printMatrix(svd.getV());
}
}
并产生outputL:
A =
1.0000 0.0000 0.0000 0.0000 2.0000
0.0000 0.0000 3.0000 0.0000 0.0000
0.0000 0.0000 0.0000 0.0000 0.0000
0.0000 4.0000 0.0000 0.0000 0.0000
U =
0.0000 0.0000 -1.0000 0.0000
0.0000 1.0000 -0.0000 0.0000
0.0000 0.0000 -0.0000 1.0000
1.0000 0.0000 -0.0000 0.0000
Sigma =
4.0000 0.0000 0.0000 0.0000 0.0000
0.0000 3.0000 0.0000 0.0000 0.0000
0.0000 0.0000 2.2361 0.0000 0.0000
0.0000 0.0000 0.0000 0.0000 0.0000
0.0000 0.0000 0.0000 0.0000 0.0000
V =
0.0000 -0.0000 -0.4472 -0.8944 -0.0000
0.0000 -0.0000 -0.0000 -0.0000 -0.0000
0.0000 1.0000 -0.0000 -0.0000 -0.0000
0.0000 -0.0000 -0.0000 -0.0000 1.0000
1.0000 -0.0000 -0.8944 0.4472 -0.0000
希望这会有所帮助。另外,FWIW这里是Matlab关于同一问题的输出:
>> A = [1.0000, 0.0000, 0.0000, 0.0000, 2.0000; 0, 0, 3, 0, 0; 0, 0, 0, 0, 0; 0, 4, 0, 0, 0];
>> A
A =
1 0 0 0 2
0 0 3 0 0
0 0 0 0 0
0 4 0 0 0
>> [U, S, V] = svd(A);
>> U
U =
0 0 1 0
0 1 0 0
0 0 0 -1
1 0 0 0
>> S
S =
4.0000 0 0 0 0
0 3.0000 0 0 0
0 0 2.2361 0 0
0 0 0 0 0
>> V
V =
0 0 0.4472 0 -0.8944
1.0000 0 0 0 0
0 1.0000 0 0 0
0 0 0 1.0000 0
0 0 0.8944 0 0.4472
关于您的第一个问题,以下代码不会产生错误:
import Jama.Matrix;
public class JAMATest {
/**
* @param args
*/
public static void main(String[] args) {
double[][] vals = {{1.,1.,0},{1.,0.,1.},{1.,3.,4.},{6.,4.,8.}};
Matrix A = new Matrix(vals);
}
}
所以你正在做的其他事情必须导致它有一个例外。尝试使用我的printMatrix方法代替您正在使用的任何方法,看看它是否有帮助。
答案 2 :(得分:0)
U,S和V的尺寸不需要与A相同.U将具有相同的行数,V ^ T将具有相同的列数。这足以通过矩阵乘法的规则重新创建A.
另一个维度(U的列,V ^ T的行和S的行/列)将是A的“等级”(在您的示例3中)。粗略地说,这就是数据的维数...需要多少轴来唯一地表示A中的列或行。它最多只能min(rows, cols)
,但通常可以少得多。没关系。
答案 3 :(得分:0)
Jama不支持完整的SVD,但只减少了SVD。它相当于Matlab svd(B,0)或svd(B,'econ')。再见