Skip to content

Commit c9fe5d7

Browse files
Merge pull request #800 from stan-dev/jacobian-plus-equal
Basic docs for jacobian +=
2 parents e7aae38 + 1dcaf78 commit c9fe5d7

File tree

8 files changed

+114
-22
lines changed

8 files changed

+114
-22
lines changed

src/reference-manual/deprecations.qmd

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,14 @@ would use Cholesky factors rather than full correlation matrix types.
5252

5353
*Scheduled Removal*: Stan 3.0 or later.
5454

55+
## Use of `_lp` functions in `transformed parameters`
56+
57+
*Deprecated*: Using [functions that end in `_lp`](user-functions.qmd#log-probability-access-in-functions)
58+
in the `transformed parameters` block.
59+
60+
*Replacement*: Use `_jacobian` functions and the `jacobian +=` statement instead. These allow for change-of-variable
61+
adjustments which can be conditionally enabled by Stan's algorithms.
62+
5563
## New Keywords
5664

5765
*Deprecated*: The following identifiers will become reserved in the language in the specified version.

src/reference-manual/grammar.txt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@
2424

2525
<identifier> ::= IDENTIFIER
2626
| TRUNCATE
27-
| <future_keyword>
28-
29-
<future_keyword> ::= JACOBIAN
3027

3128
<decl_identifier> ::= <identifier>
3229
| <reserved_word>
@@ -86,6 +83,7 @@
8683

8784
<unsized_type> ::= ARRAY <unsized_dims> <basic_type>
8885
| ARRAY <unsized_dims> <unsized_tuple_type>
86+
| <basic_type> <unsized_dims>
8987
| <basic_type>
9088
| <unsized_tuple_type>
9189

@@ -115,7 +113,9 @@
115113
<id_and_optional_assignment(rhs,
116114
<decl_identifier_after_comma>)>)*
117115

118-
<decl(type_rule, rhs)> ::= <higher_type(type_rule)>
116+
<decl(type_rule, rhs)> ::= type_rule <decl_identifier> LBRACK <expression>
117+
(COMMA <expression>)* RBRACK
118+
| <higher_type(type_rule)>
119119
<id_and_optional_assignment(rhs,
120120
<decl_identifier>)>
121121
[<remaining_declarations(rhs)>] SEMICOLON
@@ -272,6 +272,7 @@
272272
| <expression> TILDE <identifier> LPAREN [<expression>
273273
(COMMA <expression>)*] RPAREN [<truncation>] SEMICOLON
274274
| TARGET PLUSASSIGN <expression> SEMICOLON
275+
| JACOBIAN PLUSASSIGN <expression> SEMICOLON
275276
| BREAK SEMICOLON
276277
| CONTINUE SEMICOLON
277278
| PRINT LPAREN <printables> RPAREN SEMICOLON

src/reference-manual/statements.qmd

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ are used --- if they do not, the behavior is undefined.
1515
The basis of Stan's execution is the evaluation of a log probability
1616
function (specifically, a log probability density function) for a given
1717
set of (real-valued) parameters. Log probability functions can be
18-
constructed by using distribution statements and log probability increment
18+
constructed by using distribution statements and log probability increment
1919
statements. Statements may be grouped
2020
into sequences and into for-each loops. In addition, Stan allows
2121
local variables to be declared in blocks and also allows an empty
@@ -248,7 +248,8 @@ of the posterior up to an additive constant. Data and transformed
248248
data are fixed before the log density is evaluated. The total log
249249
probability is initialized to zero. Next, any log Jacobian
250250
adjustments accrued by the variable constraints are added to the log
251-
density (the Jacobian adjustment may be skipped for optimization).
251+
density (the Jacobian adjustment may be skipped for maximum likelihood estimation
252+
via optimization).
252253
Distribution statements and log probability increment statements may add to the log
253254
density in the model block. A log probability increment statement
254255
directly increments the log density with the value of an expression as
@@ -361,14 +362,51 @@ including arrays of vectors and matrices. For container arguments,
361362
their sum will be added to the total log density.
362363

363364

365+
## Increment log density with a change of variables adjustment
366+
367+
368+
A variant of the `target +=` statement described above is the
369+
`jacobian +=` statement. This can be used in the transformed parameters block
370+
or in functions ending with `_jacobian` to mimic the log Jacobian
371+
adjustments accrued by built-in variable transforms.
372+
373+
Similarly to those implemented for the built-in transforms, these Jacobian adjustment
374+
may be skipped for maximum likelihood estimation via optimization.
375+
376+
For example, here is a program which recreates the existing
377+
[`<upper=x>` transform](transforms.qmd#upper-bounded-scalar) on real numbers:
378+
379+
```stan
380+
functions {
381+
real upper_bound_jacobian(real x, real ub) {
382+
jacobian += x;
383+
return ub - exp(x);
384+
}
385+
}
386+
data {
387+
real ub;
388+
}
389+
parameters {
390+
real b_raw;
391+
}
392+
transformed parameters {
393+
real b = upper_bound_jacobian(b_raw, ub);
394+
}
395+
model {
396+
// use b as if it was declared `real<upper=ub> b;` in parameters
397+
// e.g.
398+
// b ~ lognormal(0, 1);
399+
}
400+
```
401+
364402
### Accessing the log density {-}
365403

366-
To access accumulated log density up to the current execution point,
404+
To access the accumulated log density up to the current execution point,
367405
the function `target()` may be used.
368406

369407
## Sampling statements {#sampling-statements.section}
370408

371-
The term "sampling statement" has been replaced with
409+
The term "sampling statement" has been replaced with
372410
[distribution statement](#distribution-statements.section).
373411

374412
## Distribution statements {#distribution-statements.section}
@@ -432,7 +470,7 @@ terms in the model block. Equivalently, each $\sim$ statement
432470
corresponds to a multiplicative factor in the unnormalized posterior
433471
density.
434472

435-
Distribution statements (`~`) accept only built-in or user-defined
473+
Distribution statements (`~`) accept only built-in or user-defined
436474
distributions on the
437475
right side. The left side of a distribution statement may be data,
438476
parameter, or a complex expression, but the evaluated type needs to
@@ -452,8 +490,8 @@ target += normal_lpdf(sigma | 0, 1);
452490
```
453491

454492
Stan models can mix distribution statements and log probability
455-
increment statements. Although statistical models
456-
are usually defined with distributions in the literature,
493+
increment statements. Although statistical models
494+
are usually defined with distributions in the literature,
457495
there are several scenarios in which we may want to code the log
458496
likelihood or parts of it directly, for example, due to computational
459497
efficiency (e.g. censored data model) or coding language limitations
@@ -485,7 +523,7 @@ target += dist_lpmf(y | theta1, ..., thetaN);
485523

486524
This will be well formed if and only if `dist_lpdf(y | theta1,
487525
..., thetaN)` or `dist_lpmf(y | theta1, ..., thetaN)` is a
488-
well-formed expression of type `real`. User defined distributions
526+
well-formed expression of type `real`. User defined distributions
489527
can be defined in functions block by using function names ending with `_lpdf`.
490528

491529

@@ -881,7 +919,7 @@ The equivalent code for a vectorized truncation depends on which of the
881919
variables are non-scalars (arrays, vectors, etc.):
882920

883921
1. If the variate `y` is the only non-scalar, the result is the same as
884-
described in the above sections, but the `lcdf`/`lccdf` calculation is
922+
described in the above sections, but the `lcdf`/`lccdf` calculation is
885923
multiplied by `size(y)`.
886924

887925
2. If the other arguments to the distribution are non-scalars, then the

src/reference-manual/syntax.qmd

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ The raw output is available [here](https://raw.githubusercontent.com/stan-dev/do
300300
| <expression> TILDE <identifier> LPAREN [<expression>
301301
(COMMA <expression>)*] RPAREN [<truncation>] SEMICOLON
302302
| TARGET PLUSASSIGN <expression> SEMICOLON
303+
| JACOBIAN PLUSASSIGN <expression> SEMICOLON
303304
| BREAK SEMICOLON
304305
| CONTINUE SEMICOLON
305306
| PRINT LPAREN <printables> RPAREN SEMICOLON
@@ -476,6 +477,9 @@ of other user defined functions which end in `_lp`.
476477
Sampling statements (using `~`) can only be used in the `model` block or in the
477478
bodies of user-defined functions which end in `_lp`.
478479

480+
`jacobian +=` statements can only be used inside of the `transformed parameters` block
481+
or in functions that end with `_jacobian`.
482+
479483
### Probability function naming {-}
480484

481485
A probability function literal must have one of the following

src/reference-manual/user-functions.qmd

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ arguments to produce an expression, which has a value when executed.
9595
### Functions as statements {-}
9696

9797
Functions with void return types may be applied to arguments and used
98-
as [statements.qmd](statements).
98+
as [statements.qmd](statements).
9999
These act like distribution statements or print
100100
statements. Such uses are only appropriate for functions that act
101101
through side effects, such as incrementing the log probability
@@ -161,7 +161,11 @@ used in place of parameterized distributions on the right side of
161161
Functions of certain types are restricted on scope of usage.
162162
Functions whose names end in `_lp` assume access to the log
163163
probability accumulator and are only available in the transformed
164-
parameter and model blocks.
164+
parameters and model blocks.
165+
166+
Functions whose name end in `_jacobian` assume access to the log
167+
probability accumulator may only be used within the transformed parameters
168+
block.
165169

166170
Functions whose names end in `_rng`
167171
assume access to the random number generator and may only be used
@@ -293,8 +297,8 @@ a function elsewhere results in a compile-time error.
293297

294298
### Log probability access in functions {-}
295299

296-
Functions that include
297-
[statements.qmd#distribution-statements.section](distribution statements) or
300+
Functions that include
301+
[statements.qmd#distribution-statements.section](distribution statements) or
298302
[statements.qmd#increment-log-prob.section](log probability increment statements)
299303
must have a name that ends in `_lp`.
300304
Attempts to use distribution statements or increment log probability

src/stan-users-guide/reparameterization.qmd

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -441,10 +441,10 @@ parameters {
441441
transformed parameters {
442442
real<lower=0> y;
443443
y = 1 / y_inv; // change variables
444+
jacobian += -2 * log(y_inv); // Jacobian adjustment
444445
}
445446
model {
446447
y ~ gamma(2,4);
447-
target += -2 * log(y_inv); // Jacobian adjustment;
448448
}
449449
```
450450

@@ -476,7 +476,7 @@ transformed parameters {
476476
matrix[K, K] J; // Jacobian matrix of transform
477477
// ... compute v as a function of u ...
478478
// ... compute J[m, n] = d.v[m] / d.u[n] ...
479-
target += log(abs(determinant(J)));
479+
jacobian += log(abs(determinant(J)));
480480
// ...
481481
}
482482
model {
@@ -505,7 +505,7 @@ transformed parameters {
505505
vector[K] J_diag; // diagonals of Jacobian matrix
506506
// ...
507507
// ... compute J[k, k] = d.v[k] / d.u[k] ...
508-
target += sum(log(J_diag));
508+
jacobian += sum(log(J_diag));
509509
// ...
510510
}
511511
```
@@ -596,10 +596,10 @@ parameters {
596596
}
597597
transformed parameters {
598598
vector[N] alpha = L + exp(alpha_raw);
599+
jacobian += sum(alpha_raw); // log Jacobian
599600
// ...
600601
}
601602
model {
602-
target += sum(alpha_raw); // log Jacobian
603603
// ...
604604
}
605605
```

src/stan-users-guide/user-functions.qmd

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,41 @@ transformed parameters {
287287
}
288288
```
289289

290+
## Functions implementing change-of-variable adjustments
291+
292+
Functions whose names end in `_jacobian` can use the
293+
`jacobian +=` statement. This can be used to implement a custom
294+
change of variables for arbitrary parameters.
295+
296+
For example, this function recreates the built-in
297+
`<upper=x>` transform on real numbers:
298+
```stan
299+
real upper_bound_jacobian(real x, real ub) {
300+
jacobian += x;
301+
return ub - exp(x);
302+
}
303+
```
304+
305+
It can be used as a replacement for `real<lower=ub>` as follows:
306+
307+
```stan
308+
functions {
309+
// upper_bound_jacobian as above
310+
}
311+
data {
312+
real ub;
313+
}
314+
parameters {
315+
real b_raw;
316+
}
317+
transformed parameters {
318+
real b = upper_bound_jacobian(b_raw, ub);
319+
}
320+
model {
321+
b ~ lognormal(0, 1);
322+
// ...
323+
}
324+
```
290325

291326
## Functions acting as random number generators
292327

src/stan-users-guide/using-stanc.qmd

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,9 @@ Warning:
647647
Left-hand side of distribution statement (~) may contain a non-linear
648648
transform of a parameter or local variable. If it does, you need
649649
to include a target += statement with the log absolute determinant
650-
of the Jacobian of the transform.
650+
of the Jacobian of the transform. You could also consider defining
651+
a transformed parameter and using jacobian += in the transformed
652+
parameters block.
651653
```
652654

653655
### Pedantic mode limitations {-}

0 commit comments

Comments
 (0)