简体   繁体   English

java jama矩阵问题

[英]java jama matrix problem

I am using jama to calculate SVD. 我用jama来计算SVD。 It work very good. 它工作得很好。 If i pass square matrix. 如果我通过方阵。 For example 2x2 or 3x3 etc. matrix. 例如2x2或3x3等矩阵。 But when I pass some thing like this 2x3 or 4x8 it give error . 但是当我传递像2x3或4x8这样的东西时,它会给出错误。 I used all of their example. 我用了他们所有的例子。 They have different constructor to perform the job. 他们有不同的构造函数来执行这项工作。 Also my second question is, I am usded 3x3 matrix and it gave 我的第二个问题是,我用3x3矩阵,它给了

double[][] vals = {{1.,1.,0},{1.,0.,1.},{1.,3.,4.},{6.,4.,8.}};
  Matrix A = new Matrix(vals);

It produced following error: 它产生了以下错误:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3

After that I thaught to use another constructor that is as follow 之后,我需要使用另一个构造函数,如下所示

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);

It produced following output: 它产生了以下输出:

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

It worked for non square matrix. 它适用于非方矩阵。 But it produced wrong results for svd because V and S doesn't have same rows=4 ( I am sorry if i couldn't analyze result properly as i am new for SVD) . 但它为svd产生了错误的结果,因为V和S没有相同的行= 4(如果我不能正确分析结果,我很抱歉,因为我是SVD的新手)。 Any idea? 任何的想法? What should I do? 我该怎么办?

Be careful here, JAMA supports SVD primarily for full rank matrices, and if you read the "readme" you'll notice that the behavior is not necessarily correct for rank deficient (m < n) matrices. 在这里要小心,JAMA主要支持SVD用于满秩矩阵,如果你阅读“自述”,你会注意到行为不一定对于秩不足(m <n)矩阵是正确的。

In essence, what causes your ArrayIndexOutOfBounds exception is line 486 in SingularValueDecomposition : 实质上,导致ArrayIndexOutOfBounds异常的原因是SingularValueDecomposition第486行:

return new Matrix(U,m,Math.min(m+1,n));

Changing this to: 将此更改为:

return new Matrix(U);

will solve the problem. 将解决问题。 Ultimate what happens under the covers (at least for vicatcu's example) is that you inject a matrix with m=4 and n=5 , but notice in the actual output U has dimensions m=4 and n=4 . 最后发生的事情(至少对于vicatcu的例子)是你注入一个m=4n=5的矩阵,但实际输出U中的注意事项是维度m=4n=4 If you read the top of the SingularValueDecomposition class it states: 如果您阅读SingularValueDecomposition类的顶部,它会指出:

For an m-by-n matrix A with m >= n, the singular value decomposition is an m-by-n orthogonal matrix U, an n-by-n diagonal matrix S, and an n-by-n orthogonal matrix V so that A = U S V'. 对于m> = n的m×n矩阵A,奇异值分解是m×n正交矩阵U,n-by-n对角矩阵S和n×n正交矩阵V这样A = U S V'。

But this doesn't hold in this case, because m=4 and n=5 means m<n . 但是在这种情况下这不成立,因为m=4n=5意味着m<n So now since you're passing a rank deficient matrix U has different dimensions than the normal calling case of the SVD class, and as such the statement: 所以现在因为你传递的是秩不足的矩阵,U的维度与SVD类的正常调用情况不同,因此语句如下:

new Matrix(U, m, Math.min(m+1,n))

will create a matrix with assumed rows of m , here 4 (which is correct) and assumed columns n , here Math.min(4+1,5)=5 (which is incorrect). 将创建一个假定行为m的矩阵,这里是4(这是正确的)和假设列n ,这里Math.min(4+1,5)=5 (这是不正确的)。 So: when you go print the matrix and the print routine calls getColumnDimension , the U matrix returns 5 , which is greater than the actual backing array dimension. 因此:当您打印矩阵并且print例程调用getColumnDimension ,U矩阵返回5 ,这大于实际的后备数组维度。

In short, switching to the line I pasted above will detect the dimensions of U, and as such return a valid result regardless of the rank. 简而言之,切换到上面粘贴的线I将检测U的尺寸,因此无论等级如何都返回有效结果。

Read the wiki article on SVD . 阅读SVD上wiki文章 The following code is representative of the example in Section 2. 以下代码代表第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());
    } 
} 

and yields the outputL: 并产生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 

Hope this helps. 希望这可以帮助。 Also, FWIW here is Matlab's output on the same problem: 另外,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

With regards to your first question, the following code produces no error: 关于您的第一个问题,以下代码不会产生错误:

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); 

    }
}

So something else you're doing must be causing it to have an exception. 所以你正在做的其他事情必须导致它有一个例外。 Try using my printMatrix method in place of whatever you are using and see if it helps. 尝试使用我的printMatrix方法代替您正在使用的任何方法,看看它是否有帮助。

Jama don't support full SVD but only reduced SVD. Jama不支持完整的SVD,但仅减少了SVD。 It's equivalent Matlab svd(B,0) or svd(B,'econ'). 它相当于Matlab svd(B,0)或svd(B,'econ')。 Bye 再见

The dimensions of U, S and V do not need to be the same dimensions as A. U will have the same number of rows and V^T will have the same number of columns. U,S和V的尺寸不需要与A的尺寸相同.U将具有相同的行数并且V ^ T将具有相同的列数。 That is sufficient to recreate A by the rules of matrix multiplication. 这足以通过矩阵乘法的规则重新创建A.

The other dimension (columns of U, rows of V^T and rows/columns of S) will be the "rank" of A (in your example 3). 另一个维度(U的列,V ^ T的行和S的行/列)将是A的“等级”(在您的示例3中)。 This is, roughly speaking, the dimensionality of your data...how many axes are needed to uniquely represent a column or row in A. It will be at most min(rows, cols) but can often be much less. 粗略地说,这是数据的维数...需要多少轴来唯一地表示A中的列或行。它最多只能为min(rows, cols)但通常可以少得多。 That is ok. 那没问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM