проблема матрицы Java - PullRequest
       53

проблема матрицы Java

3 голосов
/ 18 января 2010

Я использую Джама для расчета 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). Любая идея? Что мне делать?

Ответы [ 4 ]

4 голосов
/ 18 января 2010

Будьте осторожны, JAMA поддерживает SVD в первую очередь для матриц полного ранга, и если вы прочитаете «readme», вы заметите, что поведение не обязательно корректно для матриц с недостатком ранга (m

По сути, причиной вашего исключения ArrayIndexOutOfBounds является строка 486 в SingularValueDecomposition:

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

Изменение на:

return new Matrix(U);

решит проблему. В конечном счете, то, что происходит под прикрытием (по крайней мере, для примера Викачу), заключается в том, что вы вводите матрицу с m=4 и n=5, но уведомление в фактическом выводе U имеет размеры m=4 и n=4. Если вы читаете верхнюю часть класса SingularValueDecomposition, он гласит:

Для матрицы A размером m на n с m> = n разложение по сингулярному значению имеет вид ортогональная матрица U размером m на n, диагональная матрица S размером n на n и n-на-n ортогональная матрица V, так что A = U S V '.

Но в этом случае это не так, потому что m=4 и n=5 означают m<n. Так что теперь, так как вы передаете матрицу с недостатком ранга, U имеет другие измерения, чем нормальный регистр вызова класса SVD, и, таким образом, оператор:

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

создаст матрицу с предполагаемыми строками m, здесь 4 (что правильно) и предполагаемыми столбцами n, здесь Math.min(4+1,5)=5 (что неверно). Итак: когда вы печатаете матрицу и вызовы подпрограммы печати getColumnDimension, матрица U возвращает 5, что больше фактического размера резервного массива.

Короче говоря, переключение на строку, которую я вставил выше, обнаружит размеры U и, как таковое, даст действительный результат независимо от ранга.

1 голос
/ 18 января 2010

Прочитайте статью вики о 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 вместо всего, что вы используете, и посмотрите, поможет ли это.

0 голосов
/ 23 октября 2013

Jama не поддерживает полный SVD, но только сокращенный SVD.Это эквивалент Matlab SVD (B, 0) или SVD (B, 'Econ').Bye

0 голосов
/ 18 января 2010

Размеры U, S и V не обязательно должны быть такими же, как у A. U будет иметь одинаковое количество строк, а V ^ T будет иметь одинаковое количество столбцов. Этого достаточно, чтобы воссоздать А по правилам умножения матриц.

Другое измерение (столбцы U, строки V ^ T и строки / столбцы S) будет «рангом» A (в вашем примере 3). Грубо говоря, это размерность ваших данных ... сколько осей необходимо для уникального представления столбца или строки в A. Это будет самое большее min(rows, cols), но часто может быть гораздо меньше. Это нормально.

...