Как правильно сделать выборку из numpy.random.multivariate_normal (проблема положительно-полуопределенной ковариационной матрицы)

Я надеюсь создать новые "поддельные" данные из данных, которые у меня уже есть с numpy.random.multivariate_normal,

С n сэмплами и d функциями в nFD pandas DataFrame:

means = data.mean(axis=0)
covariances = data.cov()
variances = data.var()
means.shape, covariances.shape, variances.shape

>>> ((16349,), (16349, 16349), (16349,))

Это выглядит хорошо, но ковариационная матрица covariances не является положительным полуопределенным, что является требованием numpy.random.multivariate_normal,

x = np.linalg.eigvals(covariances)

np.all(x >= 0)
>>> False

len([y for y in x if y < 0])  # negative eigenvalues
>>> 4396

len([y for y in x if y > 0])  # positive eigenvalues
>>> 4585

len([y for y in x if y == 0])  # zero eigenvalues.
>>> 7368

Тем не менее, Википедия говорит

Кроме того, каждая ковариационная матрица является положительно-полуопределенной.

Что заставляет меня задуматься о том, дает ли pandas.DataFrame.cov реальную ковариационную матрицу. Вот реализация функции. Похоже, что он в основном откладывается на numpy.cov, который также обещает ковариационную матрицу.

Может кто-нибудь прояснить это для меня? Почему pandas.DataFrame.covs() не положительный полуопределенный?

Обновленный вопрос:

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

Я могу представить, используя pd.DataFrame.cov() выполнение собственной декомпозиции для получения собственных векторов и значений, отсечение значений, а затем умножение этих матриц для получения новой ковариационной матрицы, но это кажется довольно ненадежным. Это делается на практике или есть лучший способ?

1 ответ

Решение

Вероятно, происходит то, что результат является положительно-полуопределенным, с точностью до вычисления. Например:

In [71]: np.linalg.eigvals(np.cov(np.random.random((5,5))))
Out[71]: 
array([  1.87557170e-01,   9.98250875e-02,   6.85211153e-02,
         1.01062281e-02,  -5.99164839e-18])

имеет отрицательное собственное значение, но величина мала.

Так что на вашем месте я бы проверил, что величина нарушений была мала, а затем обрезал до нуля.

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