Numpy Cholesky разложение LinAlgError

В моей попытке выполнить разложение Холецкого на дисперсионно-ковариационной матрице для двумерного массива периодических граничных условий при определенных комбинациях параметров я всегда получаю LinAlgError: Matrix is not positive definite - Cholesky decomposition cannot be computed, Не уверен, что это numpy.linalg или проблема реализации, так как скрипт прост:

sigma = 3.
U = 4

def FromListToGrid(l_):
    i = np.floor(l_/U)
    j = l_ - i*U
    return np.array((i,j))

Ulist = range(U**2)

Cov = []
for l in Ulist:
    di = np.array([np.abs(FromListToGrid(l)[0]-FromListToGrid(i)[0]) for i, x in enumerate(Ulist)])
    di = np.minimum(di, U-di)

    dj = np.array([np.abs(FromListToGrid(l)[1]-FromListToGrid(i)[1]) for i, x in enumerate(Ulist)])
    dj = np.minimum(dj, U-dj)

    d = np.sqrt(di**2+dj**2)
    Cov.append(np.exp(-d/sigma))
Cov = np.vstack(Cov)

W = np.linalg.cholesky(Cov)

Попытки устранить потенциальные особенности также не смогли решить проблему. Буду признателен за любую оказанную помощь.

2 ответа

Решение

Покопавшись немного глубже в проблеме, я попытался напечатать собственные значения матрицы Cov.

print np.linalg.eigvalsh(Cov)

И ответ оказывается таким

[-0.0801339  -0.0801339   0.12653595  0.12653595  0.12653595  0.12653595 0.14847999  0.36269785  0.36269785  0.36269785  0.36269785  1.09439988 1.09439988  1.09439988  1.09439988  9.6772531 ]

Ага! Обратите внимание на первые два отрицательных собственных значения? Теперь матрица положительно определена тогда и только тогда, когда все ее собственные значения положительны. Итак, проблема с матрицей не в том, что она близка к "нулю", а в том, что она "отрицательная". Чтобы расширить аналогию @duffymo, это линейный алгебра, эквивалентный попытке получить квадратный корень из отрицательного числа.

Теперь попробуем выполнить ту же операцию, но на этот раз со Сципи.

scipy.linalg.cholesky(Cov, lower=True)

И это не говорит чего-то большего

numpy.linalg.linalg.LinAlgError: 12-th leading minor not positive definite

Это говорит о многом (хотя я не мог понять, почему он жалуется на 12-го несовершеннолетнего).

В итоге, матрица не совсем близка к "нулю", но больше похожа на "отрицательную"

Проблема в данных, которые вы ему подаете. Матрица является единственной, в соответствии с решателем. Это означает нулевой или почти нулевой диагональный элемент, поэтому инверсия невозможна.

Было бы легче диагностировать, если бы вы могли предоставить небольшую версию матрицы.

Нулевые диагонали - не единственный способ создать особенность. Если два ряда пропорциональны друг другу, то вам не нужны оба в решении; они излишни. Это сложнее, чем просто искать нули по диагонали.

Если ваша матрица верна, у вас есть непустое пустое пространство. Вам нужно будет изменить алгоритмы на что-то вроде SVD.

Смотрите мой комментарий ниже.

Другие вопросы по тегам