Проблема матрицы java jama
Я использую Джама для расчета СВД. Это работает очень хорошо. Если я передам квадратную матрицу. Например 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 ответа
Будьте осторожны, JAMA поддерживает SVD в первую очередь для матриц полного ранга, и если вы прочитаете "readme", вы заметите, что поведение не обязательно корректно для матриц с недостатком ранга (m По сути, причиной вашего исключения ArrayIndexOutOfBounds является строка 486 в Меняя это на: решит проблему. В конечном итоге, что происходит под прикрытием (по крайней мере, для примера Викачу), вы вводите матрицу с Для матрицы A размером m × n с m >= n разложение по сингулярным значениям представляет собой ортогональную матрицу U размером m на n, диагональную матрицу S размером n на n и ортогональную матрицу V размером n на n так что A = US V '. Но это не имеет места в этом случае, потому что создаст матрицу с предполагаемыми строками Короче говоря, переключение на строку, которую я вставил выше, обнаружит размеры U и, как таковое, даст действительный результат независимо от ранга.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
класс это гласит: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
, что больше, чем фактическое измерение массива подложки.
Прочитайте статью вики о 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 вместо всего, что вы используете, и посмотрите, поможет ли это.
Jama не поддерживает полный SVD, а только сокращенный SVD. Это эквивалент Matlab SVD (B,0) или SVD (B,'Econ'). до свидания
Размеры U, S и V не обязательно должны быть такими же, как у A. U будет иметь одинаковое количество строк, а V^T будет иметь одинаковое количество столбцов. Этого достаточно, чтобы воссоздать А по правилам умножения матриц.
Другое измерение (столбцы U, строки V^T и строки / столбцы S) будет "рангом" A (в вашем примере 3). Это, грубо говоря, размерность ваших данных... сколько осей необходимо для уникального представления столбца или строки в A. Это будет самое большее min(rows, cols)
но часто может быть гораздо меньше. Все в порядке.