Мінімізація NExpectation для користувацького розподілу в Mathematica


238

Це стосується попереднього питання ще в червні:

Обчислення очікування для користувацького розподілу в Mathematica

У мене є спеціальний змішаний розподіл, визначений за допомогою другого користувальницького дистрибутиву, відповідно до ліній, обговорених @Sashaу ряді відповідей за останній рік.

Код, що визначає розподіли, наступний:

nDist /: CharacteristicFunction[nDist[a_, b_, m_, s_], 
   t_] := (a b E^(I m t - (s^2 t^2)/2))/((I a + t) (-I b + t));
nDist /: PDF[nDist[a_, b_, m_, s_], x_] := (1/(2*(a + b)))*a* 
   b*(E^(a*(m + (a*s^2)/2 - x))* Erfc[(m + a*s^2 - x)/(Sqrt[2]*s)] + 
     E^(b*(-m + (b*s^2)/2 + x))* 
      Erfc[(-m + b*s^2 + x)/(Sqrt[2]*s)]); 
nDist /: CDF[nDist[a_, b_, m_, s_], 
   x_] := ((1/(2*(a + b)))*((a + b)*E^(a*x)* 
        Erfc[(m - x)/(Sqrt[2]*s)] - 
       b*E^(a*m + (a^2*s^2)/2)*Erfc[(m + a*s^2 - x)/(Sqrt[2]*s)] + 
       a*E^((-b)*m + (b^2*s^2)/2 + a*x + b*x)*
        Erfc[(-m + b*s^2 + x)/(Sqrt[2]*s)]))/ E^(a*x);         

nDist /: Quantile[nDist[a_, b_, m_, s_], p_] :=  
 Module[{x}, 
   x /. FindRoot[CDF[nDist[a, b, m, s], x] == #, {x, m}] & /@ p] /; 
  VectorQ[p, 0 < # < 1 &]
nDist /: Quantile[nDist[a_, b_, m_, s_], p_] := 
 Module[{x}, x /. FindRoot[CDF[nDist[a, b, m, s], x] == p, {x, m}]] /;
   0 < p < 1
nDist /: Quantile[nDist[a_, b_, m_, s_], p_] := -Infinity /; p == 0
nDist /: Quantile[nDist[a_, b_, m_, s_], p_] := Infinity /; p == 1
nDist /: Mean[nDist[a_, b_, m_, s_]] := 1/a - 1/b + m;
nDist /: Variance[nDist[a_, b_, m_, s_]] := 1/a^2 + 1/b^2 + s^2;
nDist /: StandardDeviation[ nDist[a_, b_, m_, s_]] := 
  Sqrt[ 1/a^2 + 1/b^2 + s^2];
nDist /: DistributionDomain[nDist[a_, b_, m_, s_]] := 
 Interval[{0, Infinity}]
nDist /: DistributionParameterQ[nDist[a_, b_, m_, s_]] := ! 
  TrueQ[Not[Element[{a, b, s, m}, Reals] && a > 0 && b > 0 && s > 0]]
nDist /: DistributionParameterAssumptions[nDist[a_, b_, m_, s_]] := 
 Element[{a, b, s, m}, Reals] && a > 0 && b > 0 && s > 0
nDist /: Random`DistributionVector[nDist[a_, b_, m_, s_], n_, prec_] :=

    RandomVariate[ExponentialDistribution[a], n, 
    WorkingPrecision -> prec] - 
   RandomVariate[ExponentialDistribution[b], n, 
    WorkingPrecision -> prec] + 
   RandomVariate[NormalDistribution[m, s], n, 
    WorkingPrecision -> prec];

(* Fitting: This uses Mean, central moments 2 and 3 and 4th cumulant \
but it often does not provide a solution *)

nDistParam[data_] := Module[{mn, vv, m3, k4, al, be, m, si},
      mn = Mean[data];
      vv = CentralMoment[data, 2];
      m3 = CentralMoment[data, 3];
      k4 = Cumulant[data, 4];
      al = 
    ConditionalExpression[
     Root[864 - 864 m3 #1^3 - 216 k4 #1^4 + 648 m3^2 #1^6 + 
        36 k4^2 #1^8 - 216 m3^3 #1^9 + (-2 k4^3 + 27 m3^4) #1^12 &, 
      2], k4 > Root[-27 m3^4 + 4 #1^3 &, 1]];
      be = ConditionalExpression[

     Root[2 Root[
           864 - 864 m3 #1^3 - 216 k4 #1^4 + 648 m3^2 #1^6 + 
             36 k4^2 #1^8 - 
             216 m3^3 #1^9 + (-2 k4^3 + 27 m3^4) #1^12 &, 
           2]^3 + (-2 + 
           m3 Root[
              864 - 864 m3 #1^3 - 216 k4 #1^4 + 648 m3^2 #1^6 + 
                36 k4^2 #1^8 - 
                216 m3^3 #1^9 + (-2 k4^3 + 27 m3^4) #1^12 &, 
              2]^3) #1^3 &, 1], k4 > Root[-27 m3^4 + 4 #1^3 &, 1]];
      m = mn - 1/al + 1/be;
      si = 
    Sqrt[Abs[-al^-2 - be^-2 + vv ]];(*Ensure positive*)
      {al, 
    be, m, si}];

nDistLL = 
  Compile[{a, b, m, s, {x, _Real, 1}}, 
   Total[Log[
     1/(2 (a + 
           b)) a b (E^(a (m + (a s^2)/2 - x)) Erfc[(m + a s^2 - 
             x)/(Sqrt[2] s)] + 
        E^(b (-m + (b s^2)/2 + x)) Erfc[(-m + b s^2 + 
             x)/(Sqrt[2] s)])]](*, CompilationTarget->"C", 
   RuntimeAttributes->{Listable}, Parallelization->True*)];

nlloglike[data_, a_?NumericQ, b_?NumericQ, m_?NumericQ, s_?NumericQ] := 
  nDistLL[a, b, m, s, data];

nFit[data_] := Module[{a, b, m, s, a0, b0, m0, s0, res},

      (* So far have not found a good way to quickly estimate a and \
b.  Starting assumption is that they both = 2,then m0 ~= 
   Mean and s0 ~= 
   StandardDeviation it seems to work better if a and b are not the \
same at start. *)

   {a0, b0, m0, s0} = nDistParam[data];(*may give Undefined values*)

     If[! (VectorQ[{a0, b0, m0, s0}, NumericQ] && 
       VectorQ[{a0, b0, s0}, # > 0 &]),
            m0 = Mean[data];
            s0 = StandardDeviation[data];
            a0 = 1;
            b0 = 2;];
   res = {a, b, m, s} /. 
     FindMaximum[
       nlloglike[data, Abs[a], Abs[b], m,  
        Abs[s]], {{a, a0}, {b, b0}, {m, m0}, {s, s0}},
               Method -> "PrincipalAxis"][[2]];
      {Abs[res[[1]]], Abs[res[[2]]], res[[3]], Abs[res[[4]]]}];

nFit[data_, {a0_, b0_, m0_, s0_}] := Module[{a, b, m, s, res},
      res = {a, b, m, s} /. 
     FindMaximum[
       nlloglike[data, Abs[a], Abs[b], m, 
        Abs[s]], {{a, a0}, {b, b0}, {m, m0}, {s, s0}},
               Method -> "PrincipalAxis"][[2]];
      {Abs[res[[1]]], Abs[res[[2]]], res[[3]], Abs[res[[4]]]}];

dDist /: PDF[dDist[a_, b_, m_, s_], x_] := 
  PDF[nDist[a, b, m, s], Log[x]]/x;
dDist /: CDF[dDist[a_, b_, m_, s_], x_] := 
  CDF[nDist[a, b, m, s], Log[x]];
dDist /: EstimatedDistribution[data_, dDist[a_, b_, m_, s_]] := 
  dDist[Sequence @@ nFit[Log[data]]];
dDist /: EstimatedDistribution[data_, 
   dDist[a_, b_, m_, 
    s_], {{a_, a0_}, {b_, b0_}, {m_, m0_}, {s_, s0_}}] := 
  dDist[Sequence @@ nFit[Log[data], {a0, b0, m0, s0}]];
dDist /: Quantile[dDist[a_, b_, m_, s_], p_] := 
 Module[{x}, x /. FindRoot[CDF[dDist[a, b, m, s], x] == p, {x, s}]] /;
   0 < p < 1
dDist /: Quantile[dDist[a_, b_, m_, s_], p_] :=  
 Module[{x}, 
   x /. FindRoot[ CDF[dDist[a, b, m, s], x] == #, {x, s}] & /@ p] /; 
  VectorQ[p, 0 < # < 1 &]
dDist /: Quantile[dDist[a_, b_, m_, s_], p_] := -Infinity /; p == 0
dDist /: Quantile[dDist[a_, b_, m_, s_], p_] := Infinity /; p == 1
dDist /: DistributionDomain[dDist[a_, b_, m_, s_]] := 
 Interval[{0, Infinity}]
dDist /: DistributionParameterQ[dDist[a_, b_, m_, s_]] := ! 
  TrueQ[Not[Element[{a, b, s, m}, Reals] && a > 0 && b > 0 && s > 0]]
dDist /: DistributionParameterAssumptions[dDist[a_, b_, m_, s_]] := 
 Element[{a, b, s, m}, Reals] && a > 0 && b > 0 && s > 0
dDist /: Random`DistributionVector[dDist[a_, b_, m_, s_], n_, prec_] :=
   Exp[RandomVariate[ExponentialDistribution[a], n, 
     WorkingPrecision -> prec] - 
       RandomVariate[ExponentialDistribution[b], n, 
     WorkingPrecision -> prec] + 
    RandomVariate[NormalDistribution[m, s], n, 
     WorkingPrecision -> prec]];

Це дозволяє мені підходити до параметрів розподілу та генерувати файли PDF та CDF . Приклад сюжетів:

Plot[PDF[dDist[3.77, 1.34, -2.65, 0.40], x], {x, 0, .3}, 
 PlotRange -> All]
Plot[CDF[dDist[3.77, 1.34, -2.65, 0.40], x], {x, 0, .3}, 
 PlotRange -> All]

введіть тут опис зображення

Тепер я визначив а functionдля обчислення середньої залишкової тривалості ( пояснення див. У цьому питанні ).

MeanResidualLife[start_, dist_] := 
 NExpectation[X \[Conditioned] X > start, X \[Distributed] dist] - 
  start
MeanResidualLife[start_, limit_, dist_] := 
 NExpectation[X \[Conditioned] start <= X <= limit, 
   X \[Distributed] dist] - start

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

Тепер мені потрібно знайти мінімум MeanResidualLifeфункції для того ж розподілу (або деяку його варіацію) або мінімізувати його.

Я спробував кілька варіантів цього:

FindMinimum[MeanResidualLife[x, dDist[3.77, 1.34, -2.65, 0.40]], x]
FindMinimum[MeanResidualLife[x, 1, dDist[3.77, 1.34, -2.65, 0.40]], x]

NMinimize[{MeanResidualLife[x, dDist[3.77, 1.34, -2.65, 0.40]], 
  0 <= x <= 1}, x]
NMinimize[{MeanResidualLife[x, 1, dDist[3.77, 1.34, -2.65, 0.40]], 0 <= x <= 1}, x]

Вони або здаються запущеними назавжди, або натрапляють на:

Power :: infy: зустрічається нескінченний вираз 1 / 0. >>

MeanResidualLifeФункція застосовується до більш простому , але так само фасонного розподілу показує , що вона має єдиний мінімум:

Plot[PDF[LogNormalDistribution[1.75, 0.65], x], {x, 0, 30}, 
 PlotRange -> All]
Plot[MeanResidualLife[x, LogNormalDistribution[1.75, 0.65]], {x, 0, 
  30},
 PlotRange -> {{0, 30}, {4.5, 8}}]

введіть тут опис зображення

Також обидва:

FindMinimum[MeanResidualLife[x, LogNormalDistribution[1.75, 0.65]], x]
FindMinimum[MeanResidualLife[x, 30, LogNormalDistribution[1.75, 0.65]], x]

дайте мені відповіді (якщо спочатку з купою повідомлень) при використанні з LogNormalDistribution.

Будь-які думки, як змусити це працювати для описаного вище користувацького розподілу?

Чи потрібно додати обмеження чи параметри?

Чи потрібно визначати щось інше у визначеннях користувацьких розподілів?

Можливо, FindMinimumабо NMinimizeпросто потрібно бігти довше (я запускав їх майже годину безрезультатно). Якщо так, мені просто потрібен спосіб прискорити пошук мінімуму функції? Будь-які пропозиції про те, як?

Чи Mathematicaє інший спосіб це зробити?

Додано 9 лютого 17:50 EST:

Будь-який бажаючий може завантажити презентацію Олександра Павлика про створення дистрибутивів у Математиці з семінару Wolfram Technology Conference 2011 «Створіть власний дистрибутив» тут . Завантаження включає ноутбук, 'ExampleOfParametricDistribution.nb'який, здається, викладає всі фрагменти, необхідні для створення дистрибутива, який можна використовувати, як дистрибутиви, що постачаються з Mathematica.

Це може дати відповідь.


9
Не експерт з математики, але в інших місцях я стикався з подібними проблемами. Здається, що у вас виникають проблеми, коли ваш домен починається з 0. Спробуйте почати з 0,1 і вище та подивіться, що відбувається.
Makketronix

7
@Makketronix - Дякую за це. Прикольна синхронність, враховуючи, що я почав переглядати це через 3 роки.
Ягра

8
Я не впевнений, що я можу вам допомогти, але ви можете спробувати задати запит на специфічному для Mathematica стартовому потоці . Удачі!
Олівія Лелека


1
На сайті zbmath.org є маса статей про це, на які можна очікувати
Іван V

Відповіді:


11

Наскільки я бачу, проблема (як ви вже писали) MeanResidualLifeвимагає тривалого часу для обчислення навіть для однієї оцінки. Тепер FindMinimumабо подібні функції намагаються знайти мінімум функції. Пошук мінімуму вимагає або встановити першу похідну функції нуля і вирішити рішення. Оскільки ваша функція є досить складною (і, ймовірно, не диференційованою), друга можливість - це зробити числове мінімізація, що вимагає багатьох оцінок вашої функції. Ерго, це дуже дуже повільно.

Я б запропонував спробувати це без магії Mathematica.

Спочатку давайте подивимося, що це MeanResidualLifeтаке, як ви його визначили. NExpectationабо Expectationобчислити очікуване значення . Для очікуваного значення нам потрібен лише PDFваш розподіл. Давайте витягнемо це з вашого визначення вище в прості функції:

pdf[a_, b_, m_, s_, x_] := (1/(2*(a + b)))*a*b*
    (E^(a*(m + (a*s^2)/2 - x))*Erfc[(m + a*s^2 - x)/(Sqrt[2]*s)] + 
    E^(b*(-m + (b*s^2)/2 + x))*Erfc[(-m + b*s^2 + x)/(Sqrt[2]*s)])
pdf2[a_, b_, m_, s_, x_] := pdf[a, b, m, s, Log[x]]/x;

Якщо ми побудуємо pdf2, він виглядає точно як ваш сюжет

Plot[pdf2[3.77, 1.34, -2.65, 0.40, x], {x, 0, .3}]

Сюжет PDF

Тепер до очікуваного значення. Якщо я правильно це зрозумів, нам доведеться інтегрувати x * pdf[x]з -infдо +infдля нормального очікуваного значення.

x * pdf[x] виглядає наче

Plot[pdf2[3.77, 1.34, -2.65, 0.40, x]*x, {x, 0, .3}, PlotRange -> All]

Сюжет x * PDF

і очікуване значення -

NIntegrate[pdf2[3.77, 1.34, -2.65, 0.40, x]*x, {x, 0, \[Infinity]}]
Out= 0.0596504

Але оскільки ви хочете, щоб очікуване значення між a startі +infнам потрібно інтегрувати в цьому діапазоні, а оскільки PDF потім більше не інтегрується до 1 в цьому меншому інтервалі, я думаю, нам доведеться нормалізувати результат, поділяючи на інтеграл PDF в цей діапазон. Тож я здогадуюсь про очікуване значення ліворуч

expVal[start_] := 
    NIntegrate[pdf2[3.77, 1.34, -2.65, 0.40, x]*x, {x, start, \[Infinity]}]/
    NIntegrate[pdf2[3.77, 1.34, -2.65, 0.40, x], {x, start, \[Infinity]}]

І за те, що MeanResidualLifeти startвід неї віднімаєш , даючи

MRL[start_] := expVal[start] - start

Які сюжети як

Plot[MRL[start], {start, 0, 0.3}, PlotRange -> {0, All}]

Сюжет середнього залишкового життя

Виглядає правдоподібно, але я не експерт. Отже, нарешті, ми хочемо мінімізувати її, тобто знайти те, startдля якого ця функція є локальним мінімумом. Здається, що мінімум становить близько 0,05, але давайте знайдемо більш точне значення, починаючи з цієї здогадки

FindMinimum[MRL[start], {start, 0.05}]

і після деяких помилок (ваша функція не визначена нижче 0, тому я думаю, що мінімізатор трохи натискає в тому забороненому регіоні) ми отримуємо

{0.0418137, {start -> 0.0584312}}

Таким чином, оптимум повинен бути при start = 0.0584312середньому залишковому терміні 0.0418137.

Я не знаю, чи правильно це, але це здається правдоподібно.


+1 - Щойно я це побачив, тому мені потрібно буде це пропрацювати, але я думаю, що те, як ви розділили проблему на вирішальні етапи, має багато сенсу. Також сюжет вашої функції MRL, безумовно, виглядає на місці. Велике спасибі, я повернусь до цього, як тільки зможу встигнути вивчити вашу відповідь.
Jagra
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.