2016-09-08 1 views
0

J'ai une table de comptes de résultats binaires et je voudrais ajuster une distribution binomiale bêta pour estimer les paramètres $ \ alpha $ et $ \ beta $, mais j'ai des erreurs quand j'essaie de échantillonner la distribution du modèle ainsi que je fais pour les autres cas:Utilisation de BetaBinomial dans PyMC3

import pymc3 as pm 
import pandas as pd 

df = pd.read_csv('~/data.csv', low_memory=False) 
df = df[df.Clicks >= 0] 

C0=df.C.values 
I0=df.N.values 
N0 = C0 + I0 

with pm.Model() as model: 
    C=pm.constant(C0) 
    I=pm.constant(I0) 
    C1=pm.constant(C0 + 1) 
    I1=pm.constant(I0 + 1) 
    N=pm.constant(N0) 
    alpha = pm.Exponential('alpha', 1/(C0.sum()+1)) 
    beta = pm.Exponential('beta', 1/(I0.sum()+1)) 
    obs = pm.BetaBinomial('obs', alpha, beta, N, observed=C0) 


with model: 
    advi_fit = pm.variational.advi(n=int(1e4)) 
    trace1 = pm.variational.sample_vp(advi_fit, draws=int(1e4)) 

pm.traceplot(trace1[::10]) 

with model: 
    step = pm.NUTS() 
    #step = pm.Metropolis() # <== same problem 
    trace2 = pm.sample(int(1e3), step) 

pm.traceplot(trace2[::10]) 

Dans les deux cas, l'échantillonnage échoue avec:

MissingInputError: ("An input of the graph, used to compute Elemwise{neg,no_inplace}(P_logodds_), was not provided and not given a value.Use the Theano flag exception_verbosity='high',for more information on this error.", P_logodds 

Dans le cas advi la trace complète de la pile est:


MissingInputError       Traceback (most recent call last) 
<ipython-input-46-8947c7c798e5> in <module>() 
----> 1 import codecs, os;__pyfile = codecs.open('''/tmp/py7996Jip''', encoding='''utf-8''');__code = __pyfile.read().encode('''utf-8''');__pyfile.close();os.remove('''/tmp/py7996Jip''');exec(compile(__code, '''/home/dmahler/Scripts/adops-bayes2.py''', 'exec')); 

/home/dmahler/Scripts/adops-bayes2.py in <module>() 
    59  advi_fit = pm.variational.advi(n=int(J*6.4e4), learning_rate=1e-3/J, epsilon=1e-8, accurate_elbo=False) 
    60  #advi_fit = pm.variational.advi_minibatch(minibatch_RVs=[alpha, beta, p], minibatch_tensors=[C,I,N]) 
---> 61  trace = pm.variational.sample_vp(advi_fit, draws=int(2e4)) 
    62 
    63 pm.traceplot(trace[::10]) 

/home/dmahler/Anaconda/lib/python2.7/site-packages/pymc3/variational/advi.pyc in sample_vp(vparams, draws, model, local_RVs, random_seed, hide_transformed) 
    317 
    318  varnames = [str(var) for var in model.unobserved_RVs] 
--> 319  trace = NDArray(model=model, vars=vars_sampled) 
    320  trace.setup(draws=draws, chain=0) 
    321 

/home/dmahler/Anaconda/lib/python2.7/site-packages/pymc3/backends/ndarray.pyc in __init__(self, name, model, vars) 
    21  """ 
    22  def __init__(self, name=None, model=None, vars=None): 
---> 23   super(NDArray, self).__init__(name, model, vars) 
    24   self.draw_idx = 0 
    25   self.draws = None 

/home/dmahler/Anaconda/lib/python2.7/site-packages/pymc3/backends/base.pyc in __init__(self, name, model, vars) 
    34   self.vars = vars 
    35   self.varnames = [var.name for var in vars] 
---> 36   self.fn = model.fastfn(vars) 
    37 
    38 

/home/dmahler/Anaconda/lib/python2.7/site-packages/pymc3/model.pyc in fastfn(self, outs, mode, *args, **kwargs) 
    374   Compiled Theano function as point function. 
    375   """ 
--> 376   f = self.makefn(outs, mode, *args, **kwargs) 
    377   return FastPointFunc(f) 
    378 

/home/dmahler/Anaconda/lib/python2.7/site-packages/pymc3/memoize.pyc in memoizer(*args, **kwargs) 
    12 
    13   if key not in cache: 
---> 14    cache[key] = obj(*args, **kwargs) 
    15 
    16   return cache[key] 

/home/dmahler/Anaconda/lib/python2.7/site-packages/pymc3/model.pyc in makefn(self, outs, mode, *args, **kwargs) 
    344        on_unused_input='ignore', 
    345        accept_inplace=True, 
--> 346        mode=mode, *args, **kwargs) 
    347 
    348  def fn(self, outs, mode=None, *args, **kwargs): 

/home/dmahler/Anaconda/lib/python2.7/site-packages/theano/compile/function.pyc in function(inputs, outputs, mode, updates, givens, no_default_updates, accept_inplace, name, rebuild_strict, allow_input_downcast, profile, on_unused_input) 
    318     on_unused_input=on_unused_input, 
    319     profile=profile, 
--> 320     output_keys=output_keys) 
    321  # We need to add the flag check_aliased inputs if we have any mutable or 
    322  # borrowed used defined inputs 

/home/dmahler/Anaconda/lib/python2.7/site-packages/theano/compile/pfunc.pyc in pfunc(params, outputs, mode, updates, givens, no_default_updates, accept_inplace, name, rebuild_strict, allow_input_downcast, profile, on_unused_input, output_keys) 
    477       accept_inplace=accept_inplace, name=name, 
    478       profile=profile, on_unused_input=on_unused_input, 
--> 479       output_keys=output_keys) 
    480 
    481 

/home/dmahler/Anaconda/lib/python2.7/site-packages/theano/compile/function_module.pyc in orig_function(inputs, outputs, mode, accept_inplace, name, profile, on_unused_input, output_keys) 
    1774     profile=profile, 
    1775     on_unused_input=on_unused_input, 
-> 1776     output_keys=output_keys).create(
    1777    defaults) 
    1778 

/home/dmahler/Anaconda/lib/python2.7/site-packages/theano/compile/function_module.pyc in __init__(self, inputs, outputs, mode, accept_inplace, function_builder, profile, on_unused_input, fgraph, output_keys) 
    1426    # OUTPUT VARIABLES) 
    1427    fgraph, additional_outputs = std_fgraph(inputs, outputs, 
-> 1428              accept_inplace) 
    1429    fgraph.profile = profile 
    1430   else: 

/home/dmahler/Anaconda/lib/python2.7/site-packages/theano/compile/function_module.pyc in std_fgraph(input_specs, output_specs, accept_inplace) 
    175 
    176  fgraph = gof.fg.FunctionGraph(orig_inputs, orig_outputs, 
--> 177         update_mapping=update_mapping) 
    178 
    179  for node in fgraph.apply_nodes: 

/home/dmahler/Anaconda/lib/python2.7/site-packages/theano/gof/fg.pyc in __init__(self, inputs, outputs, features, clone, update_mapping) 
    169 
    170   for output in outputs: 
--> 171    self.__import_r__(output, reason="init") 
    172   for i, output in enumerate(outputs): 
    173    output.clients.append(('output', i)) 

/home/dmahler/Anaconda/lib/python2.7/site-packages/theano/gof/fg.pyc in __import_r__(self, variable, reason) 
    358   # Imports the owners of the variables 
    359   if variable.owner and variable.owner not in self.apply_nodes: 
--> 360     self.__import__(variable.owner, reason=reason) 
    361   if (variable.owner is None and 
    362     not isinstance(variable, graph.Constant) and 

/home/dmahler/Anaconda/lib/python2.7/site-packages/theano/gof/fg.pyc in __import__(self, apply_node, check, reason) 
    472        "for more information on this error." 
    473        % str(node)), 
--> 474        r) 
    475 
    476   for node in new_nodes: 

MissingInputError: ("An input of the graph, used to compute Elemwise{neg,no_inplace}(P_logodds_), was not provided and not given a value.Use the Theano flag exception_verbosity='high',for more information on this error.", P_logodds_) 
> /home/dmahler/Anaconda/lib/python2.7/site-packages/theano/gof/fg.py(474)__import__() 
    472        "for more information on this error." 
    473        % str(node)), 
--> 474        r) 
    475 
    476   for node in new_nodes: 

Avant que je connaissais pymc3.BetaBinomial je convenait d'essayer d'obtenir le même résultat en utilisant des instances Beta et Binomial séparés:

with pm.Model() as model: 
    C=pm.constant(C0) 
    I=pm.constant(I0) 
    C1=pm.constant(C0 + 1) 
    I1=pm.constant(I0 + 1) 
    N=pm.constant(N0) 
    alpha = pm.Exponential('alpha', 1/(C0.sum()+1)) 
    beta = pm.Exponential('beta', 1/(I0.sum()+1)) 
    p = pm.Beta('P', alpha, beta, shape=K) 
    b = pm.Binomial('B', N, p, observed=C0) 

Ceci termine avec succès, mais différentes méthodes produisent des résultats assez différents. Je pensais que cela pourrait être en partie dû au niveau supplémentaire d'indirection entre les prieurs et les observations rend l'espace de recherche plus grand. Quand je suis tombé sur BetaBinomial je me suis dit que cela rendrait la recherche plus facile tout en étant la bonne chose^TM. Sinon, je crois que les modèles doivent être logiquement équivalents. Malheureusement, je ne peux pas comprendre comment faire batebinomial de travail et je suis incapable de trouver des exemples en utilisant BetaBinomial sur Internet.

  • Comment faire fonctionner le modwel BetaBinomial?
  • Les modèles sont-ils vraiment logiquement équivalents?
  • Quelqu'un a-t-il une meilleure idée de la cause des problèmes numériques avec la version hiérarchique initiale?
    • Comment puis-je les réparer?

Répondre

3

Votre modèle doit fonctionner, et vous pouvez écrire ce

with pm.Model() as model: 
    alpha = pm.Exponential('alpha', 1/(C0.sum()+1)) 
    beta = pm.Exponential('beta', 1/(I0.sum()+1)) 
    obs = pm.BetaBinomial('obs', alpha, beta, N0, observed=C0) 

C'est, (C, I C1, I1) ont été définis dans le modèle que vous, mais pas utilisé. Quoi qu'il en soit, ce n'était pas le problème. L'erreur que vous obtenez est parce que PyMC3 attend une variable P (comme dans le second modèle que vous avez) mais la variable n'est pas définie. Peut-être travaillez-vous avec un bloc-notes Jupyter et vous supprimez/commentez une variable theano. Essayez de réexécuter le portable.

Théoriquement, l'utilisation d'une bêta et d'un binomial ou d'un bêta-binomial devrait donner les mêmes résultats. D'un point de vue pratique. L'échantillonnage du BetaBinomial devrait être plus rapide que celui d'un bêta et d'un binôme, puisqu'une partie du travail a déjà été faite analytiquement!

En supposant un échantillonnage correct, les deux modèles devraient fournir des résultats équivalents. Pour vérifier que les deux résultats sont équivalents, essayez d'augmenter le nombre d'échantillons (et évitez thinning). Comparez également les résultats entre et dans les modèles (les différences devraient être à peu près les mêmes). Si vous n'avez pas besoin d'estimer la variable P (la distribution bêta), utilisez le BetaBinomial.