Ridurre al minimo NExpectation per una distribuzione personalizzata in Mathematica


238

Ciò si riferisce a una domanda precedente di giugno:

Calcolo delle aspettative per una distribuzione personalizzata in Mathematica

Ho una distribuzione mista personalizzata definita usando una seconda distribuzione personalizzata seguendo le linee discusse @Sashain una serie di risposte nell'ultimo anno.

Segue il codice che definisce le distribuzioni:

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]];

Ciò mi consente di adattare i parametri di distribuzione e generare PDF e CDF . Un esempio delle trame:

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]

inserisci qui la descrizione dell'immagine

Ora ho definito un functionper calcolare la vita media residua (vedi questa domanda per una spiegazione).

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

Il primo di questi che non stabilisce un limite come nel secondo richiede molto tempo per il calcolo, ma entrambi funzionano.

Ora devo trovare il minimo della MeanResidualLifefunzione per la stessa distribuzione (o qualche sua variazione) o minimizzarla.

Ho provato diverse varianti su questo:

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]

Questi sembrano funzionare per sempre o imbattersi in:

Potenza :: infy: rilevata espressione infinita 1 / 0. >>

La MeanResidualLifefunzione applicata a una distribuzione più semplice ma di forma simile mostra che ha un unico minimo:

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}}]

inserisci qui la descrizione dell'immagine

Inoltre entrambi:

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

dammi le risposte (se prima con un mucchio di messaggi) quando usato con il LogNormalDistribution.

Qualche idea su come farlo funzionare per la distribuzione personalizzata sopra descritta?

Devo aggiungere vincoli o opzioni?

Devo definire qualcos'altro nelle definizioni delle distribuzioni personalizzate?

Forse FindMinimumo NMinimizeho solo bisogno di correre più a lungo (li ho eseguiti quasi un'ora senza alcun risultato). In tal caso, ho solo bisogno di un modo per accelerare la ricerca del minimo della funzione? Qualche suggerimento su come?

C'è Mathematicaun altro modo per farlo?

Aggiunto il 9 feb 17:50 EST:

Chiunque può scaricare la presentazione di Oleksandr Pavlyk sulla creazione di distribuzioni in Mathematica dal seminario di Wolfram Technology Conference 2011 "Crea la tua distribuzione" qui . I download includono il notebook, 'ExampleOfParametricDistribution.nb'che sembra disporre di tutti i pezzi necessari per creare una distribuzione che si può usare come le distribuzioni fornite con Mathematica.

Potrebbe fornire alcune delle risposte.


9
Non esperto di Mathematica, ma ho riscontrato problemi simili in altri luoghi. Sembra che tu abbia problemi quando il tuo dominio inizia a 0. Prova a iniziare da 0,1 in su e guarda cosa succede.
Makketronix,

7
@Makketronix - Grazie per questo. Divertente sincronicità, dato che ho iniziato a rivisitare questo dopo 3 anni.
Jagra,

8
Non sono sicuro di poterti aiutare, ma potresti provare a chiedere allo stackoverflow specifico di Mathematica . Buona fortuna!
Olivia Stork,


1
Ci sono un sacco di articoli a riguardo su zbmath.org Cerca aspettative
Ivan V

Risposte:


11

Per quanto vedo, il problema è (come hai già scritto), che MeanResidualLiferichiede molto tempo per il calcolo, anche per una singola valutazione. Ora, le FindMinimumfunzioni simili o simili cercano di trovare un minimo per la funzione. Per trovare un minimo è necessario impostare la prima derivata della funzione zero e risolvere una soluzione. Poiché la tua funzione è piuttosto complicata (e probabilmente non differenziabile), la seconda possibilità è quella di fare una minimizzazione numerica, che richiede molte valutazioni della tua funzione. Ergo, è molto molto lento.

Suggerirei di provarlo senza la magia di Mathematica.

Per prima cosa vediamo cos'è MeanResidualLife, come lo hai definito. NExpectationo Expectationcalcola il valore atteso . Per il valore atteso, abbiamo solo bisogno PDFdella tua distribuzione. Estraiamolo dalla tua definizione sopra in semplici funzioni:

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;

Se tracciamo pdf2 sembra esattamente come il tuo diagramma

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

Trama di PDF

Ora al valore atteso. Se ho ben capito dobbiamo integrare x * pdf[x]da -infa +infper un valore atteso normale.

x * pdf[x] sembra

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

Trama di x * PDF

e il valore atteso è

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

Ma dal momento che vuoi il valore atteso tra a starte +infdobbiamo integrarci in questo intervallo, e poiché il PDF non si integra più a 1 in questo intervallo più piccolo, immagino che dobbiamo normalizzare il risultato dividendo per l'integrale del PDF in questa gamma. Quindi la mia ipotesi per il valore atteso di sinistra è

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]}]

E per il MeanResidualLifetuo sottrarre startda esso, dando

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

Quale trama come

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

Trama della vita media residua

Sembra plausibile, ma non sono un esperto. Quindi alla fine vogliamo minimizzarlo, ovvero trovare il startper cui questa funzione è un minimo locale. Il minimo sembra essere intorno a 0,05, ma troviamo un valore più esatto a partire da questa ipotesi

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

e dopo alcuni errori (la tua funzione non è definita sotto 0, quindi immagino che il minimizer spilli un po 'in quella regione proibita) otteniamo

{0,0418137, {inizio -> 0,0584312}}

Quindi l'ottimale dovrebbe avere start = 0.0584312una durata residua media di 0.0418137.

Non so se sia corretto, ma sembra plausibile.


+1 - Ho appena visto questo, quindi dovrò risolverlo, ma penso che il modo in cui hai diviso il problema in passaggi risolvibili abbia molto senso. Inoltre, la trama della tua funzione MRL sembra sicuramente perfetta. Molte grazie, tornerò su questo non appena avrò il tempo di studiare la tua risposta.
Jagra,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.