Проверка положительной определенности или положительный semidefiniteness

Я хочу проверить, является ли матрица положительно определенной или положительной полуопределенной с помощью Python.

Как я могу это сделать? Есть ли специальная функция в SciPy для этого или в других модулях?

5 ответов


Я полагаю, вы уже знаете, что ваша матрица симметрична.

хороший тест на положительную определенность (на самом деле стандартный!), чтобы попытаться вычислить его холеского. Он преуспевает, если ваша матрица положительно определена.

Это самый прямой способ, так как для него требуется o(n^3) операций (с небольшой константой), и вам понадобится по крайней мере n матрично-векторных умножений для проверки "напрямую".


разложение Холецкого является хорошим вариантом, если вы работаете с положительно определенной (ПД) матриц.

однако он выдает следующую ошибку на positive semi-определенная матрица (PSD) , скажи,

A = np.zeros((3,3)) // the all-zero matrix is a PSD matrix
np.linalg.cholesky(A)
LinAlgError: Matrix is not positive definite -
Cholesky decomposition cannot be computed

для PSD-матриц вы можете использовать eigh() scipy/numpy, чтобы проверить, что все собственные значения неотрицательны.

>> E,V = scipy.linalg.eigh(np.zeros((3,3)))
>> E
array([ 0.,  0.,  0.])

однако, вы, скорее всего, столкнетесь с проблемами численной стабильности. Чтобы преодолеть их, вы можете использовать следующее функция.

def isPSD(A, tol=1e-8):
  E,V = scipy.linalg.eigh(A)
  return np.all(E > -tol)

который возвращает True для матриц, которые приблизительно PSD до заданного допуска.


Проверьте, все ли собственные значения симметрической матрицы A неотрицательны занимает много времени, если A очень большой, в то время как модуль scipy.sparse.linalg.arpack обеспечивает хорошее решение, так как можно настроить возвращаемые собственные значения, указав параметры.(см. Scipy.sparse.linalg.arpack для получения дополнительной информации)

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

from scipy.sparse.linalg import arpack
def isPSD(A, tol = 1e-8):
    vals, vecs = arpack.eigsh(A, k = 2, which = 'BE') # return the ends of spectrum of A
    return np.all(vals > -tol)

By это нам нужно только вычислить два собственных значения для проверки PSD, я думаю, что это очень полезно для больших A


более простой метод-вычислить детерминанты несовершеннолетних для этого matrx.


одно хорошее решение-вычислить все несовершеннолетние детерминанты и проверить, что они все не отрицательные.