Trying to implement the model found here, which involves deriving a value from observations of comparisons between RV’s.
So, there are some number of things we would like to rank, $X_1, X_2, … X_n$. These are assumed to have a measurable “quality” that is distributed like $X_i ~ N(\mu_i, \sigma_i)$ . A set of judges then sample from this quality, and make a judgement on which quality is higher, i.e., they sample from (assuming no correlation) P(X_i > X_j) = CDF(\mu_i - \mu_j, \sigma_{i,j}). Then, given a whole bunch of judgments (i.e. X_1 > X2, X_5 < X_3, etc.) that form a directed graph, we would like to infer the original parameters mu_1, mu_2, …mu_n.
This boils down to a tt.switch model, but am I right in thinking the shape of the observations would need to be N-by-N? This would mean having some CDF that is shape (n,n) to model the likelihood of observations, right?
EDIT: I’ve gone ahead and attempted something that uses slicing, but I’m not sure how to get Theano to work in this way. Assuming I can “transpose” the PyMC3 RV’s as I can in numpy and theano.tensor.col(), something like this would make sense:
# actual item "quality", and pairwise comparisons
n_itm = 10
a = np.random.rand(n_itm,1)
pwc = np.where(a>a.T, 1,0)
# which comparisons were judged
n_comp = 20
comp_obsv = np.zeros((n_comp,2), dtype=int)
for row in range(n_comp):
comp_obsv[row, :] = np.random.choice(n_itm, size=2, replace=False)
# dummy observations:
y = pwc[comp_obsv[:,0], comp_obsv[:,1]]
# Thurstone "Law of Comparitive Judgement"
with pm.Model() as model:
theta = pm.Uniform('true_value', 0,10,shape=n_itm) # quality priors
sigma = pm.HalfCauchy('noise', 5, shape=n_itm) # noise priors
X = pm.Normal('meas_value', theta, sigma, shape=n_itm) # model the items
# is each X_i better than each X_j?
comparison = tt.switch(X>tt.transpose(X), 1, 0)
# pick out the comparisons we actually observed
judged = comparison[comp_obsv[:,0], comp_obsv[:,1]]
like = pm.Potential('judgement', judged, observed=y)
But, I’m getting the error:
----------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-137-9298573097a9> in <module>()
24
25 # pick out the comparisons we actually observed
---> 26 judged = comparison[comp_obsv[:,0], comp_obsv[:,1]]
27 like = pm.Potential('judgement', judged, observed=y)
28
~/anaconda3/lib/python3.6/site-packages/theano/tensor/var.py in __getitem__(self, args)
538 return self.take(args[axis], axis)
539 else:
--> 540 return theano.tensor.subtensor.advanced_subtensor(self, *args)
541 else:
542 if numpy.newaxis in args:
~/anaconda3/lib/python3.6/site-packages/theano/gof/op.py in __call__(self, *inputs, **kwargs)
613 """
614 return_list = kwargs.pop('return_list', False)
--> 615 node = self.make_node(*inputs, **kwargs)
616
617 if config.compute_test_value != 'off':
~/anaconda3/lib/python3.6/site-packages/theano/tensor/subtensor.py in make_node(self, x, *index)
2139
2140 index = tuple(map(as_index_variable, index))
-> 2141 bcast = adv_index_broadcastable_pattern(x, index)
2142 return gof.Apply(self,
2143 (x,) + index,
~/anaconda3/lib/python3.6/site-packages/theano/tensor/subtensor.py in adv_index_broadcastable_pattern(a, idx)
2120 # 2 - True = 1; 2 - False = 2
2121 fakeshape = [2 - bc for bc in a.broadcastable]
-> 2122 retshape = numpy.empty(fakeshape)[newidx].shape
2123 return tuple([dim == 1 for dim in retshape])
2124
IndexError: too many indices for array
indicating that this kind of slicing (which I thought might work as per the Radon Hierarchical pooling model) isn’t going to work the way I expected. Thoughts?