ADEV.jl
Experimental port of the ADEV library to Julia. Not yet documented or stable, and currently has low coverage of Julia language features.
Usage
Defining probabilistic compuations
ADEV exposes primitives, like normal_reparam
and flip_mvd
, which are functions returning "probabilistic computations." Bigger probabilistic computations can be composed using the syntax @adev begin ... end
:
function my_program(theta)
@adev begin
let x = @sample(normal_reparam(theta, 1)),
b = @sample(flip_mvd(sigmoid(theta)))
if b
@sample(normal_reparam(x, 1))
else
# Recurse
theta * @sample(my_program(theta - 1))
end
end
end
end
Within an @adev begin ... end
block, the following constructs are currently supported:
@sample(e)
, wheree
is a supported expression evaluating to a probabilistic computation;let x1 = e1, ..., xn = en; e; end
, wheree, e1, ..., en
are supported expressions;if e_cond1; e1; elseif e_cond2; e2; ...; else; en; end
, wheree_cond1, e1, ..., en
are supported expressions;e(e1, ..., en)
, wheree, e1, ..., en
are supported expressions.- other Julia expressions (e.g.
arr[idx]
), so long as they are pure (no mutation, no randomness).
The main limitations, then, are:
- No mutation (e.g.
x += 4
) or simple imperative assignment (e.g.x = 4
). Uselet
instead. - No loops (e.g.
while
orfor
). Use recursion instead. - No compound expressions that are not function calls, but not pure (e.g.
my_array[@sample(uniform(1:10))]
). Uselet idx = @sample(uniform(1:10)); my_array[idx]; end
instead. - No function calls with keyword arguments, or splatted arguments.
Estimating derivatives
ADEV currently works with functions of type Real -> ProbabilisticComputation{Real}
. For such a function, simulate(f, x)
will simulate a value of f(x)
, and differentiate(f, x)
will estimate the derivative of estimate_derivative(f, x; N=100)
. A simple version of stochastic gradient descent is implemented by sgd(f; theta=0, step_size=0.01, n_iters=1000, N=100)
, where N
is the number of samples to use for estimating the derivative at each iteration.