Кумулятивная вероятность оцененного эмпирического распределения для n-мерных данных - PullRequest
1 голос
/ 22 апреля 2020

Проблема

У меня есть набор данных с 4 числовыми c функциями и 1000 точками данных. Распределение значений неизвестно (numpy randint генерирует одинаковые целые числа, но это только для иллюстрации). Учитывая новый объект данных (4 числа), я хочу найти, какова совокупная вероятность (одно число) этого специфического c объекта данных.

import numpy as np

data = np.random.randint(1, 100, size=(1000, 4))
array([[28, 52, 91, 66],
       [78, 94, 95, 12],
       [60, 63, 43, 37],
       ...,
       [81, 68, 45, 46],
       [14, 38, 91, 46],
       [37, 51, 68, 97]])

new_data = np.random.randint(1, 100, size=(1, 4))
array([[75, 24, 39, 94]])

Я пробовал:

Сципи

Может оценить pdf, не знаю, как оценить кумулятивную вероятность. Возможные способы - симуляция Монте-Карло или интеграция (scipy.integrate.nquad), которая слишком медленная для моего случая. Интегрируйте оценку плотности ядра 2D .

import scipy.stats
kde = scipy.stats.gaussian_kde(data.T)
kde.pdf(new_data)

Scikit-learn

То же, что и выше, не знаю, как оценить совокупную вероятность.

from sklearn.neighbors import KernelDensity
model = KernelDensity()
model.fit(data)
np.exp(model.score_samples(new_data))

Statsmodels

Невозможно что-либо заархивировать, так как это принимает только 1d данные.

from statsmodels.distributions.empirical_distribution import ECDF
ecdf = ECDF(data[:, 0])
ecdf(new_data[0][0])

Вопрос в том, существует быстрый и эффективный способ оценки кумулятивной вероятности для четырехмерного элемента данных, имеющего предоставленные модели scipy или sklearn (предпочтительно)? решить это? Может, вариационные автоэнкодеры это путь к go? Есть ли простые способы решить эту проблему?

1 Ответ

2 голосов
/ 22 апреля 2020

Многомерный ecdf в точке просто вычислит долю наблюдений со значениями, меньшими, чем точка.

Что-то вроде следующего

np.random.seed(0)
data = np.random.randint(1, 100, size=(1000, 4))
new_data = np.random.randint(1, 100, size=(2, 4))

def ecdf_mv(new_data, data):
    new_data = np.atleast_2d(new_data)
    ecdf = []
    for row in new_data:
        ecdf.append((data <= row).all(1).mean())

    return np.asarray(ecdf)

ecdf_mv(new_data, data)

array([0.039, 0.002])

некоторые проверки:

ecdf_mv(np.ones(4) * 100 / 2, data), 0.5**4
(array([0.067]), 0.0625)

marginal = 100 * np.ones((4, 4)) - 50 * np.eye(4)
ecdf_mv(marginal, data)
array([0.521, 0.515, 0.502, 0.54 ])

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

...