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.
Смотрите мой комментарий ниже.