title: Using the pymc3 Categorical distribution with data that has several trials
body: <p>I am trying to detect switchpoints (which can vary trial-to-trial) on several trials (or repeated runs) of an experiment. Here's a dummy example of what I am trying to do:</p>
  
  <pre><code>import numpy as np
  import pymc3 as pm
  import theano.tensor as tt
  
  # Data has 2 trials/independent runs, each with 500 observations (which can be 0, 1 or 2)
  # Data switches from uniform probabilities to (1/6,2/3,1/6) at 250 on both trials
  data = np.zeros((2,500))
  data[0, :250] = np.random.choice(np.arange(3), size = 250, p = [1/3, 1/3, 1/3])
  data[0, 250:] = np.random.choice(np.arange(3), size = 250, p =  [1/6, 2/3, 1/6])
  data[1, :250] = np.random.choice(np.arange(3), size = 250, p =  [1/3, 1/3, 1/3])
  data[1, 250:] = np.random.choice(np.arange(3), size = 250, p =  [1/6, 2/3, 1/6])
  
  with pm.Model() as model:
      # 2 emission 'states', each with 3 possible emissions
      p = pm.Dirichlet('p', np.ones(3), shape = (2, 3)) 
      switchpoint = pm.DiscreteUniform('switchpoint', lower = 0, upper = 500)
      state = []  
  
      for i in range(2):
          state.append(tt.switch(switchpoint &gt;= np.arange(500), 0, 1))
      obs = pm.Categorical('obs', p = p[state], observed = data)
  </code></pre>
  
  <p>It doesn't seem, however, that the Categorical distribution is able to deal with several repeated trials in the same dataset, I get an error when the distribution tries to sum up the probabilities to 1:</p>
  
  <pre><code>ValueError                                Traceback (most recent call last)
  &lt;ipython-input-27-7ccdbe0bf9c9&gt; in &lt;module&gt;()
        1 with model:
  ----&gt; 2         obs = pm.Categorical('obs', p = p[state], observed = data)
  
  /home/narendra/anaconda3/lib/python3.6/site-packages/pymc3-3.0-py3.6.egg/pymc3/distributions/distribution.py in __new__(cls, name, *args, **kwargs)
       34                 raise TypeError("observed needs to be data but got: {}".format(type(data)))
       35             total_size = kwargs.pop('total_size', None)
  ---&gt; 36             dist = cls.dist(*args, **kwargs)
       37             return model.Var(name, dist, data, total_size)
       38         else:
  
  /home/narendra/anaconda3/lib/python3.6/site-packages/pymc3-3.0-py3.6.egg/pymc3/distributions/distribution.py in dist(cls, *args, **kwargs)
       45     def dist(cls, *args, **kwargs):
       46         dist = object.__new__(cls)
  ---&gt; 47         dist.__init__(*args, **kwargs)
       48         return dist
       49 
  
  /home/narendra/anaconda3/lib/python3.6/site-packages/pymc3-3.0-py3.6.egg/pymc3/distributions/discrete.py in __init__(self, p, *args, **kwargs)
      433             self.k = tt.shape(p)[-1]
      434         self.p = p = tt.as_tensor_variable(p)
  --&gt; 435         self.p = (p.T / tt.sum(p, -1)).T
      436         self.mode = tt.argmax(p)
      437 
  
  /home/narendra/anaconda3/lib/python3.6/site-packages/theano/tensor/var.py in __truediv__(self, other)
      202 
      203     def __truediv__(self, other):
  --&gt; 204         return theano.tensor.basic.true_div(self, other)
      205 
      206     def __floordiv__(self, other):
  
  /home/narendra/anaconda3/lib/python3.6/site-packages/theano/gof/op.py in __call__(self, *inputs, **kwargs)
      666                 thunk.outputs = [storage_map[v] for v in node.outputs]
      667 
  --&gt; 668                 required = thunk()
      669                 assert not required  # We provided all inputs
      670 
  
  /home/narendra/anaconda3/lib/python3.6/site-packages/theano/gof/op.py in rval()
      881 
      882         def rval():
  --&gt; 883             fill_storage()
      884             for o in node.outputs:
      885                 compute_map[o][0] = True
  
  /home/narendra/anaconda3/lib/python3.6/site-packages/theano/gof/cc.py in __call__(self)
     1705                 print(self.error_storage, file=sys.stderr)
     1706                 raise
  -&gt; 1707             reraise(exc_type, exc_value, exc_trace)
     1708 
     1709 
  
  /home/narendra/anaconda3/lib/python3.6/site-packages/six.py in reraise(tp, value, tb)
      684         if value.__traceback__ is not tb:
      685             raise value.with_traceback(tb)
  --&gt; 686         raise value
      687 
      688 else:
  
  ValueError: Input dimension mis-match. (input[0].shape[1] = 500, input[1].shape[1] = 2)
  </code></pre>
  
  <p>Is there any way to deal with Categorical emissions on several trials in pymc3? Analyzing each trial separately isn't an option for me because I want to construct a hierarchical model with the actual data that switches between states of different kinds on many repeated trials, with each state being characterized with its own Categorical emission probabilities.</p>