Skip to content

Commit ae2671c

Browse files
aloctavodiajunpenglao
authored andcommitted
do not use backward_val (#3744)
* do not use backward_val * make variable name more explicit
1 parent 700df83 commit ae2671c

File tree

2 files changed

+31
-88
lines changed

2 files changed

+31
-88
lines changed

pymc3/distributions/transforms.py

Lines changed: 11 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
from .distribution import draw_values
99
import numpy as np
1010
from scipy.special import logit as nplogit
11-
from scipy.special import expit
1211

1312

1413
__all__ = [
@@ -193,9 +192,6 @@ class Log(ElemwiseTransform):
193192
def backward(self, x):
194193
return tt.exp(x)
195194

196-
def backward_val(self, x):
197-
return np.exp(x)
198-
199195
def forward(self, x):
200196
return tt.log(x)
201197

@@ -215,9 +211,6 @@ class LogExpM1(ElemwiseTransform):
215211
def backward(self, x):
216212
return tt.nnet.softplus(x)
217213

218-
def backward_val(self, x):
219-
return np.log(1 + np.exp(-np.abs(x))) + np.max([x, 0])
220-
221214
def forward(self, x):
222215
"""Inverse operation of softplus.
223216
@@ -236,16 +229,12 @@ def jacobian_det(self, x):
236229
log_exp_m1 = LogExpM1()
237230

238231

239-
240232
class LogOdds(ElemwiseTransform):
241233
name = "logodds"
242234

243235
def backward(self, x):
244236
return invlogit(x, 0.0)
245237

246-
def backward_val(self, x):
247-
return invlogit(x, 0.0)
248-
249238
def forward(self, x):
250239
return logit(x)
251240

@@ -256,7 +245,6 @@ def forward_val(self, x, point=None):
256245
logodds = LogOdds()
257246

258247

259-
260248
class Interval(ElemwiseTransform):
261249
"""Transform from real line interval [a,b] to whole real line."""
262250

@@ -265,19 +253,12 @@ class Interval(ElemwiseTransform):
265253
def __init__(self, a, b):
266254
self.a = tt.as_tensor_variable(a)
267255
self.b = tt.as_tensor_variable(b)
268-
self.a_ = a
269-
self.b_ = b
270256

271257
def backward(self, x):
272258
a, b = self.a, self.b
273259
r = (b - a) * tt.nnet.sigmoid(x) + a
274260
return r
275261

276-
def backward_val(self, x):
277-
a, b = self.a_, self.b_
278-
r = (b - a) * 1 / (1 + np.exp(-x)) + a
279-
return r
280-
281262
def forward(self, x):
282263
a, b = self.a, self.b
283264
return tt.log(x - a) - tt.log(b - x)
@@ -304,16 +285,10 @@ class LowerBound(ElemwiseTransform):
304285

305286
def __init__(self, a):
306287
self.a = tt.as_tensor_variable(a)
307-
self.a_ = a
308288

309289
def backward(self, x):
310-
a = self.a_
311-
r = tt.exp(x) + a
312-
return r
313-
314-
def backward_val(self, x):
315290
a = self.a
316-
r = np.exp(x) + a
291+
r = tt.exp(x) + a
317292
return r
318293

319294
def forward(self, x):
@@ -332,10 +307,10 @@ def jacobian_det(self, x):
332307

333308

334309
lowerbound = LowerBound
335-
'''
310+
"""
336311
Alias for ``LowerBound`` (:class: LowerBound) Transform (:class: Transform) class
337312
for use in the ``transform`` argument of a random variable.
338-
'''
313+
"""
339314

340315

341316
class UpperBound(ElemwiseTransform):
@@ -345,18 +320,12 @@ class UpperBound(ElemwiseTransform):
345320

346321
def __init__(self, b):
347322
self.b = tt.as_tensor_variable(b)
348-
self.b_ = b
349323

350324
def backward(self, x):
351325
b = self.b
352326
r = b - tt.exp(x)
353327
return r
354328

355-
def backward_val(self, x):
356-
b = self.b_
357-
r = b - np.exp(x)
358-
return r
359-
360329
def forward(self, x):
361330
b = self.b
362331
return tt.log(b - x)
@@ -373,11 +342,10 @@ def jacobian_det(self, x):
373342

374343

375344
upperbound = UpperBound
376-
'''
345+
"""
377346
Alias for ``UpperBound`` (:class: UpperBound) Transform (:class: Transform) class
378347
for use in the ``transform`` argument of a random variable.
379-
'''
380-
348+
"""
381349

382350

383351
class Ordered(Transform):
@@ -389,12 +357,6 @@ def backward(self, y):
389357
x = tt.inc_subtensor(x[..., 1:], tt.exp(y[..., 1:]))
390358
return tt.cumsum(x, axis=-1)
391359

392-
def backward_val(self, y):
393-
x = np.zeros(y.shape)
394-
x[..., 0] += y[..., 0]
395-
x[..., 1:] += np.exp(y[..., 1:])
396-
return np.cumsum(x, axis=-1)
397-
398360
def forward(self, x):
399361
y = tt.zeros(x.shape)
400362
y = tt.inc_subtensor(y[..., 0], x[..., 0])
@@ -412,10 +374,10 @@ def jacobian_det(self, y):
412374

413375

414376
ordered = Ordered()
415-
'''
377+
"""
416378
Instantiation of ``Ordered`` (:class: Ordered) Transform (:class: Transform) class
417379
for use in the ``transform`` argument of a random variable.
418-
'''
380+
"""
419381

420382

421383
class SumTo1(Transform):
@@ -430,10 +392,6 @@ def backward(self, y):
430392
remaining = 1 - tt.sum(y[..., :], axis=-1, keepdims=True)
431393
return tt.concatenate([y[..., :], remaining], axis=-1)
432394

433-
def backward_val(self, y):
434-
remaining = 1 - np.sum(y[..., :], axis=-1, keepdims=True)
435-
return np.concatenate([y[..., :], remaining], axis=-1)
436-
437395
def forward(self, x):
438396
return x[..., :-1]
439397

@@ -500,18 +458,6 @@ def backward(self, y_):
500458
x = S * yl
501459
return floatX(x.T)
502460

503-
def backward_val(self, y_):
504-
y = y_.T
505-
Km1 = y.shape[0]
506-
k = np.arange(Km1)[(slice(None),) + (None,) * (y.ndim - 1)]
507-
eq_share = nplogit(1.0 / (Km1 + 1 - k).astype(str(y_.dtype)))
508-
z = expit(y + eq_share)
509-
yl = np.concatenate([z, np.ones(y[:1].shape)])
510-
yu = np.concatenate([np.ones(y[:1].shape), 1 - z])
511-
S = np.cumprod(yu, 0)
512-
x = S * yl
513-
return floatX(x.T)
514-
515461
def jacobian_det(self, y_):
516462
y = y_.T
517463
Km1 = y.shape[0]
@@ -526,10 +472,9 @@ def jacobian_det(self, y_):
526472
stick_breaking = StickBreaking()
527473

528474

529-
530475
def t_stick_breaking(eps: float) -> StickBreaking:
531-
'''Return a new :class:`StickBreaking` transform with specified eps(ilon),
532-
instead of the default.'''
476+
"""Return a new :class:`StickBreaking` transform with specified eps(ilon),
477+
instead of the default."""
533478
return StickBreaking(eps)
534479

535480

@@ -542,9 +487,6 @@ class Circular(ElemwiseTransform):
542487
def backward(self, y):
543488
return tt.arctan2(tt.sin(y), tt.cos(y))
544489

545-
def backward_val(self, y):
546-
return y
547-
548490
def forward(self, x):
549491
return tt.as_tensor_variable(x)
550492

@@ -557,6 +499,7 @@ def jacobian_det(self, x):
557499

558500
circular = Circular()
559501

502+
560503
class CholeskyCovPacked(Transform):
561504
name = "cholesky-cov-packed"
562505

@@ -566,10 +509,6 @@ def __init__(self, n):
566509
def backward(self, x):
567510
return tt.advanced_set_subtensor1(x, tt.exp(x[self.diag_idxs]), self.diag_idxs)
568511

569-
def backward_val(self, x):
570-
x[..., self.diag_idxs] = np.exp(x[..., self.diag_idxs])
571-
return x
572-
573512
def forward(self, y):
574513
return tt.advanced_set_subtensor1(y, tt.log(y[self.diag_idxs]), self.diag_idxs)
575514

@@ -580,6 +519,7 @@ def forward_val(self, y, point=None):
580519
def jacobian_det(self, y):
581520
return tt.sum(y[self.diag_idxs])
582521

522+
583523
class Chain(Transform):
584524
def __init__(self, transform_list):
585525
self.transform_list = transform_list
@@ -603,12 +543,6 @@ def backward(self, y):
603543
x = transf.backward(x)
604544
return x
605545

606-
def backward_val(self, y):
607-
x = y
608-
for transf in reversed(self.transform_list):
609-
x = transf.backward_val(x)
610-
return x
611-
612546
def jacobian_det(self, y):
613547
y = tt.as_tensor_variable(y)
614548
det_list = []

pymc3/smc/smc.py

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from ..step_methods.metropolis import MultivariateNormalProposal
1818
from ..backends.ndarray import NDArray
1919
from ..backends.base import MultiTrace
20-
from ..util import get_untransformed_name, is_transformed_name
20+
from ..util import is_transformed_name
2121

2222
EXPERIMENTAL_WARNING = (
2323
"Warning: SMC-ABC methods are experimental step methods and not yet"
@@ -128,6 +128,7 @@ def setup_kernel(self):
128128
simulator.distribution.function,
129129
self.model,
130130
self.var_info,
131+
self.variables,
131132
self.dist_func,
132133
self.sum_stat,
133134
)
@@ -373,7 +374,9 @@ class PseudoLikelihood:
373374
Pseudo Likelihood
374375
"""
375376

376-
def __init__(self, epsilon, observations, function, model, var_info, distance, sum_stat):
377+
def __init__(
378+
self, epsilon, observations, function, model, var_info, variables, distance, sum_stat
379+
):
377380
"""
378381
epsilon : float
379382
Standard deviation of the gaussian pseudo likelihood.
@@ -395,9 +398,13 @@ def __init__(self, epsilon, observations, function, model, var_info, distance, s
395398
self.function = function
396399
self.model = model
397400
self.var_info = var_info
401+
self.variables = variables
402+
self.varnames = [v.name for v in self.variables]
403+
self.unobserved_RVs = [v.name for v in self.model.unobserved_RVs]
398404
self.kernel = self.gauss_kernel
399405
self.dist_func = distance
400406
self.sum_stat = sum_stat
407+
self.get_unobserved_fn = self.model.fastfn(self.model.unobserved_RVs)
401408

402409
if distance == "absolute_error":
403410
self.dist_func = self.absolute_error
@@ -409,17 +416,19 @@ def __init__(self, epsilon, observations, function, model, var_info, distance, s
409416
def posterior_to_function(self, posterior):
410417
model = self.model
411418
var_info = self.var_info
412-
parameters = {}
419+
420+
varvalues = []
421+
samples = {}
413422
size = 0
414-
for var, values in var_info.items():
415-
shape, new_size = values
416-
value = posterior[size : size + new_size].reshape(shape)
417-
if is_transformed_name(var):
418-
var = get_untransformed_name(var)
419-
value = model[var].transformation.backward_val(value)
420-
parameters[var] = value
423+
for var in self.variables:
424+
shape, new_size = var_info[var.name]
425+
varvalues.append(posterior[size : size + new_size].reshape(shape))
421426
size += new_size
422-
return parameters
427+
point = {k: v for k, v in zip(self.varnames, varvalues)}
428+
for varname, value in zip(self.unobserved_RVs, self.get_unobserved_fn(point)):
429+
if not is_transformed_name(varname):
430+
samples[varname] = value
431+
return samples
423432

424433
def gauss_kernel(self, value):
425434
epsilon = self.epsilon

0 commit comments

Comments
 (0)