Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
ift
NIFTy
Commits
00a2a0c5
Commit
00a2a0c5
authored
Jan 18, 2019
by
Martin Reinecke
Browse files
Merge branch 'KL_docstrings' into 'NIFTy_5'
KL docstrings See merge request ift/nifty-dev!190
parents
d1e5a734
01e88a70
Changes
10
Hide whitespace changes
Inline
Side-by-side
demos/bernoulli_demo.py
View file @
00a2a0c5
...
...
@@ -74,7 +74,7 @@ if __name__ == '__main__':
ic_sampling
=
ift
.
GradientNormController
(
iteration_limit
=
100
)
# Minimize the Hamiltonian
H
=
ift
.
Hamiltonian
(
likelihood
,
ic_sampling
)
H
=
ift
.
Standard
Hamiltonian
(
likelihood
,
ic_sampling
)
H
=
ift
.
EnergyAdapter
(
position
,
H
,
want_metric
=
True
)
# minimizer = ift.L_BFGS(ic_newton)
H
,
convergence
=
minimizer
(
H
)
...
...
demos/getting_started_2.py
View file @
00a2a0c5
...
...
@@ -99,7 +99,7 @@ if __name__ == '__main__':
minimizer
=
ift
.
NewtonCG
(
ic_newton
)
# Compute MAP solution by minimizing the information Hamiltonian
H
=
ift
.
Hamiltonian
(
likelihood
)
H
=
ift
.
Standard
Hamiltonian
(
likelihood
)
initial_position
=
ift
.
from_random
(
'normal'
,
domain
)
H
=
ift
.
EnergyAdapter
(
initial_position
,
H
,
want_metric
=
True
)
H
,
convergence
=
minimizer
(
H
)
...
...
demos/getting_started_3.py
View file @
00a2a0c5
...
...
@@ -100,10 +100,10 @@ if __name__ == '__main__':
# Set up likelihood and information Hamiltonian
likelihood
=
ift
.
GaussianEnergy
(
mean
=
data
,
covariance
=
N
)(
signal_response
)
H
=
ift
.
Hamiltonian
(
likelihood
,
ic_sampling
)
H
=
ift
.
Standard
Hamiltonian
(
likelihood
,
ic_sampling
)
initial_
positio
n
=
ift
.
MultiField
.
full
(
H
.
domain
,
0.
)
positio
n
=
initial_
positio
n
initial_
mea
n
=
ift
.
MultiField
.
full
(
H
.
domain
,
0.
)
mea
n
=
initial_
mea
n
plot
=
ift
.
Plot
()
plot
.
add
(
signal
(
mock_position
),
title
=
'Ground Truth'
)
...
...
@@ -117,9 +117,9 @@ if __name__ == '__main__':
# Draw new samples to approximate the KL five times
for
i
in
range
(
5
):
# Draw new samples and minimize KL
KL
=
ift
.
KL_Energy
(
positio
n
,
H
,
N_samples
)
KL
=
ift
.
MetricGaussianKL
(
mea
n
,
H
,
N_samples
)
KL
,
convergence
=
minimizer
(
KL
)
positio
n
=
KL
.
position
mea
n
=
KL
.
position
# Plot current reconstruction
plot
=
ift
.
Plot
()
...
...
@@ -128,7 +128,7 @@ if __name__ == '__main__':
plot
.
output
(
ny
=
1
,
ysize
=
6
,
xsize
=
16
,
name
=
"loop-{:02}.png"
.
format
(
i
))
# Draw posterior samples
KL
=
ift
.
KL_Energy
(
positio
n
,
H
,
N_samples
)
KL
=
ift
.
MetricGaussianKL
(
mea
n
,
H
,
N_samples
)
sc
=
ift
.
StatCalculator
()
for
sample
in
KL
.
samples
:
sc
.
add
(
signal
(
sample
+
KL
.
position
))
...
...
demos/polynomial_fit.py
View file @
00a2a0c5
...
...
@@ -103,7 +103,7 @@ N = ift.DiagonalOperator(ift.from_global_data(d_space, var))
IC
=
ift
.
DeltaEnergyController
(
tol_rel_deltaE
=
1e-12
,
iteration_limit
=
200
)
likelihood
=
ift
.
GaussianEnergy
(
d
,
N
)(
R
)
Ham
=
ift
.
Hamiltonian
(
likelihood
,
IC
)
Ham
=
ift
.
Standard
Hamiltonian
(
likelihood
,
IC
)
H
=
ift
.
EnergyAdapter
(
params
,
Ham
,
want_metric
=
True
)
# Minimize
...
...
nifty5/__init__.py
View file @
00a2a0c5
...
...
@@ -49,7 +49,7 @@ from .operators.simple_linear_operators import (
from
.operators.value_inserter
import
ValueInserter
from
.operators.energy_operators
import
(
EnergyOperator
,
GaussianEnergy
,
PoissonianEnergy
,
InverseGammaLikelihood
,
BernoulliEnergy
,
Hamiltonian
,
AveragedEnergy
)
BernoulliEnergy
,
Standard
Hamiltonian
,
AveragedEnergy
)
from
.probing
import
probe_with_posterior_samples
,
probe_diagonal
,
\
StatCalculator
...
...
@@ -68,7 +68,7 @@ from .minimization.scipy_minimizer import (ScipyMinimizer, L_BFGS_B, ScipyCG)
from
.minimization.energy
import
Energy
from
.minimization.quadratic_energy
import
QuadraticEnergy
from
.minimization.energy_adapter
import
EnergyAdapter
from
.minimization.
kl_energy
import
KL_Energy
from
.minimization.
metric_gaussian_kl
import
MetricGaussianKL
from
.sugar
import
*
from
.plot
import
Plot
...
...
nifty5/library/adjust_variances.py
View file @
00a2a0c5
...
...
@@ -18,7 +18,7 @@
from
..minimization.energy_adapter
import
EnergyAdapter
from
..multi_field
import
MultiField
from
..operators.distributors
import
PowerDistributor
from
..operators.energy_operators
import
Hamiltonian
,
InverseGammaLikelihood
from
..operators.energy_operators
import
Standard
Hamiltonian
,
InverseGammaLikelihood
from
..operators.scaling_operator
import
ScalingOperator
from
..operators.simple_linear_operators
import
ducktape
...
...
@@ -53,8 +53,8 @@ def make_adjust_variances(a,
Returns
-------
Energy
Hamiltonian that can be used for further minimization.
StandardHamiltonian
A
Hamiltonian that can be used for further minimization.
"""
d
=
a
*
xi
...
...
@@ -72,7 +72,7 @@ def make_adjust_variances(a,
if
scaling
is
not
None
:
x
=
ScalingOperator
(
scaling
,
x
.
target
)(
x
)
return
Hamiltonian
(
InverseGammaLikelihood
(
d_eval
)(
x
),
ic_samp
=
ic_samp
)
return
Standard
Hamiltonian
(
InverseGammaLikelihood
(
d_eval
)(
x
),
ic_samp
=
ic_samp
)
def
do_adjust_variances
(
position
,
...
...
nifty5/minimization/
kl_energy
.py
→
nifty5/minimization/
metric_gaussian_kl
.py
View file @
00a2a0c5
...
...
@@ -20,31 +20,70 @@ from ..linearization import Linearization
from
..
import
utilities
class
KL_Energy
(
Energy
):
def
__init__
(
self
,
position
,
h
,
nsamp
,
constants
=
[],
constants_samples
=
None
,
gen_mirrored_samples
=
False
,
class
MetricGaussianKL
(
Energy
):
"""Provides the sampled Kullback-Leibler divergence between a distribution
and a Metric Gaussian.
A Metric Gaussian is used to approximate some other distribution.
It is a Gaussian distribution that uses the Fisher Information Metric
of the other distribution at the location of its mean to approximate the
variance. In order to infer the mean, the a stochastic estimate of the
Kullback-Leibler divergence is minimized. This estimate is obtained by
drawing samples from the Metric Gaussian at the current mean.
During minimization these samples are kept constant, updating only the
mean. Due to the typically nonlinear structure of the true distribution
these samples have to be updated by re-initializing this class at some
point. Here standard parametrization of the true distribution is assumed.
Parameters
----------
mean : Field
The current mean of the Gaussian.
hamiltonian : StandardHamiltonian
The StandardHamiltonian of the approximated probability distribution.
n_samples : integer
The number of samples used to stochastically estimate the KL.
constants : list
A list of parameter keys that are kept constant during optimization.
point_estimates : list
A list of parameter keys for which no samples are drawn, but that are
optimized for, corresponding to point estimates of these.
mirror_samples : boolean
Whether the negative of the drawn samples are also used,
as they are equaly legitimate samples. If true, the number of used
samples doubles. Mirroring samples stabilizes the KL estimate as
extreme sample variation is counterbalanced. (default : False)
Notes
-----
For further details see: Metric Gaussian Variational Inference
(in preparation)
"""
def
__init__
(
self
,
mean
,
hamiltonian
,
n_sampels
,
constants
=
[],
point_estimates
=
None
,
mirror_samples
=
False
,
_samples
=
None
):
super
(
KL_Energy
,
self
).
__init__
(
positio
n
)
if
h
.
domain
is
not
positio
n
.
domain
:
super
(
MetricGaussianKL
,
self
).
__init__
(
mea
n
)
if
h
amiltonian
.
domain
is
not
mea
n
.
domain
:
raise
TypeError
self
.
_h
=
h
self
.
_h
amiltonian
=
hamiltonian
self
.
_constants
=
constants
if
constants_sampl
es
is
None
:
constants_sampl
es
=
constants
self
.
_constants_samples
=
constants_sampl
es
if
point_estimat
es
is
None
:
point_estimat
es
=
constants
self
.
_constants_samples
=
point_estimat
es
if
_samples
is
None
:
met
=
h
(
Linearization
.
make_partial_var
(
position
,
constants_sampl
es
,
True
)).
metric
met
=
h
amiltonian
(
Linearization
.
make_partial_var
(
mean
,
point_estimat
es
,
True
)).
metric
_samples
=
tuple
(
met
.
draw_sample
(
from_inverse
=
True
)
for
_
in
range
(
nsamp
))
if
gen_
mirror
ed
_samples
:
for
_
in
range
(
n
_
samp
els
))
if
mirror_samples
:
_samples
+=
tuple
(
-
s
for
s
in
_samples
)
self
.
_samples
=
_samples
self
.
_lin
=
Linearization
.
make_partial_var
(
positio
n
,
constants
)
self
.
_lin
=
Linearization
.
make_partial_var
(
mea
n
,
constants
)
v
,
g
=
None
,
None
for
s
in
self
.
_samples
:
tmp
=
self
.
_h
(
self
.
_lin
+
s
)
tmp
=
self
.
_h
amiltonian
(
self
.
_lin
+
s
)
if
v
is
None
:
v
=
tmp
.
val
.
local_data
[()]
g
=
tmp
.
gradient
...
...
@@ -56,9 +95,9 @@ class KL_Energy(Energy):
self
.
_metric
=
None
def
at
(
self
,
position
):
return
KL_Energy
(
position
,
self
.
_h
,
0
,
self
.
_constants
,
self
.
_constants_samples
,
_samples
=
self
.
_samples
)
return
MetricGaussianKL
(
position
,
self
.
_h
amiltonian
,
0
,
self
.
_constants
,
self
.
_constants_samples
,
_samples
=
self
.
_samples
)
@
property
def
value
(
self
):
...
...
@@ -71,7 +110,8 @@ class KL_Energy(Energy):
def
_get_metric
(
self
):
if
self
.
_metric
is
None
:
lin
=
self
.
_lin
.
with_want_metric
()
mymap
=
map
(
lambda
v
:
self
.
_h
(
lin
+
v
).
metric
,
self
.
_samples
)
mymap
=
map
(
lambda
v
:
self
.
_hamiltonian
(
lin
+
v
).
metric
,
self
.
_samples
)
self
.
_metric
=
utilities
.
my_sum
(
mymap
)
self
.
_metric
=
self
.
_metric
.
scale
(
1.
/
len
(
self
.
_samples
))
...
...
nifty5/operators/block_diagonal_operator.py
View file @
00a2a0c5
...
...
@@ -27,7 +27,7 @@ class BlockDiagonalOperator(EndomorphicOperator):
domain : MultiDomain
Domain and target of the operator.
operators : dict
Dictionary with subdomain names as keys and :class:`LinearOperator`s
Dictionary with subdomain names as keys and :class:`LinearOperator`
s
as items.
"""
def
__init__
(
self
,
domain
,
operators
):
...
...
nifty5/operators/energy_operators.py
View file @
00a2a0c5
...
...
@@ -259,7 +259,7 @@ class BernoulliEnergy(EnergyOperator):
return
v
.
add_metric
(
met
)
class
Hamiltonian
(
EnergyOperator
):
class
Standard
Hamiltonian
(
EnergyOperator
):
"""Computes an information Hamiltonian in its standard form, i.e. with the
prior being a Gaussian with unit covariance.
...
...
@@ -314,13 +314,13 @@ class Hamiltonian(EnergyOperator):
def
__repr__
(
self
):
subs
=
'Likelihood:
\n
{}'
.
format
(
utilities
.
indent
(
self
.
_lh
.
__repr__
()))
subs
+=
'
\n
Prior: Quadratic{}'
.
format
(
self
.
_lh
.
domain
.
keys
())
return
'Hamiltonian:
\n
'
+
utilities
.
indent
(
subs
)
return
'
Standard
Hamiltonian:
\n
'
+
utilities
.
indent
(
subs
)
class
AveragedEnergy
(
EnergyOperator
):
"""Computes Kullback-Leibler (KL) divergence or Gibbs free energies.
A sample-averaged energy, e.g. a
n
Hamiltonian, approximates the relevant
A sample-averaged energy, e.g. a Hamiltonian, approximates the relevant
part of a KL to be used in Variational Bayes inference if the samples are
drawn from the approximating Gaussian:
...
...
test/test_energy_gradients.py
View file @
00a2a0c5
...
...
@@ -69,7 +69,7 @@ def test_hamiltonian_and_KL(field):
field
=
field
.
exp
()
space
=
field
.
domain
lh
=
ift
.
GaussianEnergy
(
domain
=
space
)
hamiltonian
=
ift
.
Hamiltonian
(
lh
)
hamiltonian
=
ift
.
Standard
Hamiltonian
(
lh
)
ift
.
extra
.
check_value_gradient_consistency
(
hamiltonian
,
field
)
S
=
ift
.
ScalingOperator
(
1.
,
space
)
samps
=
[
S
.
draw_sample
()
for
i
in
range
(
3
)]
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment