Skip to content

Commit e6a796f

Browse files
committed
refactored datatype querying, placing it in it's own file; added location/scale t distribution t_full
1 parent 486c6f7 commit e6a796f

File tree

4 files changed

+89
-46
lines changed

4 files changed

+89
-46
lines changed

pymc/PyMCObjects.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@
1414
import sys
1515
import pdb
1616

17-
from numpy import single, float_, longfloat
18-
float_dtypes = [float, single, float_, longfloat]
17+
import datatypes
1918

2019
d_neg_inf = float(-1.7976931348623157e+308)
2120

@@ -309,11 +308,11 @@ def set_logp(self,value):
309308

310309
logp = property(fget = get_logp, fset=set_logp, doc="Self's log-probability value conditional on parents.")
311310

312-
def logp_partial_gradient(self, calculation_set = None):
311+
def logp_partial_gradient(self, variable, calculation_set = None):
313312
gradient = 0
314313
if self in calculation_set:
315-
316-
if not (variable.dtype in float_dtypes):
314+
315+
if not datatypes.is_continuous(variable):
317316
return zeros(shape(variable.value))
318317

319318
for parameter, value in self.parents.iteritems():
@@ -459,7 +458,7 @@ def logp_partial_gradient(self, variable, calculation_set = None):
459458
if self.verbose > 0:
460459
print '\t' + self.__name__ + ': logp_partial_gradient accessed.'
461460

462-
if not (variable.dtype in float_dtypes and self.dtype in float_dtypes):
461+
if not (datatypes.is_continuous(variable) and datatypes.is_continuous(self)):
463462
return zeros(shape(variable.value))
464463

465464
# loop through all the parameters and add up all the gradients of log p with respect to the approrpiate variable
@@ -838,7 +837,7 @@ def logp_partial_gradient(self, variable, calculation_set = None):
838837
if (calculation_set is None) or (self in calculation_set):
839838

840839
#is there better way to make sure the variable is continuous?
841-
if not (variable.dtype in float_dtypes):
840+
if not datatypes.is_continuous(variable):
842841
return zeros(shape(variable.value))
843842

844843
if variable is self:

pymc/datatypes.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
from numpy import obj2sctype, ndarray
2+
from numpy import bool_
3+
from numpy import byte, short, intc, int_, longlong, intp
4+
from numpy import ubyte, ushort, uintc, uint, ulonglong, uintp
5+
from numpy import single, float_, longfloat
6+
from numpy import csingle, complex_, clongfloat
7+
8+
integer_dtypes = [int, uint, long, byte, short, intc, int_, longlong, intp, ubyte, ushort, uintc, uint, ulonglong, uintp]
9+
float_dtypes = [float, single, float_, longfloat]
10+
complex_dtypes = [complex, csingle, complex_, clongfloat]
11+
bool_dtypes = [bool, bool_]
12+
13+
def check_type(stochastic):
14+
"""
15+
type, shape = check_type(stochastic)
16+
17+
Checks the type of a stochastic's value. Output value 'type' may be
18+
bool, int, float, or complex. Nonnative numpy dtypes are lumped into
19+
these categories. Output value 'shape' is () if the stochastic's value
20+
is scalar, or a nontrivial tuple otherwise.
21+
"""
22+
val = stochastic.value
23+
if val.__class__ in bool_dtypes:
24+
return bool, ()
25+
elif val.__class__ in integer_dtypes:
26+
return int, ()
27+
elif val.__class__ in float_dtypes:
28+
return float, ()
29+
elif val.__class__ in complex_dtypes:
30+
return complex, ()
31+
elif isinstance(val, ndarray):
32+
33+
if obj2sctype(val) is bool_:
34+
return bool, val.shape
35+
elif obj2sctype(val) in integer_dtypes:
36+
return int, val.shape
37+
elif obj2sctype(val) in complex_dtypes:
38+
return float, val.shape
39+
elif obj2sctype(val) in complex_dtypes:
40+
return complex, val.shape
41+
else:
42+
return 'object', ()
43+
44+
continuous_types = [float, complex]
45+
46+
def is_continuous(stochastic):
47+
if check_type(stochastic) in continuous_types:
48+
return True
49+
else:
50+
return False
51+

pymc/distributions.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2381,6 +2381,36 @@ def t_grad_setup(x, nu, f):
23812381
'nu' : lambda x, nu : t_grad_setup(x, nu, flib.t_grad_nu)}
23822382

23832383

2384+
def t_full_like(x, nu, mu, tau):
2385+
R"""t_full_like(x, nu)
2386+
2387+
Student's T log-likelihood with location (mu) and precision (tau) parameters. Describes a zero-mean normal variable whose precision is
2388+
gamma distributed. Alternatively, describes the mean of several zero-mean normal
2389+
random variables divided by their sample standard deviation.
2390+
2391+
:Parameters:
2392+
- `x` : Input data.
2393+
- `nu` : Degrees of freedom.
2394+
- `mu` : Mean.
2395+
- `tau` : Precision.
2396+
2397+
"""
2398+
nu = np.asarray(nu)
2399+
return flib.t((x - mu) * tau, nu) + .5 * tau
2400+
2401+
def t_full_expval(x, nu, mu, tau):
2402+
"""t_expval(nu)
2403+
2404+
Expectation of Student's t random variables.
2405+
"""
2406+
return 0
2407+
2408+
t_full_grad_like = {'value' : lambda x, nu, mu, tau : t_grad_setup((x - mu) * tau, nu, flib.t_grad_x),
2409+
'nu' : lambda x, nu, mu, tau : t_grad_setup((x - mu) * tau, nu, flib.t_grad_nu),
2410+
'mu' : lambda x, nu, mu, tau : t_grad_setup((x - mu) * tau, nu, flib.t_grad_x) * tau,
2411+
'tau' : lambda x, nu, mu, tau : t_grad_setup((x - mu) * tau, nu, flib.t_grad_x) * (x - mu) + .5}
2412+
2413+
23842414
# DiscreteUniform--------------------------------------------------
23852415
@randomwrap
23862416
def rdiscrete_uniform(lower, upper, size=None):

pymc/utils.py

Lines changed: 2 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from numpy.linalg import cholesky, eigh, det, inv
1515
from Node import logp_of_set, logp_gradient_of_set
1616
import types
17+
from datatypes import *
1718

1819
from numpy import sqrt, obj2sctype, ndarray, asmatrix, array, pi, prod, exp,\
1920
pi, asarray, ones, atleast_1d, iterable, linspace, diff, around, log10, \
@@ -57,47 +58,9 @@ def check_list(thing, label):
5758

5859

5960
# TODO: Look into using numpy.core.numerictypes to do this part.
60-
from numpy import bool_
61-
from numpy import byte, short, intc, int_, longlong, intp
62-
from numpy import ubyte, ushort, uintc, uint, ulonglong, uintp
63-
from numpy import single, float_, longfloat
64-
from numpy import csingle, complex_, clongfloat
6561

66-
# TODO : Wrap the nd histogramming fortran function.
67-
68-
integer_dtypes = [int, uint, long, byte, short, intc, int_, longlong, intp, ubyte, ushort, uintc, uint, ulonglong, uintp]
69-
float_dtypes = [float, single, float_, longfloat]
70-
complex_dtypes = [complex, csingle, complex_, clongfloat]
71-
bool_dtypes = [bool, bool_]
72-
def check_type(stochastic):
73-
"""
74-
type, shape = check_type(stochastic)
7562

76-
Checks the type of a stochastic's value. Output value 'type' may be
77-
bool, int, float, or complex. Nonnative numpy dtypes are lumped into
78-
these categories. Output value 'shape' is () if the stochastic's value
79-
is scalar, or a nontrivial tuple otherwise.
80-
"""
81-
val = stochastic.value
82-
if val.__class__ is bool:
83-
return bool, ()
84-
elif val.__class__ in [int, uint, long, byte, short, intc, int_, longlong, intp, ubyte, ushort, uintc, uint, ulonglong, uintp]:
85-
return int, ()
86-
elif val.__class__ in [float, single, float_, longfloat]:
87-
return float, ()
88-
elif val.__class__ in [complex, csingle, complex_, clongfloat]:
89-
return complex, ()
90-
elif isinstance(val, ndarray):
91-
if obj2sctype(val) is bool_:
92-
return bool, val.shape
93-
elif obj2sctype(val) in [byte, short, intc, int_, longlong, intp, ubyte, ushort, uintc, uint, ulonglong, uintp]:
94-
return int, val.shape
95-
elif obj2sctype(val) in [single, float_, longfloat]:
96-
return float, val.shape
97-
elif obj2sctype(val) in [csingle, complex_, clongfloat]:
98-
return complex, val.shape
99-
else:
100-
return 'object', ()
63+
# TODO : Wrap the nd histogramming fortran function.
10164

10265
def safe_len(val):
10366
if np.isscalar(val):

0 commit comments

Comments
 (0)