У меня относительно большая матрица, из которой я хотел бы вычислить одноразрядную декомпозицию. Использование прямой функции linear/svd
функции core.matrix (с использованием реализации :vectorz
), к сожалению, приводит к исключению из-за-памяти - у моей машины сравнительно мало памяти для dev-машины (8 ГБ, пространство кучи Java установлено на max при 5Гб).Однораздельное разложение разреженной матрицы
матрица имеет размерность [422, 23069]
и относительно редкими (~ 1,74% значений не равны нулю), так что моя следующая попытка была преобразования матрицы к sparse-matrix
:
(def sparse-fs (matrix/sparse-matrix fs))
Это удивительно терпит неудачу с ArrayOutOfBoundsException
в коде Java. Я мог бы обойти эту проблему, создав разреженную матрицу первого и затем установить ненулевые значения:
user> (def sparse-fs (matrix/sparse-matrix [422 23069]))
#'user/sfs
user> (count
(map-indexed
(fn [row line]
(map-indexed
(fn [col val]
(when (not (= val 0.0))
(matrix/mset! sparse-fs row col val)))))
fs))
422
Однако, называя linear/svd
на этой разреженной матрицы также терпит неудачу, так как протокол для СВД, по-видимому, не реализуется:
user> (def svd-fs (linear/svd sparse-fs))
CompilerException java.lang.IllegalArgumentException: No implementation of method: :svd of protocol:
#'clojure.core.matrix.protocols/PSVDDecomposition found for class: mikera.vectorz.Vector2,
В настоящее время у меня нет идей о том, как продвигаться отсюда, и был бы признателен за любые данные о том, как я мог бы подставить мою матрицу (и вычисление svd) в мою относительно небольшую память.
Update: Проблема протокола приходит от меня до сих пор пытается использовать clojure.core.matrix/sparse-matrix
, который предназначение я, видимо, не понимаю. Вместо этого я могу использовать new-sparse-array
, который создает экземпляр, реализующий AMatrix
, для которых реализован протокол разложения:
user> (def foo-sparse (matrix/sparse-matrix [422 23069]))
#'user/foo-sparse
user> (type foo-sparse)
mikera.vectorz.Vector2
user> (matrix/dimensionality foo-sparse)
1
user> (def foo-sparse (matrix/new-sparse-array [422 23069]))
#'user/foo-sparse
user> (matrix/dimensionality foo-sparse)
2
user> (type foo-sparse)
mikera.matrixx.impl.SparseRowMatrix
К сожалению, когда я называю linear/svd
на этой матрице, я вернулся в моем отказе от ошибки памяти:
1. Caused by java.lang.OutOfMemoryError
Java heap space
DoubleArrays.java: 724 mikera.vectorz.util.DoubleArrays/createStorage
Matrix.java: 45 mikera.matrixx.Matrix/<init>
Matrix.java: 56 mikera.matrixx.Matrix/create
Matrix.java: 653 mikera.matrixx.Matrix/createIdentity
BidiagonalRow.java: 174 mikera.matrixx.decompose.impl.bidiagonal.BidiagonalRow/handleU
BidiagonalRow.java: 155 mikera.matrixx.decompose.impl.bidiagonal.BidiagonalRow/getU
BidiagonalRow.java: 115 mikera.matrixx.decompose.impl.bidiagonal.BidiagonalRow/_decompose
BidiagonalRow.java: 78 mikera.matrixx.decompose.impl.bidiagonal.BidiagonalRow/decompose
Bidiagonal.java: 21 mikera.matrixx.decompose.Bidiagonal/decompose
SvdImplicitQr.java: 177 mikera.matrixx.decompose.impl.svd.SvdImplicitQr/bidiagonalization
SvdImplicitQr.java: 154 mikera.matrixx.decompose.impl.svd.SvdImplicitQr/_decompose
SvdImplicitQr.java: 89 mikera.matrixx.decompose.impl.svd.SvdImplicitQr/decompose
SVD.java: 31 mikera.matrixx.decompose.SVD/decompose
matrix_api.clj: 334 mikera.vectorz.matrix-api/eval26238/fn
protocols.cljc: 1150 clojure.core.matrix.protocols$eval21076$fn__21077$G__21067__21084/invoke
linear.cljc: 105 clojure.core.matrix.linear$svd/invoke
Я подозреваю, что это может быть связано с vectorz-clj issue 18 that operations on sparse matrices don't produce sparse results.
Любые альтернативы?
Вместо этого вы можете использовать «Кольт»? Я знаю, что это не совсем то, что вы хотите, но они имеют разреженную поддержку матрицы и SVD. http://dst.lbl.gov/ACSSoftware/colt/api/cern/colt/matrix/linalg/SingularValueDecomposition.html – endbegin