Math.Net 错误 'Matrix must be positive definite'

Math.Net error 'Matrix must be positive definite'

我尝试使用 Cholesky 分解求解最小二乘问题。

我收到一个错误,'Matrix must be positive definite'。 我已确保矩阵 A 是满秩列。另外,我尝试输出这个矩阵,发现可以用numpy计算。

不知道问题出在哪里

C#代码:

var X = A.TransposeThisAndMultiply(A).Cholesky();

矩阵A可以下载here

我反编译了他们的dll和异常

throw new ArgumentException("Matrix must be positive definite.");

对角线上任意一个因子小于0.0时抛出

for (int index = 0; index < factor.RowCount; ++index)
            {
                double d = factor.At(index, index);
                if (d <= 0.0)
                    throw new ArgumentException("Matrix must be positive definite.");

例如 - 给定以下定义

        Matrix<double> m = Matrix<double>.Build.Random(3, 3);

        m[0, 0] = 1;
        m[0, 1] = 12;
        m[0, 2] = 0;

        m[1, 0] = 2;
        m[1,1] = 37;
        m[1, 2] = -43;

        m[2, 0] = 3;
        m[2, 1] = -43;
        m[2, 2] = 98;

[0,0] 和 [1,1] 和 [2,2] 处的因子 - 它们都必须是正数 - 否则你会遇到那个异常

编辑

我已经设法让它按预期工作。我认为问题在于您构建矩阵的方式 - 可能不正确。

这是我的实现:

    {
        FileStream stream = File.Open(@"YOUR_PATH_HERE\A.xlsx", FileMode.Open, FileAccess.Read);
        IExcelDataReader excelReader = ExcelReaderFactory.CreateOpenXmlReader(stream);
        Matrix<double> m = Matrix<double>.Build.Dense(352, 252);
        int row = 0;
        using (var reader = ExcelReaderFactory.CreateReader(stream))
        {
            do
            {
                while (reader.Read())
                {
                    for (int column = 0; column < 252; column++)
                    {
                        var value = reader.GetDouble(column);
                        m[row, column] = value;
                    }
                    row++;
                }
            } while (reader.NextResult());
        }

        excelReader.Close();

        Matrix<double> transpose = m.TransposeThisAndMultiply(m);
        Cholesky<double> p = transpose.Cholesky();
    }

编辑 2

为了使用稀疏矩阵,我们可以强制值只进入对角线

例如:

        using (var reader = ExcelReaderFactory.CreateReader(stream))
        {
            do
            {
                while (reader.Read())
                {
                    for (int column = 0; column < 252; column++)
                    {
                        //var value = reader.GetDouble(column);
                        //m[row, column] = value;

                        if (column == row)
                        {
                            var value = reader.GetDouble(column);
                            m[row, column] = value;
                        }
                    }
                    row++;
                }
            } while (reader.NextResult());
        }

具有以下输出:

请注意,由于原始稀疏矩阵不是正方形,因此我们可能会在此处丢失一些数据。

我实施了上面的程序,但存在可能影响舍入的微小差异,并得到行列式 = 4.9714636E-19。可能没什么大不了的,但这表明结果有点不稳定。考虑到涉及的算术量,这并不奇怪。