Представление непрерывного распределения вероятностей - PullRequest
22 голосов
/ 28 декабря 2008

У меня проблема с набором функций непрерывного распределения вероятностей, большинство из которых определяются эмпирически (например, время отправления, время прохождения). Мне нужен какой-то способ взять два из этих PDF-файлов и сделать арифметику с ними. Например. если у меня есть два значения x, взятых из PDF X, и y, взятых из PDF Y, мне нужно получить PDF для (x + y) или любую другую операцию f (x, y).

Аналитическое решение невозможно, поэтому я ищу какое-то представление PDF-файлов, которое позволяет такие вещи. Очевидным (но вычислительно дорогим) решением является метод Монте-Карло: генерировать множество значений x и y, а затем просто измерять f (x, y). Но это занимает слишком много процессорного времени.

Я действительно думал о представлении PDF в виде списка диапазонов, где каждый диапазон имеет примерно равную вероятность, эффективно представляя PDF как объединение списка равномерных распределений. Но я не вижу, как их объединить.

Есть ли у кого-нибудь хорошие решения этой проблемы?

Редактировать: Цель состоит в том, чтобы создать мини-язык (также известный как предметно-ориентированный язык) для работы с PDF-файлами. Но сначала мне нужно разобраться в базовом представлении и алгоритмах.

Редактировать 2: dmckee предлагает реализацию гистограммы. Это то, к чему я шел с моим списком унифицированных дистрибутивов. Но я не вижу, как их объединить для создания новых дистрибутивов. В конечном итоге мне нужно найти такие вещи, как P (x

Редактировать 3: У меня есть куча гистограмм. Они распределяются неравномерно, потому что я генерирую их из данных о вхождении, поэтому, в основном, если у меня есть 100 выборок и мне нужно десять точек на гистограмме, я выделяю 10 выборок для каждого столбца и делаю столбцы переменной ширины, но постоянной площади.

Я понял, что для добавления PDF-файлов вы их сверните, и для этого я взялся за математику. Когда вы сворачиваете два равномерных распределения, вы получаете новое распределение с тремя разделами: более широкое равномерное распределение все еще там, но с треугольником, прикрепленным с каждой стороны шириной более узкого. Так что, если я сверну каждый элемент X и Y, я получу кучу таких, все перекрываются. Теперь я пытаюсь выяснить, как сложить их все, а затем получить гистограмму, которая является наилучшим приближением к ней.

Я начинаю задумываться, не была ли Монте-Карло такой плохой идеей.

Редактировать 4: В этой статье обсуждаются свертки равномерных распределений в некоторых деталях. В общем, вы получаете «трапециевидное» распределение. Поскольку каждый «столбец» в гистограммах представляет собой равномерное распределение, я надеялся, что проблему можно решить путем свертки этих столбцов и суммирования результатов.

Однако результат значительно сложнее, чем входы, а также включает в себя треугольники. Редактировать 5: [Неверный материал удален]. Но если эти трапеции приближаются к прямоугольникам с одинаковой площадью, тогда вы получите правильный ответ, и уменьшение количества прямоугольников в результате выглядит довольно просто. Это может быть решением, которое я пытался найти.

Редактировать 6: Решено! Вот окончательный код Haskell для этой проблемы:

-- | Continuous distributions of scalars are represented as a
-- | histogram where each bar has approximately constant area but
-- | variable width and height.  A histogram with N bars is stored as
-- | a list of N+1 values.
data Continuous = C {
      cN :: Int,
      -- ^ Number of bars in the histogram.
      cAreas :: [Double],
      -- ^ Areas of the bars.  @length cAreas == cN@
      cBars :: [Double]
      -- ^ Boundaries of the bars.  @length cBars == cN + 1@
    } deriving (Show, Read)


{- | Add distributions.  If two random variables @vX@ and @vY@ are
taken from distributions @x@ and @y@ respectively then the
distribution of @(vX + vY)@ will be @(x .+. y).

This is implemented as the convolution of distributions x and y.
Each is a histogram, which is to say the sum of a collection of
uniform distributions (the "bars").  Therefore the convolution can be
computed as the sum of the convolutions of the cross product of the
components of x and y.

When you convolve two uniform distributions of unequal size you get a
trapezoidal distribution. Let p = p2-p1, q - q2-q1.  Then we get:


>   |                              |
>   |     ______                   |
>   |     |    |           with    |  _____________
>   |     |    |                   |  |           |
>   +-----+----+-------            +--+-----------+-
>         p1   p2                     q1          q2
> 
>  gives    h|....... _______________
>            |       /:             :\
>            |      / :             : \                1
>            |     /  :             :  \     where h = -
>            |    /   :             :   \              q
>            |   /    :             :    \
>            +--+-----+-------------+-----+-----
>             p1+q1  p2+q1       p1+q2   p2+q2

However we cannot keep the trapezoid in the final result because our
representation is restricted to uniform distributions.  So instead we
store a uniform approximation to the trapezoid with the same area:

>           h|......___________________
>            |     | /               \ |
>            |     |/                 \|
>            |     |                   |
>            |    /|                   |\
>            |   / |                   | \
>            +-----+-------------------+--------
>               p1+q1+p/2          p2+q2-p/2

-}
(.+.) :: Continuous -> Continuous -> Continuous
c .+. d = C {cN     = length bars - 1,
             cBars  = map fst bars, 
             cAreas = zipWith barArea bars (tail bars)}
    where
      -- The convolve function returns a list of two (x, deltaY) pairs.
      -- These can be sorted by x and then sequentially summed to get
      -- the new histogram.  The "b" parameter is the product of the
      -- height of the input bars, which was omitted from the diagrams
      -- above.
      convolve b c1 c2 d1 d2 =
          if (c2-c1) < (d2-d1) then convolve1 b c1 c2 d1 d2 else convolve1 b d1 
d2 c1 c2
      convolve1 b p1 p2 q1 q2 = 
          [(p1+q1+halfP, h), (p2+q2-halfP, (-h))]
               where 
                 halfP = (p2-p1)/2
                 h = b / (q2-q1)
      outline = map sumGroup $ groupBy ((==) `on` fst) $ sortBy (comparing fst) 
$ concat
                [convolve (areaC*areaD) c1 c2 d1 d2 |
                 (c1, c2, areaC) <- zip3 (cBars c) (tail $ cBars c) (cAreas c),
                 (d1, d2, areaD) <- zip3 (cBars d) (tail $ cBars d) (cAreas d)
                ]
      sumGroup pairs = (fst $ head pairs, sum $ map snd pairs)

      bars = tail $ scanl (\(_,y) (x2,dy) -> (x2, y+dy)) (0, 0) outline
      barArea (x1, h) (x2, _) = (x2 - x1) * h

Другие операторы оставлены в качестве упражнения для читателя.

Ответы [ 10 ]

16 голосов
/ 05 апреля 2011

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

[Я буду использовать термины «мера» и «распределение» взаимозаменяемо. Кроме того, мой Хаскелл ржавый, и я прошу вас простить меня за неточность в этой области.]

Распределения вероятностей действительно codata .

Пусть мю - мера вероятности. Единственное, что вы можете сделать с мерой, это интегрировать ее с тестовой функцией (это одно из возможных математических определений «меры»). Обратите внимание, что это то, что вы в конечном итоге будете делать: например, интеграция против идентичности принимает среднее значение:

mean :: Measure -> Double
mean mu = mu id

другой пример:

variance :: Measure -> Double
variance mu = (mu $ \x -> x ^ 2) - (mean mu) ^ 2

другой пример, который вычисляет P (mu

cdf :: Measure -> Double -> Double
cdf mu x = mu $ \z -> if z < x then 1 else 0

Это предполагает подход по дуальности.

Тип Measure должен обозначать тип (Double -> Double) -> Double. Это позволяет моделировать результаты моделирования MC, числовой / символьной квадратуры по PDF и т. Д. Например, функция

empirical :: [Double] -> Measure
empirical h:t f = (f h) + empirical t f

возвращает интеграл f от эмпирической меры , полученной, например,. MC выборка. Также

from_pdf :: (Double -> Double) -> Measure
from_pdf rho f = my_favorite_quadrature_method rho f

построить меры из (регулярных) плотностей.

Теперь хорошие новости. Если mu и nu - две меры, то свертка mu ** nu определяется как:

(mu ** nu) f = nu $ \y -> (mu $ \x -> f $ x + y)

Итак, учитывая две меры, вы можете интегрироваться против их свертки.

Также, учитывая случайную величину X закона mu, закон * X дается формулой:

rescale :: Double -> Measure -> Measure
rescale a mu f = mu $ \x -> f(a * x)

Кроме того, распределение phi (X) задается мерой изображения phi_ * X в нашей структуре:

apply :: (Double -> Double) -> Measure -> Measure
apply phi mu f = mu $ f . phi

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

В частности, pushforward является функториальным:

newtype Measure a = (a -> Double) -> Double
instance Functor Measure a where
    fmap f mu = apply f mu

Это тоже монада (упражнение - подсказка: это очень похоже на монаду продолжения. Что такое return? Что является аналогом call/cc?).

Кроме того, в сочетании с каркасом дифференциальной геометрии это, вероятно, можно превратить в нечто, что автоматически вычисляет байесовские апостериорные распределения.

В конце дня вы можете написать что-то вроде

m = mean $ apply cos ((from_pdf gauss) ** (empirical data))

для вычисления среднего значения cos (X + Y), где X имеет pdf gauss, а Y выбрано методом MC, результаты которого data.

6 голосов
/ 14 апреля 2011

Распределения вероятностей образуют монаду; см., например, работу Клэр Джонс , а также документ LICS 1989 года, но идеи восходят к статье Джири 1982 года (DOI 10.1007 / BFb0092872) и записке Лаврера 1962 года, которую я не могу отследить http://permalink.gmane.org/gmane.science.mathematics.categories/6541).

Но я не вижу комонады: нет способа вывести «а» из «(a-> Double) -> Double». Возможно, если вы сделаете это полиморфным - (a-> r) -> r для всех r? (Это продолжение монада.)

2 голосов
/ 23 августа 2012

Я работал над подобными проблемами для своей диссертации.

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

Посмотрите в Приложении C моей диссертации формулы для различных особых случаев операций над распределениями вероятностей. Вы можете найти диссертацию по адресу: http://riso.sourceforge.net

Я написал Java-код для выполнения этих операций. Вы можете найти код по адресу: https://sourceforge.net/projects/riso

2 голосов
/ 28 декабря 2008

Есть что-нибудь, что мешает вам использовать для этого мини-язык?

Под этим я подразумеваю определение языка, который позволяет вам писать f = x + y и оценивает f для вас так же, как написано. И аналогично для g = x * z, h = y(x) и т. Д. до тошноты . (Я предлагаю семантику призвать оценщика выбрать случайное число для каждого внутреннего PDF-файла, появляющегося в RHS во время оценки, и не пытаться понять составленную форму полученных PDF-файлов. Это может быть недостаточно быстро. .)


Предполагая, что вы понимаете пределы точности, которые вам нужны, вы можете довольно просто представить PDF-файл с помощью гистограммы или сплайна (первый случай - вырожденный, а второй - позже). Если вам нужно смешать аналитически определенные PDF-файлы с экспериментально определенными, вам придется добавить механизм типов.


Гистограмма - это просто массив, содержимое которого представляет частоту в определенной области входного диапазона. Вы не сказали, если у вас есть языковые предпочтения, поэтому я предполагаю что-то вроде c. Вам необходимо знать структуру бина (размеры униформ просты, но не всегда оптимальны), включая верхние и нижние пределы и, возможно, нормализацию:

struct histogram_struct {
  int bins; /* Assumed to be uniform */
  double low;
  double high;
  /* double normalization; */    
  /* double *errors; */ /* if using, intialize with enough space, 
                         * and store _squared_ errors
                         */
  double contents[];
};

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

1 голос
/ 30 декабря 2008

Другое предложение - использовать плотности ядра . Особенно, если вы используете ядра Гаусса, то с ними может быть относительно легко работать ... за исключением того, что дистрибутивы быстро увеличиваются в размере без заботы. В зависимости от применения могут использоваться дополнительные методы аппроксимации, такие как выборка важности .

1 голос
/ 30 декабря 2008

Я думаю, что гистограммы или список областей 1 / N - хорошая идея. Ради аргумента, я предполагаю, что у вас будет фиксированное N для всех дистрибутивов.

Используйте бумагу, которую вы связали, отредактируйте 4 для создания нового дистрибутива. Затем аппроксимируйте его новым распределением N-элементов.

Если вы не хотите исправлять N, это еще проще. Возьмите каждый выпуклый многоугольник (трапецию или треугольник) в новом сгенерированном распределении и аппроксимируйте его равномерным распределением.

1 голос
/ 29 декабря 2008

Некоторые начальные мысли:

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

Во-вторых, представление в виде гистограмм (т. Е. Эмпирических PDF-файлов) проблематично, так как вам приходится выбирать размер корзины. Этого можно избежать, сохранив вместо этого накопительное распределение, т. Е. Эмпирический CDF. (Фактически, вы затем сохраняете возможность воссоздать полный набор данных выборок, на которых основано эмпирическое распределение.)

Вот некрасивый код Mathematica, который берет список выборок и возвращает эмпирический CDF, а именно список пар значение-вероятность. Запустите вывод этого через ListPlot, чтобы увидеть график эмпирического CDF.

empiricalCDF[t_] := Flatten[{{#[[2,1]],#[[1,2]]},#[[2]]}&/@Partition[Prepend[Transpose[{#[[1]], Rest[FoldList[Plus,0,#[[2]]]]/Length[t]}&[Transpose[{First[#],Length[#]}&/@ Split[Sort[t]]]]],{Null,0}],2,1],1]

Наконец, вот некоторая информация о комбинировании дискретных распределений вероятностей:

http://www.dartmouth.edu/~chance/teaching_aids/books_articles/probability_book/Chapter7.pdf

1 голос
/ 28 декабря 2008

Пара ответов:

1) Если у вас есть эмпирически определенные файлы PDF, то у вас либо есть гистограммы, либо у вас есть приближение к параметрическому PDF. PDF - это непрерывная функция, и у вас нет бесконечных данных ...

2) Предположим, что переменные независимы. Тогда, если вы сделаете PDF-файл дискретным, тогда P (f (x, y)) = f (x, y) p (x, y) = f (x, y) p (x) p (y) суммируется по всем комбинациям x и y, так что f (x, y) соответствует вашей цели.

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

Если переменные не являются независимыми, у вас больше проблем, и я думаю, что вы должны использовать copulas .

Я думаю, что определять свой собственный мини-язык и т. Д. - это излишне. Вы можете сделать это с массивами ...

1 голос
/ 28 декабря 2008

Автономная мобильная робототехника имеет дело с аналогичной проблемой локализации и навигации, в частности Марковская локализация и Фильтр Калмана (датчик слияния). См. Например, экспериментальное сравнение методов локализации продолжено .

Еще один подход, который вы можете позаимствовать у мобильных роботов, - это планирование пути с использованием потенциальных полей.

0 голосов
/ 28 декабря 2008

Если вы хотите повеселиться, попробуйте представить их символически, как это сделал бы Maple или Mathemetica. Maple использует ориентированные ациклические графы, в то время как Matematica использует подход типа list / lisp (я верю, но это было долгое время, так как я даже думал об этом).

Сделайте все ваши манипуляции символически, затем в конце протолкните числовые значения. (Или просто найдите способ запустить его в оболочке и выполнить вычисления).

Paul.

...