Commit 14052dd3 authored by Philipp Haim's avatar Philipp Haim
Browse files

Merge branch 'normalized_amplitudes_DomT' into 'normalized_amplitudes_pp'

Correlated Field model for DomainTuple

See merge request !373
parents 5bc51e4b 5e2ea82e
Pipeline #64380 passed with stages
in 8 minutes and 51 seconds
...@@ -19,7 +19,6 @@ from .multi_field import MultiField ...@@ -19,7 +19,6 @@ from .multi_field import MultiField
from .operators.operator import Operator from .operators.operator import Operator
from .operators.adder import Adder from .operators.adder import Adder
from .operators.log1p import Log1p
from .operators.diagonal_operator import DiagonalOperator from .operators.diagonal_operator import DiagonalOperator
from .operators.distributors import DOFDistributor, PowerDistributor from .operators.distributors import DOFDistributor, PowerDistributor
from .operators.domain_tuple_field_inserter import DomainTupleFieldInserter from .operators.domain_tuple_field_inserter import DomainTupleFieldInserter
......
...@@ -32,7 +32,7 @@ __all__ = ["ntask", "rank", "master", "local_shape", "data_object", "full", ...@@ -32,7 +32,7 @@ __all__ = ["ntask", "rank", "master", "local_shape", "data_object", "full",
"redistribute", "default_distaxis", "is_numpy", "absmax", "norm", "redistribute", "default_distaxis", "is_numpy", "absmax", "norm",
"lock", "locked", "uniform_full", "transpose", "to_global_data_rw", "lock", "locked", "uniform_full", "transpose", "to_global_data_rw",
"ensure_not_distributed", "ensure_default_distributed", "ensure_not_distributed", "ensure_default_distributed",
"tanh", "conjugate", "sin", "cos", "tan", "log10", "tanh", "conjugate", "sin", "cos", "tan", "log10", "log1p", "expm1",
"sinh", "cosh", "sinc", "absolute", "sign", "clip"] "sinh", "cosh", "sinc", "absolute", "sign", "clip"]
_comm = MPI.COMM_WORLD _comm = MPI.COMM_WORLD
...@@ -297,7 +297,8 @@ def _math_helper(x, function, out): ...@@ -297,7 +297,8 @@ def _math_helper(x, function, out):
_current_module = sys.modules[__name__] _current_module = sys.modules[__name__]
for f in ["sqrt", "exp", "log", "tanh", "conjugate", "sin", "cos", "tan", for f in ["sqrt", "exp", "log", "tanh", "conjugate", "sin", "cos", "tan",
"sinh", "cosh", "sinc", "absolute", "sign", "log10"]: "sinh", "cosh", "sinc", "absolute", "sign", "log10", "log1p",
"expm1"]:
def func(f): def func(f):
def func2(x, out=None): def func2(x, out=None):
return _math_helper(x, f, out) return _math_helper(x, f, out)
...@@ -396,6 +397,8 @@ def from_global_data(arr, sum_up=False, distaxis=0): ...@@ -396,6 +397,8 @@ def from_global_data(arr, sum_up=False, distaxis=0):
raise TypeError raise TypeError
if sum_up: if sum_up:
arr = np_allreduce_sum(arr) arr = np_allreduce_sum(arr)
if arr.ndim == 0:
distaxis = -1
if distaxis == -1: if distaxis == -1:
return data_object(arr.shape, arr, distaxis) return data_object(arr.shape, arr, distaxis)
lo, hi = _shareRange(arr.shape[distaxis], ntask, rank) lo, hi = _shareRange(arr.shape[distaxis], ntask, rank)
......
...@@ -22,7 +22,7 @@ from numpy import ndarray as data_object ...@@ -22,7 +22,7 @@ from numpy import ndarray as data_object
from numpy import empty, empty_like, ones, zeros, full from numpy import empty, empty_like, ones, zeros, full
from numpy import absolute, sign, clip, vdot from numpy import absolute, sign, clip, vdot
from numpy import sin, cos, sinh, cosh, tan, tanh from numpy import sin, cos, sinh, cosh, tan, tanh
from numpy import exp, log, log10, sqrt, sinc from numpy import exp, log, log10, sqrt, sinc, log1p, expm1
from .random import Random from .random import Random
...@@ -35,8 +35,8 @@ __all__ = ["ntask", "rank", "master", "local_shape", "data_object", "full", ...@@ -35,8 +35,8 @@ __all__ = ["ntask", "rank", "master", "local_shape", "data_object", "full",
"redistribute", "default_distaxis", "is_numpy", "absmax", "norm", "redistribute", "default_distaxis", "is_numpy", "absmax", "norm",
"lock", "locked", "uniform_full", "to_global_data_rw", "lock", "locked", "uniform_full", "to_global_data_rw",
"ensure_not_distributed", "ensure_default_distributed", "ensure_not_distributed", "ensure_default_distributed",
"clip", "sin", "cos", "tan", "sinh", "clip", "sin", "cos", "tan", "sinh", "cosh",
"cosh", "absolute", "sign", "sinc", "log10"] "absolute", "sign", "sinc", "log10", "log1p", "expm1"]
ntask = 1 ntask = 1
rank = 0 rank = 0
......
...@@ -663,9 +663,8 @@ for op in ["__iadd__", "__isub__", "__imul__", "__idiv__", ...@@ -663,9 +663,8 @@ for op in ["__iadd__", "__isub__", "__imul__", "__idiv__",
return func2 return func2
setattr(Field, op, func(op)) setattr(Field, op, func(op))
for f in ["sqrt", "exp", "log", "log10", "tanh", for f in ["sqrt", "exp", "log", "sin", "cos", "tan", "sinh", "cosh", "tanh",
"sin", "cos", "tan", "cosh", "sinh", "absolute", "sinc", "sign", "log10", "log1p", "expm1"]:
"absolute", "sinc", "sign"]:
def func(f): def func(f):
def func2(self): def func2(self):
return Field(self._domain, getattr(dobj, f)(self.val)) return Field(self._domain, getattr(dobj, f)(self.val))
......
This diff is collapsed.
...@@ -335,6 +335,16 @@ class Linearization(object): ...@@ -335,6 +335,16 @@ class Linearization(object):
tmp2 = 1. / (self._val * np.log(10)) tmp2 = 1. / (self._val * np.log(10))
return self.new(tmp, makeOp(tmp2)(self._jac)) return self.new(tmp, makeOp(tmp2)(self._jac))
def log1p(self):
tmp = self._val.log1p()
tmp2 = 1. / (1. + self._val)
return self.new(tmp, makeOp(tmp2)(self.jac))
def expm1(self):
tmp = self._val.expm1()
tmp2 = self._val.exp()
return self.new(tmp, makeOp(tmp2)(self.jac))
def sinh(self): def sinh(self):
tmp = self._val.sinh() tmp = self._val.sinh()
tmp2 = self._val.cosh() tmp2 = self._val.cosh()
......
...@@ -338,7 +338,7 @@ for op in ["__iadd__", "__isub__", "__imul__", "__idiv__", ...@@ -338,7 +338,7 @@ for op in ["__iadd__", "__isub__", "__imul__", "__idiv__",
setattr(MultiField, op, func(op)) setattr(MultiField, op, func(op))
for f in ["sqrt", "exp", "log", "tanh"]: for f in ["sqrt", "exp", "log", "log1p", "expm1", "tanh"]:
def func(f): def func(f):
def func2(self): def func2(self):
fu = getattr(Field, f) fu = getattr(Field, f)
......
...@@ -24,20 +24,21 @@ from .linear_operator import LinearOperator ...@@ -24,20 +24,21 @@ from .linear_operator import LinearOperator
class ContractionOperator(LinearOperator): class ContractionOperator(LinearOperator):
"""A :class:`LinearOperator` which sums up fields into the direction of """A :class:`LinearOperator` which sums up fields into the direction of
subspaces. subspaces.
This Operator sums up a field with is defined on a :class:`DomainTuple` This Operator sums up a field with is defined on a :class:`DomainTuple`
to a :class:`DomainTuple` which contains the former as a subset. to a :class:`DomainTuple` which is a subset of the former.
Parameters Parameters
---------- ----------
domain : Domain, tuple of Domain or DomainTuple domain : Domain, tuple of Domain or DomainTuple
spaces : int or tuple of int spaces : None, int or tuple of int
The elements of "domain" which are contracted. The elements of "domain" which are contracted.
If `None`, everything is contracted
weight : int, default=0 weight : int, default=0
If nonzero, the fields defined on self.domain are weighted with the If nonzero, the fields defined on self.domain are weighted with the
specified power. specified power along the submdomains which are contracted.
""" """
def __init__(self, domain, spaces, weight=0): def __init__(self, domain, spaces, weight=0):
......
...@@ -250,20 +250,18 @@ class InverseGammaLikelihood(EnergyOperator): ...@@ -250,20 +250,18 @@ class InverseGammaLikelihood(EnergyOperator):
class StudentTEnergy(EnergyOperator): class StudentTEnergy(EnergyOperator):
"""Computes likelihood energy of expected event frequency constrained by """Computes likelihood energy corresponding to Student's t-distribution.
event data.
.. math :: .. math ::
E(f) = -\\log \\text{Bernoulli}(d|f) E_\\theta(f) = -\\log \\text{StudentT}_\\theta(f)
= -d^\\dagger \\log f - (1-d)^\\dagger \\log(1-f), = \\frac{\\theta + 1}{2} \\log(1 + \\frac{f^2}{\\theta}),
where f is a field defined on `d.domain` with the expected where f is a field defined on `domain`.
frequencies of events.
Parameters Parameters
---------- ----------
d : Field domain : `Domain` or `DomainTuple`
Data field with events (1) or non-events (0). Domain of the operator
theta : Scalar theta : Scalar
Degree of freedom parameter for the student t distribution Degree of freedom parameter for the student t distribution
""" """
...@@ -271,12 +269,10 @@ class StudentTEnergy(EnergyOperator): ...@@ -271,12 +269,10 @@ class StudentTEnergy(EnergyOperator):
def __init__(self, domain, theta): def __init__(self, domain, theta):
self._domain = DomainTuple.make(domain) self._domain = DomainTuple.make(domain)
self._theta = theta self._theta = theta
from .log1p import Log1p
self._l1p = Log1p(domain)
def apply(self, x): def apply(self, x):
self._check_input(x) self._check_input(x)
v = ((self._theta+1)/2)*self._l1p(x**2/self._theta).sum() v = ((self._theta+1)/2)*(x**2/self._theta).log1p().sum()
if not isinstance(x, Linearization): if not isinstance(x, Linearization):
return Field.scalar(v) return Field.scalar(v)
if not x.want_metric: if not x.want_metric:
......
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Copyright(C) 2013-2019 Max-Planck-Society
#
# NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik.
from ..field import Field
from ..multi_field import MultiField
from .operator import Operator
from .diagonal_operator import DiagonalOperator
from ..linearization import Linearization
from ..sugar import from_local_data
from numpy import log1p
class Log1p(Operator):
"""computes x -> log(1+x)
"""
def __init__(self, dom):
self._domain = dom
self._target = dom
def apply(self, x):
lin = isinstance(x, Linearization)
xval = x.val if lin else x
xlval = xval.local_data
res = from_local_data(xval.domain, log1p(xlval))
if not lin:
return res
jac = DiagonalOperator(1/(1+xval))
return x.new(res, jac@x.jac)
...@@ -391,7 +391,7 @@ _current_module = sys.modules[__name__] ...@@ -391,7 +391,7 @@ _current_module = sys.modules[__name__]
for f in ["sqrt", "exp", "log", "log10", "tanh", "sigmoid", for f in ["sqrt", "exp", "log", "log10", "tanh", "sigmoid",
"conjugate", 'sin', 'cos', 'tan', 'sinh', 'cosh', "conjugate", 'sin', 'cos', 'tan', 'sinh', 'cosh',
'absolute', 'one_over', 'sinc']: 'absolute', 'one_over', 'sinc', 'log1p', 'expm1']:
def func(f): def func(f):
def func2(x): def func2(x):
from .linearization import Linearization from .linearization import Linearization
...@@ -424,14 +424,17 @@ def get_default_codomain(domainoid, space=None): ...@@ -424,14 +424,17 @@ def get_default_codomain(domainoid, space=None):
codomain. `domain[space]` must be of class `RGSpace`. codomain. `domain[space]` must be of class `RGSpace`.
""" """
from .domains.rg_space import RGSpace from .domains.rg_space import RGSpace
from .domains.hp_space import HPSpace
from .domains.gl_space import GLSpace
from .domains.lm_space import LMSpace
if isinstance(domainoid, RGSpace): if isinstance(domainoid, RGSpace):
return domainoid.get_default_codomain() return domainoid.get_default_codomain()
if not isinstance(domainoid, DomainTuple): if not isinstance(domainoid, DomainTuple):
raise TypeError( raise TypeError(
'Works only on RGSpaces and DomainTuples containing those') 'Works only on RGSpaces and DomainTuples containing those')
space = utilities.infer_space(domainoid, space) space = utilities.infer_space(domainoid, space)
if not isinstance(domainoid[space], RGSpace): if not isinstance(domainoid[space], (RGSpace, HPSpace, GLSpace, LMSpace)):
raise TypeError("can only codomain RGSpaces") raise TypeError("can only codomain structrued spaces")
ret = [dom for dom in domainoid] ret = [dom for dom in domainoid]
ret[space] = domainoid[space].get_default_codomain() ret[space] = domainoid[space].get_default_codomain()
return DomainTuple.make(ret) return DomainTuple.make(ret)
......
...@@ -54,7 +54,7 @@ def test_special_gradients(): ...@@ -54,7 +54,7 @@ def test_special_gradients():
@pmp('f', [ @pmp('f', [
'log', 'exp', 'sqrt', 'sin', 'cos', 'tan', 'sinc', 'sinh', 'cosh', 'tanh', 'log', 'exp', 'sqrt', 'sin', 'cos', 'tan', 'sinc', 'sinh', 'cosh', 'tanh',
'absolute', 'one_over', 'sigmoid', 'log10' 'absolute', 'one_over', 'sigmoid', 'log10', 'log1p', "expm1"
]) ])
def test_actual_gradients(f): def test_actual_gradients(f):
dom = ift.UnstructuredDomain((1,)) dom = ift.UnstructuredDomain((1,))
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment