-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprobability.py
140 lines (110 loc) · 4.71 KB
/
probability.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
"""
Functions for computing probabilities and distributions of spike patterns and
hyperparameters.
---
State-Space Analysis of Spike Correlations (Shimazaki et al. PLoS Comp Bio 2012)
Copyright (C) 2014 Thomas Sharp ([email protected])
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import numpy
import pdb
import transforms
def log_likelihood(y_t, theta_f_t, R):
"""
Computes the likelihood of observed pattern rates given the natural
parameters, all for a single timestep.
:param numpy.ndarray y_t:
Frequency of observed patterns for one timestep.
:param numpy.ndarray theta_f_t:
Natural parameters of observed patterns for one timestep.
:param int R:
Number of trials over which patterns were observed.
:returns:
Log likelhood of the observed patterns given the natural parameters,
as a float.
"""
psi = transforms.compute_psi(theta_f_t)
log_p = R * (numpy.dot(y_t, theta_f_t) - psi)
return log_p
def log_marginal(emd, period=None):
"""
Computes the log marginal probability of the observed spike-pattern rates
by marginalising over the natural-parameter distributions. See equation 45
of the source paper for details.
This is just a wrapper function for `log_marginal_raw`. It unpacks data
from the EMD container pbject and calls that function.
:param container.EMData emd:
All data pertaining to the EM algorithm.
:param period tuple:
Timestep range over which to compute probability.
:returns:
Log marginal probability of the synchrony estimate as a float.
"""
# Unwrap the parameters and call the raw function
log_p = log_marginal_raw(emd.theta_f, emd.theta_o, emd.sigma_f, emd.sigma_o,
emd.y, emd.R, period)
return log_p
def log_marginal_raw(theta_f, theta_o, sigma_f, sigma_o, y, R, period=None):
"""
Computes the log marginal probability of the observed spike-pattern rates
by marginalising over the natural-parameter distributions. See equation 45
of the source paper for details.
From within SSASC, this function should be accessed by calling
`log_marginal` with the EMD container as a parameter. This raw function is
designed to be called from outside SSASC, when a complete EMD container
might not be available.
See the container.py for a full description of the parameter properties.
:param period tuple:
Timestep range over which to compute probability.
:returns:
Log marginal probability of the synchrony estimate as a float.
"""
if period == None: period = (0, theta_f.shape[0])
# Initialise
log_p = 0
# Iterate over each timestep and compute...
a, b = 0, 0
for i in xrange(period[0], period[1]):
a += log_likelihood(y[i,:], theta_f[i,:], R)
theta_d = theta_f[i,:] - theta_o[i,:]
sig_inv = numpy.linalg.inv(sigma_o[i,:,:])
b -= numpy.dot(theta_d, numpy.dot(sig_inv, theta_d))
b += numpy.log(numpy.linalg.det(sigma_f[i,:,:])) -\
numpy.log(numpy.linalg.det(sigma_o[i,:,:]))
log_p = a + b / 2
return log_p
def log_multivariate_normal(x, mu, sigma):
"""
Computes the probability of `x' from a multivariate normal distribution
of mean `mu' and covariance `sigma'. This function is taken from SciPy.
:param float x:
Point at which to evalue the multivariate normal PDF.
:param numpy.ndarray mu:
Mean of the multivariate normal, of size D.
:param numpy.ndarray sigma:
Covariance of the multivariate normal, of dimensions (D, D).
:returns:
Probability of x as a float.
"""
# Find the number of dimensions of the multivariate normal
dim = mu.size
assert mu.size == sigma.shape[0] == sigma.shape[1],\
'The covariance matrix must have the same number of dimensions as '+\
'the mean vector.'
# Compute the normalising term
norm = numpy.log(((2 * numpy.pi) ** dim * numpy.linalg.det(sigma)) ** .5)
# Compute the distribution term
si, xd = numpy.linalg.inv(sigma), x - mu
dist = -.5 * numpy.dot(numpy.dot(xd.transpose(), si), xd)
# Finish up!
log_p = norm + dist
return log_p