ChangeLog.md 11.8 KB
Newer Older
1
2
3
Changes since NIFTy 6
=====================

4
5
6
7
8
9
10
11
12
New parametric amplitude model
------------------------------

The `ift.CorrelatedFieldMaker` now features two amplitude models. In addition
to the non-parametric one, one may choose to use a Matern kernel instead. The
method is aptly named `add_fluctuations_matern`. The major advantage of the
parametric model is its more intuitive scaling with the size of the position
space.

13
14
15
CorrelatedFieldMaker interface change
-------------------------------------

16
17
18
19
20
21
22
23
24
25
26
27
28
29
The interface of `ift.CorrelatedFieldMaker` changed and instances of it may now
be instantiated directly without the previously required `make` method. Upon
initialization, no zero-mode must be specified as the normalization for the
different axes of the power respectively amplitude spectrum now only happens
once in the `finalize` method. There is now a new call named
`set_amplitude_total_offset` to set the zero-mode. The method accepts either an
instance of `ift.Operator` or a tuple parameterizing a log-normal parameter.
Methods which require the zero-mode to be set raise a `NotImplementedError` if
invoked prior to having specified a zero-mode.

Furthermore, the interface of `ift.CorrelatedFieldMaker.add_fluctuations`
changed; it now expects the mean and the standard deviation of their various
parameters not as separate arguments but as a tuple. The same applies to all
new and renamed methods of the `CorrelatedFieldMaker` class.
30

31
Furthermore, it is now possible to disable the asperity and the flexibility
Martin Reinecke's avatar
Martin Reinecke committed
32
33
together with the asperity in the correlated field model. Note that disabling
only the flexibility is not possible.
34

35
36
37
38
39
40
Additionally, the parameters `flexibility`, `asperity` and most importantly
`loglogavgslope` refer to the power spectrum instead of the amplitude now.
For existing codes that means that both values in the tuple `loglogavgslope`
and `flexibility` need to be doubled. The transformation of the `asperity`
parameter is nontrivial.

41
42
43
SimpleCorrelatedField
---------------------

Martin Reinecke's avatar
Martin Reinecke committed
44
A simplified version of the correlated field model was introduced which does not
45
allow for multiple power spectra, the presence of a degree of freedom parameter
Martin Reinecke's avatar
Martin Reinecke committed
46
`dofdex`, or `total_N` larger than zero. Except for the above mentioned
47
48
limitations, it is equivalent to `ift.CorrelatedFieldMaker`. Hence, if one
wants to understand the implementation idea behind the model, it is easier to
Martin Reinecke's avatar
Martin Reinecke committed
49
grasp from reading `ift.SimpleCorrelatedField` than from going through
50
51
`ift.CorrelatedFieldMaker`.

Martin Reinecke's avatar
switch    
Martin Reinecke committed
52
53
54
55
56
57
Change in external dependencies
-------------------------------

Instead of the optional external packages `pypocketfft` and `pyHealpix`, NIFTy
now uses the DUCC package (<https://gitlab.mpcdf.mpg.de/mtr/ducc)>,
which is their successor.
58
59


Philipp Arras's avatar
Philipp Arras committed
60
61
62
63
64
65
Naming of operator tests
------------------------

The implementation tests for nonlinear operators are now available in
`ift.extra.check_operator()` and for linear operators
`ift.extra.check_linear_operator()`.
66

67
68
69
MetricGaussianKL interface
--------------------------

Philipp Frank's avatar
Philipp Frank committed
70
71
72
73
74
75
76
`mirror_samples` is not set by default anymore.


GeoMetricKL
-----------

A new posterior approximation scheme, called geometric Variational Inference
Philipp Arras's avatar
Philipp Arras committed
77
78
79
80
(geoVI) was introduced. `GeoMetricKL` extends `MetricGaussianKL` in the sense
that it uses (non-linear) geoVI samples instead of (linear) MGVI samples.
`GeoMetricKL` can be configured such that it reduces to `MetricGaussianKL`.
`GeoMetricKL` is now used in `demos/getting_started_3.py` and a visual
Philipp Frank's avatar
Philipp Frank committed
81
82
comparison to MGVI can be found in `demos/variational_inference_visualized.py`.
For further details see (<https://arxiv.org/abs/2105.10470>).
Philipp Frank's avatar
Philipp Frank committed
83
84


Philipp Arras's avatar
Philipp Arras committed
85
86
87
88
89
90
91
92
93
LikelihoodEnergyOperator
------------------------

A new subclass of `EnergyOperator` was introduced and all `EnergyOperator`s that
are likelihoods are now `LikelihoodEnergyOperator`s. A
`LikelihoodEnergyOperator` has to implement the function `get_transformation`,
which returns a coordinate transformation in which the Fisher metric of the
likelihood becomes the identity matrix. This is needed for the `GeoMetricKL`
algorithm.
94
95


Philipp Arras's avatar
Philipp Arras committed
96
97
98
99
100
101
102
Remove gitversion interface
---------------------------

Since we provide proper nifty releases on PyPI now, the gitversion interface is
not supported any longer.


103
104
Changes since NIFTy 5
=====================
Martin Reinecke's avatar
Martin Reinecke committed
105

Martin Reinecke's avatar
Martin Reinecke committed
106
Minimum Python version increased to 3.6
107
---------------------------------------
Martin Reinecke's avatar
Martin Reinecke committed
108
109


110
New operators
111
-------------
112
113
114
115
116
117
118
119
120
121

In addition to the below changes, the following operators were introduced:

* UniformOperator: Transforms a Gaussian into a uniform distribution
* VariableCovarianceGaussianEnergy: Energy operator for inferring covariances
* MultiLinearEinsum: Multi-linear version of numpy's einsum with derivates
* LinearEinsum: Linear version of numpy's einsum with one free field
* PartialConjugate: Conjugates parts of a multi-field
* SliceOperator: Geometry preserving mask operator
* SplitOperator: Splits a single field into a multi-field
122
* MatrixProductOperator: Applies matrices (scipy.sparse, numpy) to fields
123
* IntegrationOperator: Integrates over subspaces of fields
124

Martin Reinecke's avatar
Martin Reinecke committed
125
FFT convention adjusted
126
-----------------------
Martin Reinecke's avatar
Martin Reinecke committed
127
128
129
130
131

When going to harmonic space, NIFTy's FFT operator now uses a minus sign in the
exponent (and, consequently, a plus sign on the adjoint transform). This
convention is consistent with almost all other numerical FFT libraries.

Martin Reinecke's avatar
Martin Reinecke committed
132
Interface change in EndomorphicOperator.draw_sample()
133
-----------------------------------------------------
Martin Reinecke's avatar
Martin Reinecke committed
134

Philipp Arras's avatar
Philipp Arras committed
135
Both complex-valued and real-valued Gaussian probability distributions have
Martin Reinecke's avatar
Martin Reinecke committed
136
Hermitian and positive endomorphisms as covariance. Just by looking at an
Philipp Arras's avatar
Philipp Arras committed
137
138
139
140
141
142
endomorphic operator itself it is not clear whether it is viewed as covariance
for real or complex Gaussians when a sample of the respective distribution shall
be drawn. Therefore, we introduce the method `draw_sample_with_dtype()` which
needs to be given the data type of the probability distribution. This function
is implemented for all operators which actually draw random numbers
(`DiagonalOperator` and `ScalingOperator`). The class `SamplingDtypeSetter` acts
Martin Reinecke's avatar
Martin Reinecke committed
143
as a wrapper for this kind of operators in order to fix the data type of the
Philipp Arras's avatar
Philipp Arras committed
144
145
146
147
148
distribution. Samples from these operators can be drawn with `.draw_sample()`.
In order to dive into those subtleties I suggest running the following code and
playing around with the dtypes.

```
Martin Reinecke's avatar
Martin Reinecke committed
149
import nifty7 as ift
Philipp Arras's avatar
Philipp Arras committed
150
151
152
153
154
import numpy as np

dom = ift.UnstructuredDomain(5)
dtype = [np.float64, np.complex128][1]
invcov = ift.ScalingOperator(dom, 3)
Martin Reinecke's avatar
Martin Reinecke committed
155
e = ift.GaussianEnergy(mean=ift.from_random(dom, 'normal', dtype=dtype),
Philipp Arras's avatar
Philipp Arras committed
156
                       inverse_covariance=invcov)
Martin Reinecke's avatar
Martin Reinecke committed
157
pos = ift.from_random(dom, 'normal', dtype=np.complex128)
Philipp Arras's avatar
Philipp Arras committed
158
159
160
161
162
lin = e(ift.Linearization.make_var(pos, want_metric=True))
met = lin.metric
print(met)
print(met.draw_sample())
```
Martin Reinecke's avatar
Martin Reinecke committed
163

164
165
166
167
168
169
New approach for sampling complex numbers
=========================================

When calling draw_sample_with_dtype with a complex dtype,
the variance is now used for the imaginary part and real part separately.
This is done in order to be consistent with the Hamiltonian.
170
Note that by this,
171
172
```
np.std(ift.from_random(domain, 'normal', dtype=np.complex128).val)
173
````
174
175
176
does not give 1, but sqrt(2) as a result.


Philipp Arras's avatar
Philipp Arras committed
177
MPI parallelisation over samples in MetricGaussianKL
178
----------------------------------------------------
Philipp Arras's avatar
Philipp Arras committed
179
180
181
182

The classes `MetricGaussianKL` and `MetricGaussianKL_MPI` have been unified
into one `MetricGaussianKL` class which has MPI support built in.

Martin Reinecke's avatar
Martin Reinecke committed
183
New approach for random number generation
184
-----------------------------------------
Martin Reinecke's avatar
Martin Reinecke committed
185
186
187
188
189

The code now uses `numpy`'s new `SeedSequence` and `Generator` classes for the
production of random numbers (introduced in numpy 1.17. This greatly simplifies
the generation of reproducible random numbers in the presence of MPI parallelism
and leads to cleaner code overall. Please see the documentation of
Martin Reinecke's avatar
Martin Reinecke committed
190
`nifty7.random` for details.
Martin Reinecke's avatar
Martin Reinecke committed
191

192

Rouven Lemmerz's avatar
Rouven Lemmerz committed
193
Interface Change for from_random and OuterProduct
194
-------------------------------------------------
Rouven Lemmerz's avatar
Rouven Lemmerz committed
195
196
197
198
199

The sugar.from_random, Field.from_random, MultiField.from_random now take domain
as the first argument and default to 'normal' for the second argument.
Likewise OuterProduct takes domain as the first argument and a field as the second.

Philipp Arras's avatar
Philipp Arras committed
200
Interface Change for non-linear Operators
201
-----------------------------------------
Philipp Arras's avatar
Philipp Arras committed
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216

The method `Operator.apply()` takes a `Linearization` or a `Field` or a
`MultiField` as input. This has not changed. However, now each non-linear
operator assumes that the input `Linearization` comes with an identity operator
as jacobian. Also it is assumed that the `apply()` method returns a
`Linearization` with the jacobian of the operator itself. The user is not in
charge anymore of stacking together the jacobians of operator chains. Something
like `x.jac` should not appear in any self-written `apply()` methods. The method
`Operator._check_input` tests if this condition is met. The same goes for the
metric. There is no need anymore to call `SandwichOperator` in an `apply()`
method when implementing new energies. This change should not lead to unexpected
behaviour since both `Operator._check_input()` and
`extra.check_jacobian_consistency()` tests for the new conditions to be
fulfilled.

Martin Reinecke's avatar
Martin Reinecke committed
217
Special functions for complete Field reduction operations
218
---------------------------------------------------------
Martin Reinecke's avatar
Martin Reinecke committed
219
220
221
222
223
224
225
226
227
228

So far, reduction operations called on Fields (like `vdot`, `sum`, `integrate`,
`mean`, `var`, `std`, `prod` etc.) returned a scalar when the reduction was
carried out over all domains, and otherwise a `Field`.
Having the data type of the returned value depend on input parameters is
extremely confusing, so all of these reduction operations now always return a
Field. We also introduced another set of reduction operations which always
operate over all subdomains and therefore don't take a `spaces` argument; they
are named `s_vdot`, `s_sum` etc. and always return a scalar.

229
Updates regarding correlated fields
230
-----------------------------------
231
232
233
234
235
236
237
238
239
240
241
242
243
244

The most commonly used model for homogeneous and isotropic correlated fields in
nifty5 has been `SLAmplitude` combined with `CorrelatedField`. This model
exhibits unintuitive couplings between its parameters and as been replaced
by `CorrelatedFieldMaker` in NIFTy 6. This model aims to conceptionally provide
the same functionality. However, internally it works quite differently. Therefore,
specific classes for `SLAmplitude` like `LogRGSpace`, `QHTOperator`, `ExpTransform`,
`SlopeOperator`, `SymmetrizingOperator`, `CepstrumOperator`, `CorrelatedField`
and `MfCorrelatedField` are not needed anymore and have been removed. In general,
`CorrelatedFieldMaker` feels to be better conditioned leading to faster convergence
but it is hard to make explicit tests since the two approaches cannot be mapped
onto each other exactly. We experienced that preconditioning in the `MetricGaussianKL`
via `napprox` breaks the inference scheme with the new model so `napprox` may not
be used here.
Martin Reinecke's avatar
merge    
Martin Reinecke committed
245

Lukas Platz's avatar
Lukas Platz committed
246
Removal of the standard MPI parallelization scheme:
247
---------------------------------------------------
Martin Reinecke's avatar
Martin Reinecke committed
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264

When several MPI tasks are present, NIFTy5 distributes every Field over these
tasks by splitting it along the first axis. This approach to parallelism is not
very efficient, and it has not been used by anyone for several years, so we
decided to remove it, which led to many simplifications within NIFTy.
User-visible changes:
- the methods `to_global_data`, `from_global_data`, `from_local_data` and
  the property `local_data` have been removed from `Field` and `MultiField`.
  Instead there are now the property `val` (returning a read-only numpy.ndarray
  for `Field` and a dictionary of read-only numpy.ndarrays for `MultiField`) and
  the method `val_rw()` (returning the same structures with writable copies of
  the arrays). Fields and MultiFields can be created from such structures using
  the static method `from_raw`
- the functions `from_global_data` and `from_local_data` in `sugar` have been
  replaced by a single function called `makeField`
- the property `local_shape` has been removed from `Domain` (and subclasses)
  and `DomainTuple`.