我遇到了完全相同的问题,我的解决方案是:
- 在矩阵上使用Apache Commons Math运行 SVD
- 截断对角矩阵以仅保留前k个奇异值
- 截断其他两个矩阵,仅将前k列作为第一个矩阵,将前k行作为最后一个矩阵
- 将三个矩阵相乘
您获得的是原始矩阵的截断 SVD。
下面是完整的解决方案,使用具有数千行/列的矩阵进行测试。
public static double[][] getTruncatedSVD(double[][] matrix, final int k) {
SingularValueDecomposition svd = new SingularValueDecomposition(new Array2DRowRealMatrix(matrix));
double[][] truncatedU = new double[svd.getU().getRowDimension()][k];
svd.getU().copySubMatrix(0, truncatedU.length - 1, 0, k - 1, truncatedU);
double[][] truncatedS = new double[k][k];
svd.getS().copySubMatrix(0, k - 1, 0, k - 1, truncatedS);
double[][] truncatedVT = new double[k][svd.getVT().getColumnDimension()];
svd.getVT().copySubMatrix(0, k - 1, 0, truncatedVT[0].length - 1, truncatedVT);
RealMatrix approximatedSvdMatrix = (new Array2DRowRealMatrix(truncatedU)).multiply(new Array2DRowRealMatrix(truncatedS)).multiply(new Array2DRowRealMatrix(truncatedVT));
return approximatedSvdMatrix.getData();
}